YOUR FEEDBACK
the usr wrote: So... how about your prediction that SCO would prevail? 11/20/2008 565 - FINAL...
SOA World Conference
Virtualization Conference
$100 Savings Expire November 18, 2008... – Register Today!

SYS-CON.TV
TODAY'S TOP SOA & WEBSERVICES LINKS


Building A Connected MIDlet
...and writing a full-featured J2ME application Part 2

This article is the second in a two-part series devoted to developing a connected MIDlet. In the first part of the series, we designed and built a functional application that collected a string from the user, established a connection to a remote server, sent and received data along that connection, and then presented the result to the user. In this article, we'll refine the design of the application, add a few features that are essential to any connected MIDlet, and implement exception handling.

This article assumes you have read "Building a Connected MIDlet, Part 1" (JDJ, Vol. 8, issue 12) and installed our Echo application. In case you need them, the servlet .ear file and the rest of the code are still available for download at www.altisimo.com/download/echo.ear and www.altisimo.com/download/echo-1.0.zip.

By the end of this article, you'll have learned how to:

  • Break a single class application into better partitioned packages and classes
  • Invoke a new method in a background thread
  • Interrupt an ongoing background thread
  • Gracefully handle application-specific exceptions
This is the list of issues from the first article that we still need to address:
  • Architecture: Our client is complex enough that we should be using multiple classes to handle the various tasks. We will rework the code to follow the architecture of Sun's J2ME blueprint.
  • Progress indicator: Whenever users select a command that takes more than a second to complete, we need to let them know that the application is working on it. In Echo, we should tell the user how far along we are in the network transaction between the mobile device and the servlet. In the current implementation, the user sees a blank screen during the network round-trip and has no idea what is happening.
  • Stop command: We should allow the user to interrupt any task that takes more than a second to complete. In the case of Echo, this again is the network transaction. Users currently have no way to stop the network round-trip to check their calendar or do anything else on the handheld device.
  • Input validation: The J2EE component of our application will throw an exception if the string it receives is null or empty. One way to address this issue is to add a preliminary client-side test before we send the data to the servlet.
  • Exception handling: There are a variety of other issues that can arise during the execution of our application. We'll explore how to identify and handle many of these issues.
Architecture
We based the second iteration of Echo on Sun's J2ME Smart Ticket blueprint, using the same architecture and class names whenever possible, while removing any unused features. This makes it easier to become familiar with the inner workings of the blueprint in a simplified context. The server-side portion of this application has not changed from the first version. It's a simple servlet that reads in a string from the client and returns the same string. The server side consists of the following classes:
  • EchoServlet: The servlet class, which reads in the string using readUTF and then writes it back out using writeUTF.
  • EchoTest: An automated test client to ensure that the servlet is functioning properly before we begin writing J2ME client code. For a more complex application, we would use JUnit, but for this example this simpler test is acceptable.
The J2ME client-side portion of this version of Echo looks more complex on the surface. We start by thinking about the application from the Model-View-Controller (MVC) point of view. Figure 1 illustrates the basic MVC architecture and how the different layers interact.

We'll use three packages, each of which encapsulates part of the MVC architecture; our complete architecture is shown in Figure 2. It might seem extreme to make the Echo client so complex, but we can reuse this architecture and these packages in future projects. The packages are:

  • echo.model: Contains the model part of the MVC architecture - the classes that model what the client needs to know about the server side of the application. This includes data objects, business logic, and a proxy connector to the server.
  • echo.ui: Contains the view and the controller parts of the MVC architecture. These are the classes that obtain and display information from and to the user, and control the flow from screen to screen.
  • echo.util: Contains the utility classes that are used by both the model and UI packages.
  • echo: A top-level package containing exactly one class, EchoMIDlet. This is the entry point for the application. EchoMIDlet creates instances of the model, the view, and the controller, and delegates control to the controller.

    The model package holds all the business objects used on the mobile side of the application, allowing us to separate business logic from the user interface classes. The model package contains two classes:

  • RemoteModelProxy: An instance of the Proxy design pattern, it offers a local method call interface to the remote server. RemoteModelProxy is responsible for establishing a connection with the remote server, passing on any requests made by the user, and receiving the data returned by the remote server. This is where the actual communication happens, so this is also a place where we must catch the many exceptions that might be thrown, and present the user with a message that explains what has happened - why the application was unable to complete the requested task and what the user should do differently to avoid the error in the future.
  • ModelFacade: We use the Facade pattern to control access to the model package. ModelFacade is the single access point for other classes into the model of the program. It creates a RemoteModelProxy as an instance variable, and then delegates all subsequent requests onto it.
