- Client Considerations
- General Design Issues and Guidelines
- Design Issues and Guidelines for Browser Clients
- Design Issues and Guidelines for Java Clients
- Summary
- References and Resources
3.4 Design Issues and Guidelines for Java Clients
Java clients can be divided into three categories: applications, applets, and MIDlets. They all leverage the Java programming language and a small common set of Java libraries, but they are deployed differently.
3.4.0.0.1
Application Clients
Application clients execute in the Java 2 Runtime Environment, Standard Edition (JRE). They are very similar to the stand-alone applications that run on traditional desktop computers. As such, they typically depend much less on servers than do browsers.
Application clients are packaged inside JAR files and may be installed explicitly on a client's machine or provisioned on demand using Java Web Start technology. Preparing an application client for Java Web Start deployment involves distributing its JAR with a Java Network Launching Protocol (JNLP) file. When a user running Java Web Start requests the JNLP file (normally by clicking a link in a Web browser), Java Web Start automatically downloads all necessary files. It then caches the files so the user can relaunch the application without having to download them again (unless they have changed, in which case Java Web Start technology takes care of downloading the appropriate files).
For more information on Java Web Start and JNLP, see the Java Web Start home page listed in "References and Resources" on page 73.
3.4.0.0.2 Applet Clients
Applet clients are user interface components that typically execute in a Web browser, although they can execute in other applications or devices that support the applet programming model. They are typically more dependent on a server than are application clients, but are less dependent than browser clients.
Like application clients, applet clients are packaged inside JAR files. However, applets are typically executed using Java Plug-in technology. This technology allows applets to be run using Sun's implementation of the Java 2 Runtime Environment, Standard Edition (instead of, say, a browser's default JRE).
For more information on packaging applets, consult the Java Tutorial. For more information on serving applets from JSP pages using Java Plug-in technology, consult the J2EE Tutorial.
3.4.0.0.3 MIDlet Clients
MIDlet clients are small applications programmed to the Mobile Information Device Profile (MIDP), a set of Java APIs which, together with the Connected Limited Device Configuration (CLDC), provides a complete Java 2 Micro Edition (J2ME) runtime environment for cellular phones, two-way pagers, and palmtops.
A MIDP application is packaged inside a JAR file, which contains the application's class and resource files. This JAR file may be pre-installed on a mobile device or downloaded onto the device (usually over the air). Accompanying the JAR file is a Java Application Descriptor (JAD) file, which describes the application and any configurable application properties.
For a complete specification of a JAD file's contents, as well as deploying MIDP applications in general, see the J2ME Wireless Toolkit User's Guide.
3.4.1 Presenting the User Interface
Although a Java client contains an application's user interface, the presentation logic behind this interface may come from a server, as it would for a browser, or it may be programmed from the ground up on the client. In this section, we discuss the latter case.
Java applet and application clients may use the Java Foundation Classes (JFC)/Swing API, a comprehensive set of GUI components for desktop clients. Java MIDlets, meanwhile, may use the MIDP User Interface API, a GUI toolkit that is geared towards the limited input capabilities of today's mobile information devices. For example, Figure 3.2 shows the Java Smart Ticket sample application using the MIDP UI API and running on a Palm IIIc emulator.
Figure 3.2 Java Smart Ticket Sample Application Client Running on a Palm OS Device
Implementing the user interface for a Java client usually requires more effort to implement than a browser interface, but the benefits are substantial. First, Java client interfaces offer a richer user experience; with programmable GUI components, you can create more natural interfaces for the task at hand. Second, and perhaps more importantly, full programmability makes Java clients much more responsive than browser interfaces.
When a Java client and a browser client request the same data, the Java client consumes less bandwidth. For example, when a browser requests a list of orders and a Java client requests the same list, the response is larger for the browser because it includes presentation logic. The Java client, on the other hand, gets the data and nothing more.
Furthermore, Java clients can be programmed to make fewer connections than a browser to a server. For example, in the Java Pet Store sample application, an administrator may view orders in a table and sort them by date, order identifier, and so on. He or she may also see order data presented in a pie chart or a bar chart, as shown in Figure 3.3.
Figure 3.3 Java Pet Store Sample Application Administrator Client Displaying Order Data in Pie and Bar Charts Using the JFC/Swing API
Because the administrator client uses the JFC/Swing API, it can provide all of these views from the same data set; once it retrieves the data, it does not have to reconnect to the server (unless it wants to refresh its data). In contrast, an administrator client implemented using a browser must connect to the server each time the view changes. Even though the data does not change, the browser has to download a new view because the data and the view are intertwined.
For more information on programming JFC/Swing user interfaces, refer to the JFC Swing Tutorial. For more information on programming MIDP user interfaces, read Programming Wireless Devices with the Java 2 Plaform, Micro E_dition.
3.4.2 Validating User Inputs
Like presentation logic, input validation logic may also be programmed on Java clients, which have more to gain than browser clients from client-side input validation. Recall that browser clients have to trade off the benefit of fewer connections (from detecting bad inputs before they get to the server) for the cost of using more bandwidth (from downloading validation code from the server). In contrast, Java clients realize a more responsive interface because they do not have to download validation logic from the server.
With Java clients, it is straightforward to write input validation logic. You use the Java programming language, as shown in Code Example 3.3 from the Java Smart Ticket sample application:
Code Example 3.3 Java Smart Ticket Sample Application Code for Validating Inputs in a User Account Form
public void validateAll() throws ApplicationException { if (username.size() < 4) { /* Complain about username being too short... */ } if (password.size() < 6) { /* Complain about password being too short... */ } if (zipCode.size() != 5) { /* Complain about ZIP code not having 5 characters... */ } if (creditCard.size() != 12) { /* Complain about credit card number not having 12 digits... */ } }
For more sophisticated input validation on JFC/Swing clients, consider using the InputVerifier class provided by the JFC/Swing framework. For more information, see "References and Resources" on page 73.
Of course, the best way to reduce client-side validation requirements is to make it impossible to enter bad data in the first place (especially if you are expecting a value of an enumerated type). For example, using a text field to enter a date is error-prone because a text field can receive many types of input. Providing a set of drop-downs that contain valid months, days, and years might be an improvement, but a user can still enter invalid input (such as Feb. 30). The best solution is to provide a calendar widget that intelligently constrains what date is chosen, and the only way to implement such a custom component is with a programmable client.
3.4.3 Communicating with the Server
Java clients may connect to a J2EE application as Web clients (connecting to the Web tier), EJB clients (connecting to the EJB tier), or EIS clients (connecting to the EIS tier).
3.4.3.0.1 Web Clients
Like browser clients, Java Web clients connect over HTTP to the Web tier of a J2EE application. This aspect of Web clients is particularly important on the Internet, where HTTP communication is typically the only way a client can reach a server. Many servers are separated from their clients by firewalls, and HTTP is one of the few protocols most firewalls allow through.
Whereas browsers have built-in mechanisms that translate user gestures into HTTP requests and interpret HTTP responses to update the view, Java clients must be programmed to perform these actions. A key consideration when implementing such actions is the format of the messages between client and server.
Unlike browser clients, Java clients may send and receive messages in any format. For example, in the Java Smart Ticket sample application, a user may look at a list of movies. If the user had a browser client, the list would have to be formatted in HTML before downloading it to the client. However, the Java client in this demo downloads a plain binary string representing the list.
A Java client could use another format, such as comma-separated values:
1,Big and Badder,2,The Dot,4,Invasion of the Dots
Or, the client could use key-value pairs:
id=1,title="Big and Badder" id=2,title="The Dot" id=4,title="Invasion of the Dots"
Or, the client could use XML:
<movies> <movie> <id>1</id> <title>Big and Badder</title> </movie> <movie> <id>2</id> <title>The Dot</title> </movie> <movie> <id>4</id> <title>Invasion of the Dots</title> </movie> </movies>
Although the possibilities are endless, you can think of message formats as falling into a spectrum, with binary strings on one end and XML documents on the other. To understand the tradeoffs of message formats in general, it helps to consider these two extremes.
Binary messages consume little bandwidth. This aspect of binary messages is especially attractive in low-bandwidth environments (such as wireless and dial-up networks), where every byte counts. Code Example 3.4 illustrates how a Java client might construct a binary request to log into an application.
Code Example 3.4 Java Client Code for Sending a Binary Request
static final int LOGIN_USER = 1; // ... HttpConnection c; DataOutputStream out; String username, password; /* Construct the body of the HTTP POST request using out... */ out.write(LOGIN_USER); out.writeUTF(username); out.writeUTF(password); /* Send the HTTP request... */
Code Example 3.5 illustrates how a Java servlet might listen for requests from the Java client:
Code Example 3.5 Java Servlet Code for Interpreting a Binary Request
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { /* Interpret the request. */ DataInputStream in = new DataInputStream(req.getInputStream()); int command = in.readInt(); resp.setContentType("application/binary"); DataOutputStream out = new DataOutputStream(resp.getOutputStream()); byte command = in.read(); switch (command) { case LOGIN_USER: String username = in.readUTF(); String password = in.readUTF(); /* Check username and password against user database... */ } }
These examples also illustrate a substantial cost of HTTP-based messaging in general; you have to write code for parsing and interpreting messages. Unfortunately, writing such code, especially for multiple programmable clients, can be time-consuming and error-prone.
Java technologies for XML alleviate some of the burdens experienced with binary messaging. These technologies, which include the Java API for XML Processing (JAXP), automate the parsing and aid the construction of XML messages. Messaging toolkits based on Java technology help interpret messages once they are parsed; these toolkits implement open standards such as the Simple Object Access Protocol (SOAP). The ability to parse and interpret messages automatically reduces development time and helps maintenance and testing.
A side benefit of using XML messages is that alternate clients are easier to support, as XML is a widely-accepted open standard. For example, StarOffice Calc and Macromedia Flash clients could both read order data formatted in XML from the same JSP page and present the data in their respective interfaces. Also, you can use XML to encode messages from a variety of clients. A C++ client, for example, could use a SOAP toolkit to make remote procedure calls (RPC) to a J2EE application.
The most common models for XML processing are DOM and the Simple API for XML (SAX). Unlike DOM, which provides an in-memory, tree-based data structure for random access, SAX offers event-based serial access, which makes processing messages faster. For more information on using XML effectively, see "References and Resources" on page 73.
Like browser clients, Java Web clients carry out secure communication over HTTPS. See Section 9.2.2 on page 284 for more information on Web authentication mechanisms and Section 9.4.2 on page 305 for more information on Web confidentiality mechanisms.
3.4.3.0.2 EJB Clients
When using Web clients, you must write code for translating user gestures into HTTP requests, HTTP requests into application events, event responses into HTTP responses, and HTTP responses into view updates. On the other hand, when using EJB clients, you do not need to write such code because the clients connect directly to the EJB tier using Java Remote Method Invocation (RMI) calls.
Unfortunately, connecting as an EJB client is not always possible. First, only applet and application clients may connect as EJB clients. (At this time, MIDlets cannot connect to the EJB tier because RMI is not a native component of MIDP.) Second, RMI calls are implemented using IIOP, and most firewalls usually block communication using that protocol. So, when a firewall separates a server and its clients, as would be the case over the Internet, using an EJB client is not an option. However, you could use an EJB client within a company intranet, where firewalls generally do not intervene between servers and clients.
When deploying an applet or application EJB client, you should distribute it with a client-side container and install the container on the client machine. This container (usually a class library) allows the client to access middle-tier services (such as the JMS, JDBC, and JTA APIs) and is provided by the application server vendor. However, the exact behavior for installing EJB clients is not completely specified for the J2EE platform, so the client-side container and deployment mechanisms for EJB clients vary slightly from application server to application server.
Clients should be authenticated to access the EJB tier, and the client container is responsible for providing the appropriate authentication mechanisms. For more information on EJB client authentication, see Section 9.2.2.2 on page 287.
3.4.3.0.3 EIS Clients
Generally, Java clients should not connect directly to a J2EE application's EIS tier. EIS clients require a powerful interface, such as the JDBC API, to manipulate data on a remote resource. When this interface is misused (by a buggy client you have implemented or by a malicious client someone else has hacked or built from scratch), your data can be compromised. Furthermore, non-trivial EIS clients must implement business logic. Because the logic is attached to the client, it is harder to share among multiple types of clients.
In some circumstances, it may be acceptable for clients to access the EIS tier directly, such as for administration or management tasks, where the user interface is small or nonexistent and the task is simple and well understood. For example, a simple Java program could perform maintenance on database tables and be invoked every night through an external mechanism.
3.4.4 Managing Conversational State
Whereas browser clients require a robust server-side mechanism for maintaining session state, Java clients can manage session state on their own, because they can cache and manipulate substantial amounts of state in memory. Consequently, Java clients have the ability to work while disconnected, which is beneficial when latency is high or when each connection consumes significant bandwidth.
To support a disconnected operation, a Java client must retrieve enough usable data for the user before going offline. The initial cost of downloading such data can be high, but you can reduce this cost by constraining what gets downloaded, by filtering on user preferences, or requiring users to enter search queries at the beginning of each session. Many applications for mobile devices already use such strategies; they also apply well to Java clients in general.
For example, you could extend the Java Smart Ticket sample application to allow users to download movie listings onto their phones. To reduce the size of the listings, you could allow users to filter on simple criteria such as genre (some users may not be in the mood for drama) or ZIP code (some users may only want to go to movie theaters within 10 miles of where they live). Users could then browse the personalized lists on their phones without needing to connect to the server until they want to buy a ticket.
Also note that the movie listings are candidates for persistence on the client, since they are updated infrequently, perhaps once every week. The Java Smart Ticket sample application client uses the MIDP Record Management Store (RMS) API to store data locally. Application clients, meanwhile, can use either local files (assuming they have permission) or the Java Native Launching Protocol and API (JNLP) persistence service. (Applets have very limited local storage because they normally use a browser's cookie store, although they can request permission to use local files as well.)
Figure 3.4 Java Smart Ticket Sample Application Listing Movie Information Downloaded onto the Phone
The example of downloading movie listings illustrates a read-only interaction. The client retrieves data from the server, caches it, and does not modify the cached data. There may be times, however, when a Java client needs to update data it receives from the server and report its changes to the server. To stay disconnected, the client must queue updates locally on the client and only send the batch when the user connects to the server.
In the Java Smart Ticket sample application, the client allows users to pinpoint the exact seats they want to buy. When the user decides what show he or she wants to see, the client downloads the data for the show's seating plan and displays the plan to the user. The plan indicates which seats are available and which have already been taken, as shown in Figure 3.5.
Figure 3.5 Java Smart Ticket Sample Application Displaying an Editable Seating Plan for a Particular Movie Showing
This example highlights two important issues. First, when Java clients manipulate enterprise data, they need to know about the model and some or all of the business rules surrounding the data model. For example, the client must understand the concept of booked and unbooked seats, and model that concept just like the server does. For another example, the client must also prevent users from trying to select booked seats, enforcing a business rule also implemented on the server. Generally, clients manipulating enterprise data must duplicate logic on the server, because the server must enforce all business rules regardless of what its clients do.
Second, when Java clients manipulate enterprise data, applications need to implement data synchronization schemes. For example, between the time when the user downloads the seating plan and the time when the user decides what seats he or she wants to buy, another user may buy some or all of those seats. The application needs rules and mechanisms for resolving such a conflict. In this case, the server's data trumps the client's data because whoever buys the tickets firstand hence updates the server firstgets the tickets. The application could continue by asking the second user if he or she wants the seats that the first user did not buy. Or, it could refresh the second user's display with an updated seating plan and have the user pick seats all over again.