To save content items to your account,
please confirm that you agree to abide by our usage policies.
If this is the first time you use this feature, you will be asked to authorise Cambridge Core to connect with your account.
Find out more about saving content to .
To save content items to your Kindle, first ensure no-reply@cambridge.org
is added to your Approved Personal Document E-mail List under your Personal Document Settings
on the Manage Your Content and Devices page of your Amazon account. Then enter the ‘name’ part
of your Kindle email address below.
Find out more about saving to your Kindle.
Note you can select to save to either the @free.kindle.com or @kindle.com variations.
‘@free.kindle.com’ emails are free but can only be saved to your device when it is connected to wi-fi.
‘@kindle.com’ emails can be delivered even when you are not connected to wi-fi, but note that service fees apply.
In Chapter 6 we presented the basic techniques for loading image files into applets and applications. We used instances of the Image class to hold images and invoked the drawImage() method in the Graphics class to display them. In this chapter we explore further the image handling and processing capabilities of Java.
In the first few sections we look in greater detail at the Image class and introduce its BufferedImage subclass, which offers many useful features. We discuss how to monitor the loading of images, how to scale image displays, how to create images, and how to save images to files.
We then switch to topics related to image processing. We show how to gain access to the pixels of an image, how to modify them, how to make an image from a pixel array, and how to use these techniques to create animations. We then discuss the standard filters provided with Java 2D and also give an example of a custom filter.
We give only a brief overview of the wide range of image tools available with Java. The classes mentioned here, for example, hold many overloaded constructors and methods that provide many options. See the Java 2 API Specifications for thorough descriptions of the classes. Also, see the book by Knudsen [1] and the other resources for in-depth discussions of images in Java [2, 3].
In Part I of this book and Web Course we tried to provide an introduction to the essential elements of the Java language that allow you to begin creating useful programs in short order. In this chapter we discuss several practical techniques that will expand the capabilities of your programs. We begin with a discussion of how to print your graphics displays and then discuss several user interface features such as cursor icons and popup menus, handling keystrokes, and audio. We also review various ways to improve the speed of Java programs.
Printing
Java 1.1 provided the capability to print what is displayed on a Java component [1]. Java 1.2 added Java 2D, which expanded the print capabilities to support greater control over multiple page printing and other features. (We should point out that printing only works with applications since the SecurityManager in browser JVMs blocks printing from applets.)
In Java graphics the usual job of the paint() method in AWT and the paintComponent() method in Swing is to send drawing commands to the monitor screen. Java printing simply entails sending drawing commands to the printer instead of the monitor screen. In rendering Java components, we have seen that a Graphics context object is passed to the paint() and paintComponent() methods. To render to the printer, you obtain an instance of PrintGraphics, which is a subclass of Graphics, and pass it to the paint() or paintComponent() method.
Chapter 16 introduced distributed computing, the UML notation language, and the design of the server side of a client/server application. Chapter 17 described the client side. Before beginning an actual implementation, it was necessary to describe Java RMI in Chapter 18. Then we took a brief detour in Chapter 19 to describe CORBA as an alternative to RMI. Now that we have all the pieces, we can put them together to build a simple example of a distributed computing application in which the calculation engine is implemented completely in Java. If the calculation engine involves legacy code in a language other than Java, then we must use JNI (the Java Native Interface, which is described in Chapter 22).
The sample application
A real client/server application using the design of Chapters 16 and 17 will be more complex than the sample described here. In fact, if the application were not somewhat complex, there would be little reason to implement it in a client/server design in the first place! However, for the sake of demonstration purposes and to provide a template for the reader's own applications, we provide a simple application that illustrates the important features of the client/server design presented in Chapters 16 and 17.
Recall that the client/server system designed earlier assumed a time-dependent simulation – i.e. one with a solution that varies as a function of time. The same approach could also work with monitoring and controlling a real system such as a remote sensor.
Chapter 20 developed a complete client/server application in which both the client code and the server-side code were implemented completely in Java. Pure Java on the client side is desirable for many reasons – platform portability, rich user interface, object-oriented programming environment, ability to run as an application, an applet or a Java Web Start application, etc. For many of the same reasons, a pure Java server offers obvious advantages too. However, for some calculation-intensive processing tasks, particularly if legacy code in another language already exists, it can be advantageous for a Java program to gain access to code written in another language such as C or Fortran.
Java permits calls to code written in languages other than Java. Such external languages are referred to as “native” languages, and the API for accessing them is called the Java Native Interface, or JNI [1]. The decision to use JNI should be made with great care. JNI is designed for use when it is necessary to take advantage of platform-specific functionality that is not available within the Java Virtual Machine. There are two key concepts in that previous sentence – necessary and platform-specific functionality. To utilize platform-specific functionality via JNI obviously removes Java's platform portability. In fact, any use of JNI at all renders a Java application no longer platform portable since the Java application requires a native shared object library for each platform to which it is targeted.
Java provides a consistent framework for all input/output. That framework centers on the concept of a stream. A stream in Java is a sequential flow of bytes in one direction. There is an output stream that carries text to the console and a corresponding input stream that brings text from the keyboard. Another type of output stream carries data to a file, and a corresponding input stream brings data into a program from a file. There is another output stream that sends data through a network port to another computer on the network while an input stream brings in data through a network port from such a source.
The bulk of Java I/O classes belong to the java.io package. (See pediagram in Figure 9.1.) The class hierarchy builds on the base classes InputStream, OutputStream, Reader, and Writer to provide a wide range of input and output tasks. In addition, this package holds stream classes that wrap a stream to add more capabilities to it. Some I/O classes provide a destination or source, such as a file or an array. Others process the stream in some way such as buffering or filtering the data.
Packages involving I/O include:
java.io – the primary Java I/O classes
java.nio, java.nio.* – a set of five packages new with Java 1.4 based on the concept of channels that represent an open connection to a hardware device, file, or other entity. Channels don't supplant streams but rather work with them to add additional capabilities and enhanced scaling when working with large numbers of connections
In Chapter 14 we showed how to build a basic web server that sends files to browsers or to browser-like clients. In this chapter we present a more interesting socket-based client/server demonstration system that goes beyond just transmission of web pages. This new server sends data to a client, which then displays the data in histograms. This type of client/server system could be quite useful in various applications such as transmitting data from a remote experiment, running diagnostics under the direction of a client, installing calibration settings, and controlling an instrument remotely. For demonstration purposes, our server generates simulated data.
As in Chapter 14 we use sockets for our client/server communications [1–3]. Later chapters present RMI and CORBA based approaches. In a step-by-step manner we describe the concepts and the code techniques used in the client and server demonstration programs.
The client/server design
For the web server discussed in Chapter 14 we used socket communications. The server monitors a port with a ServerSocket, which returns a socket for a client whenever one requests a connection. The socket is passed to a thread that receives a request from the client for a file and then transmits that file if it is available. The server then breaks the connection and the session ends.
We can, however, create a client/server system in which the server maintains a connection for as long as the client desires.
Over the last few years, a new distributed computing technology based on the now-ubiquitous World Wide Web and known as web services has become very popular. In this chapter we introduce web services and briefly discuss how the technology can be used in a scientific application. We also introduce the closely-related Extensible Markup Language (XML). These are both large subjects. A full treatment is outside the scope of this book, but this chapter is designed to give the interested reader enough basic information to get started and pointers on where to look for more.
Introducing web services for distributed computing
We have already learned about distributed computing in the abstract sense using UML in Chapters 16 and 17. And we've learned concrete implementations using Java RMI in Chapters 18 and 20 and CORBA in Chapter 19. Both RMI and CORBA are technologies invented to implement distributed computing. One can think of both as transport mechanisms used to move data and, at least in the case of RMI, objects from clients to servers and back. There are other technologies for distributed computing as well, such as the low-level socket based networking technologies discussed in Chapters 14 and 15, and higher-level proprietary single-platform technologies, particularly Microsoft® products, that are not of interest to this book. Web services offer another alternative technology for distributed computing.
Chapter 16 introduced distributed computing and enough UML to describe server-side interactions. In this chapter we describe the design of the client for a distributed scientific application in which the computationally intense calculations are performed on a remote server. Like the server, the client details necessarily depend heavily on the calculation being performed and the data that is to be presented to the user. Nevertheless we can provide some general guidelines that should apply to many scientific applications.
Multithreaded client
Recall that the server in Chapter 16 is running on a remote machine, at least conceptually, and is generating results continuously as the simulation is running. To avoid problems with intervening firewalls, we designed the server to be polled by the client rather than using a callback from the server to the client when new data is available. That is, the client must poll the server periodically to retrieve the results being calculated by the server. Assuming that the server calculation is generating results somewhat uniformly, we clearly would prefer for the client to poll the server on a regular basis. Meanwhile, once the client receives the current set of results, the client must display them to the user in some fashion and allow the user to interact with the displayed data. Whenever human users are involved, one can be assured that the user's actions will not be uniform and regular.
If you buy one of those do-it-yourself furniture kits, the best way to start is to just dump all of those screws, nuts, planks, tools and other odd looking widgets on the floor, group them into piles of similar looking items, and then go read the instructions. Even if you don't know what all of those widgets are for, it helps to pick them up and look them over so that you become familiar with them and can recognize them in the instructions.
So rather than dribbling them out over several chapters, here we dump out most of the basic widgets needed to construct Java programs. The goal is to start to become familiar with Java's symbols, keywords, operators, expressions, and other building blocks of the language with which to construct programs. We provide examples and starter programs (on the Web Course) that allow you to begin to write programs without needing to understand yet all of these language elements at a deep level. You should refer back to this chapter as you proceed and as your understanding of the language increases.
Note that in this chapter we occasionally mention the terms class, method, and object. If you are new to object-oriented programming, do not worry about these terms for now. We discuss them in detail in the following chapters.
We begin with a listing of the basic elements and then outline the structure of a generic program.
Java arrived on the scene just as computer networking was expanding from isolated local area networks outward to the whole world via the Internet. The developers of Java quickly realized that exploiting the vast potential of networks would become a major activity for programmers in this new interconnected world, so they built a wide array of networking capabilities into the language. This capability grew with each new version of Java and became one of the primary reasons for its popularity.
In this chapter we review the basics of TCP/IP (Internet) networking and some of the tools that Java provides to exploit it [1, 2]. In the rest of Part II we examine many of the more sophisticated networking capabilities of Java with an emphasis on how they could benefit scientific and engineering applications.
Internet basics
As shown in Figure 13.1, networking architecture is based on the concept of layers of protocols. (The more formal OSI – Open System Interconnection – model has seven layers but this one shows the essential layer definitions.) Each layer has its own standardized protocol and standardized application programming interface (API), which allows the next higher layer to communicate with it. Internally, the layers can be implemented in different ways as long as they provide the standard API. For example, the Network layer does not know if the physical layer is Ethernet or a wireless system because the software device drivers respond to the function calls the same way.
In this chapter we look first at several topics related to the organization of Java files. In fact, a scheme for organizing Java files and classes comes built into the language. When a class is used, the name of the class includes, either explicitly or implicitly (via the import directive), its location in a particular package. The Java package resembles the code libraries of other languages and provides a name space that successfully avoids name collisions. In practice, a large class library will contain many packages – the J2SE 1.4 class library contains over 100 separate packages – arranged in some sensible order. A very small, single-purpose library might reside entirely in just one package.
In some of the examples in previous chapters the code included the public modifier. We finally explain in this chapter exactly what that modifier does. It and the other access modifiers determine what classes, methods and fields can be used by methods in other classes and subclasses, in the same and in other packages.
For faster downloading, you can pack your Java packages, classes, images, audio files and other program resources into a single file called a JAR (Java Archive) file. JAR files use the ZIP format and compression system (a variation of Lempel-Ziv) to hold files and to maintain internally a hierarchical directory system like that on disk. We show how to create JAR files and how to extract files from them.
A web server program runs continuously while waiting for and answering requests it receives over the Internet from browsers. Typically the requestor asks for the transmission of a web page in HTML (Hypertext Markup Language) format or asks for some other HTTP (Hypertext Transmission Protocol) service such as the running of a CGI (Common Gateway Interface) program.
Developing web servers and server applications such as online stores became the first big money-making business area that used Java extensively. Sun offers additional packages with the Java 2 Platform Enterprise Edition (J2EE) to support server development for applications such as database access, shopping cart systems for web stores, and other elaborate middleware services that can scale to large numbers of client users. Companies like IBM and BEA have been quite successful in selling their own middleware Java software.
In this chapter and the next we look at a simple socket-based approach to building web servers for specialized applications [1–4]. This can be done with the classes available in J2SE. In Chapters 16–20 we focus on RMI (Remote Method Invocation) clients and servers and other distributed computing techniques. In Chapter 21 we return to web-based networking with a discussion of web services.
We show here how to create a simple web server that could run on any platform that implements a JVM with the java.net and java.io packages.
As has been demonstrated, Java is a very capable platform for many scientific computing tasks. Yet Java is still sometimes perceived as slow. While this often is a no-longer-deserved reputation, especially in Java 1.4 and later, there are definitely times when the nature of the scientific calculation is so demanding that typical desktop computing resources are insufficient. In such cases, moving portions of the calculation to a heavy-duty remote server machine, perhaps even a “supercomputer,” makes good sense. In this chapter, we introduce the concept of distributed computing.
We continue with the client/server paradigm discussed in the previous chapters, but rather than simply passing messages via socket connections, the client and server objects directly invoke methods in each other over the network. This allows for much more elaborate and productive interactions. The Java Remote Method Invocation (RMI) or Common Object Request Broker Architecture (CORBA) frameworks take care of the communications, and we do not need to create our own low-level protocols as we did with sockets.
We first discuss just what distributed computing is and what form of distributed computing is of value to scientific calculations. We introduce just a little Unified Modeling Language (UML) as a visual aid to understanding the various components in a distributed application. This use of UML and the Design Pattern approach allows us to describe client/server programs in a more formal manner than in the previous chapters.
Java's graphics capability has always been a leading feature of the language. The Java designers clearly expected the graphical user interface (GUI) to dominate interactions with Java programs on all but the smallest platforms. Java appeared at the start of the Internet boom and applets were expected to bring interactivity to the browser. Many thought that Java would also quickly become popular for standalone client applications on platforms with graphical operating systems.
In Java 1.0, however, the graphical elements provided for workable interfaces but they appeared crude compared to platform-specific graphics developed with other languages. The goal of portability had led to a lowest common denominator approach that was not very pretty. This became one of the main stumbling blocks that prevented Java from becoming a popular language for desktop applications.
However, with the inclusion of the Swing packages in version 1.2, Java graphics took a huge leap forward in visual appeal and in the breadth and depth of its features. With subsequent versions, Java graphics continued to improve and now compares quite well with that available with any other programming language and still provides for relatively easy portability.
In this chapter we introduce Java graphics starting with a quick overview of the Abstract Windowing Toolkit from Java 1.0. We then look at the Java Foundation Classes system, also known as “Swing,” in some detail. We wait until Chapter 7 to discuss how to bring interactivity to the user interface.
The Java Virtual Machine (JVM) is often said to provide a safe and self-contained sandbox where programs such as applets can play without accidentally or deliberately entering restricted areas of the platform. That is sufficient if all a program does is interact with the user via a graphical interface but many programs need to reach out and access the world beyond the JVM to obtain information and interact with external hardware.
In Chapter 22 we showed how Java classes can link to native codes, which possess none of Java's security restrictions. This is the ultimate form of local platform access but it involves a lot of inelegant coding and violates the portability of Java. In this chapter we look at less drastic ways that a program can access the platform. We first show how a program can obtain properties describing the platform such as the operating system, the Java version, and screen size. We then explain how to run a non-Java program from within a Java program. Next we discuss how to use serial ports to communicate with external devices. We include a demonstration program in which a Java application communicates via a serial port with a temperature sensor.
We note that the security restrictions put into place by a browser JVM place severe limits on the access that applets have to the platform and the network. However, as we saw in Chapter 14, the security restrictions on Java applications can be easily customized as needed.