|
YOUR FEEDBACK
|
TODAY'S TOP SOA & WEBSERVICES LINKS Building A Connected MIDlet
...and writing a full-featured J2ME application Part 2
Mar. 5, 2004 12:00 AM
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:
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:
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:
Progress Indicator 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 { 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 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) { 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 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() { 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 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) { 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 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 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. YOUR FEEDBACK
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK |
|||||||||||||||||||||||||||||||