The UI package contains the view and controller parts of the MVC architecture: all of the screens used to gather and display information, as well as the classes required to manage them. In Echo, the view consists of three forms, and the controller is implemented by a UIController object.
  • GetInputUI is a form that collects a single string from the user. Figure 3 shows GetInputUI immediately after the MIDlet is started.
  • ProgressObserverUI holds a gauge that displays the progress made in the network transaction. This class implements the ProgressObserver interface. Figure 4 shows the ProgressObserverUI in the middle of the connection process.
  • ShowOutputUI is another form. It displays the server's response to the user, as in Figure 5.
  • UIController handles the transitions between screens. It performs the actions that ensure that the user is presented with correct and up-to-date information as to what is happening in the application. This class also spawns and starts a new thread to display the ProgressObserverUI.
The util package is used by classes in both the model and the UI packages, thereby maintaining separation between the other packages while not requiring repeated code to handle exceptions and other assistive tasks, such as displaying a progress indicator.
  • ApplicationException encapsulates any exceptions that might be thrown during the execution of the application.
  • ErrorMessageCode is an additional level of abstraction used to categorize some of the ApplicationExceptions.
  • ProgressObserver is an interface implemented by Progress- ObserverUI. It defines the basic methods required to display and control the gauge. ProgressObserver contains methods to update the gauge, set the "is stoppable" flag, determine if the stoppable flag is set, and stop the ongoing process.
Now that you're familiar with how the classes are packaged and their basic functionality, let's look at how we implemented some of the improvements to the application.

Progress Indicator
A powerful aspect of the J2ME platform is its inherent multithreading capability. By using multiple threads, an application can perform a time-consuming task in the background while still updating the UI to keep the user informed. There's nothing more frustrating than hitting a button and not having any idea whether anything is going on: Is the application doing something difficult or did it just hang?

The only part of Echo that's likely to take some time to complete a task is in the method RemoteModelProxy.echo(). This is where the client creates and communicates along the connection to the remote server. While the device is establishing a connection and sending data, there is currently no visual feedback to let the user know that anything is happening. This is why we will implement a Progress Indicator: to let the user know where the application is in the connection process. The ProgressObserver runs in its own thread and uses the ProgressObserverUI to provide information to the user. ProgressObserverUI extends the form and uses a gauge to show how far along in its task the ProgressObserver is.

In our implementation, when the user wants to send out the string he or she entered, we call UIController.doEcho(). doEcho() spawns the new thread and then passes the thread and the user's string as arguments to runWithProgress(). runWithProgess() prepares the ProgessObserverUI, sets it as the current screen, and starts the new thread. The thread executes the code in run() (see Listing 1).

model.echo() actually calls RemoteModelProxy.echo(), which establishes the connection to the remote server, transmits the string the user provided, and returns the response from the server (see Listing 2).

By creating a separate thread for the ProgressObserver and setting it to be the current display before we start to connect to the remote server, we let RemoteModelProxy do the complex work of establishing and using the connection in the background. This means we can update the ProgressObserverUI to let the user know the state of the application. Once RemoteModelProxy. echo() has returned, the result is appended to ShowOutputUI, and ShowOutputUI is set to be the current display.

Notice that after each important step in echo() we make a call to checkAndUpdateProgress(). This allows us to break the method into relevant chunks, and perform any tests required before continuing through the method.

protected void checkAndUpdateProgress() throws ApplicationException {
if (progressObserver != null) {
if (progressObserver.isStopped()) {
throw new ApplicationException(
ErrorMessageCode.ERROR_OPERATION_INTERRUPTED);
}
else {
progressObserver.updateProgress();
}

}

}

checkAndUpdateProgress() makes sure there is a ProgressObserver to update, and tests to see if the ProgressObserver's stopped flag has been set to true. If the flag is not set, we increment the gauge and continue on through the method. If the flag is set, we throw an ApplicationException and exit the method. Setting the stopped flag is handled by the stop command.

Stop Command
The ProgressObserver is a nice feature, but what if the user needs to cancel a transaction while communicating with the remote server? We need to give him or her a way to cancel a task before it returns. This is a situation for a stop command.

We have already added commands to our application in UIController, but in this case we are using a command that is local to the ProgressObserverUI. All of the previously implemented commands have been used when the program was inactive and waiting for user input to initiate a new task. In this case, we want to stop an ongoing task and to have that task interrupted as quickly as possible.

Look back at the implementation of echo() and notice that we delegate all of the calls to increment the gauge to checkAndUpdateProgress() when RemoteModelProxy completes a step in the communication process. We do not have a way to instantly shut down the RemoteModelProxy as it is contacting the remote server, but we can have the RemoteModelProxy check if it should continue before each additional step. This is where we use the stop command, and it is the reason ProgressObserverUI implements CommandListener.

When the stop button is pressed, the stopped flag in the ProgressObserver is set to true, and the RemoteModelProxy will stop executing echo() the next time checkAndUpdateProgress() is called. checkAndUpdateProgress() will throw an ApplicationException of type ErrorMessageCode.ERROR_ OPERATION_INTERRUPTED to let the caller know what happened:

public void commandAction(Command command, Displayable display) {
if (command == stopCommand) {
stopped = true;
}
}

We can then catch the ApplicationException in UIController. run() and display a message to the user letting him or her know that they successfully interrupted the communication process.

Input Validation
If we send a null or empty string to the server, our application will throw a RuntimeException when EchoServlet calls readUTF(). We need to implement some very basic input validation in the client before we call doEcho(). It would be an easy enough task to change EchoServlet to handle this case, but we don't want to take the time and resources to create a connection if there is no useful information to send along it. Remember, our handheld device is limited - its network connection is likely to be slow and have high latency - and many carriers charge by the packet. This is a case where a few lines of additional code in the client can save the user some time and money. Because the buttons in GetInputUI use UIController as their CommandListener, we have commandAction() call GetInputUI.hasValidInput() to ensure that the user has provided an acceptable string. By having the callback to GetInputUI for the validation, we can customize hasValidInput() for future versions of GetInputUI without having to change UIController (see Listing 3).

If the user has not provided valid input, GetInputUI.tryAgain() is called. The user is then prompted to enter a string again, after being shown an error telling him or her that the input cannot be blank.

void tryAgain() {
uiController.showErrorAlert(
new ApplicationException(ErrorMessageCode.ERROR_BLANK_INPUT),
this);
}

This is about as thorough as client-side data validation needs to be. A nice side effect is that it teaches the user how to use the application.

Exception Handling
Our exception handling scheme is also based on the architecture from the Sun blueprint. We use ApplicationException to handle all nonnative exceptions, and use constants within ErrorMessageCode to store the various types of ApplicationExceptions that can occur most frequently (see Listing 4).

ApplicationException has a no-argument and three single-argument constructors that take either a string, an int, or another exception. These allow you to set your own error message, use one of the predefined messages, or wrap another exception in an ApplicationException to pass it up the chain of method calls.

When the int-argument constructor is used, the int is mapped to one of the existing error types in ErrorMessageCode. The corresponding text is assigned to the message attribute of the ApplicationException instance, with a default error message to handle any undefined errors that are encountered (see Listing 5).

Each ApplicationException has a string attribute and an exception attribute, and when either of the other single-argument constructors are used, the corresponding instance attribute is set to the argument that is passed into the constructor.

public ApplicationException(String msg) {
this.message = msg;
return;
}

public ApplicationException(Exception exception) {
this.exception = exception;
return;
}

By having a single, versatile ApplicationException, we can have greatly simplified catch blocks, but still be sure that we are indeed handling all possible nonnative exceptions by catching only ApplicationException, and that we are still able to customize error messages for any situation we might encounter.

Model-View-Controller Architecture
The Model-View-Controller (MVC) Architecture divides the functionality of an application into three layers: model, view, and controller. MVC decouples the responsibilities of the different layers and assigns each layer a specific set of tasks.

A model represents business objects and the rules as to how they are accessed and updated. The model informs views when data changes and contains methods for the views to determine its current state.

A view displays the contents of a model to the user. It's responsible for how the data is presented. Views also forward user actions to the controller.

A controller directs the actions within the application. It's responsible for interpreting user input and triggering the appropriate model actions.

Conclusion
We have now written a complete example of how to connect to and communicate with a remote server. There are more features we could add to this application to offer the user more control or to handle more obscure potential exceptions, but in its current state, Echo is more than enough for a sample connected application. We use Echo as the basis for more complex applications, and we hope that this article provides you with a foundation to develop your own connected MIDlets.

There are many more issues to consider when writing a full-featured J2ME application, such as accessing the device's memory store or being able to operate in a disconnected mode, and we look forward to covering them in upcoming articles. If there are any topics that you want to see included in the series, please send us an e-mail at info@altisimo.com.

About Richard Kasperowski
Richard Kasperowski, a cofounder of Altisimo Computing, has been programming in Java since 1997 and developed numerous applications for private and commercial use. Richard is also the cochair of the New England Java Users Group J2ME Special Interest Group.

About Alex Bourgeois
Alex Bourgeois is a cofounder of Altisimo Computing, a J2ME consulting and training company. He has been programming in Java since 1997 and has developed numerous applications for private and commercial use. Alex also cochairs the New England Java Users Group J2ME Special Interest Group.

YOUR FEEDBACK
- wrote: This example, like most other networking MIDLets, hangs for minutes waiting for a network connection if it does not get a response from the server (or some other network entity saying that the server is unreachable). Whatever happened to the user being able to abortthe operation???
- wrote: This example, like most other networking MIDLets hangs for minutes waiting for a network connection if it does not get a response from the server (or some other network entity saying that the server is unreachable). Whatever happened to the user being able to abortthe operation???
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON FEATURED WHITEPAPERS


ADS BY GOOGLE