Browse DevX
Sign up for e-mail newsletters from DevX


Build a SOAP-based Chat Application with Java Web Services, Part 2 : Page 5

In Part 1, you built a fully-functional chat application using the Eclipse IDE and free Web services software from Systinet. In Part 2, use WASP Developer for Eclipse 4.6 to extend your original application with asynchronous messaging.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Intermezzo: SOAP Faults
Before you get to the async client, let's make a short detour into the realm of exception propagation. You've just seen it in action. SOAP carries an abstraction for fault states on the server side. There's a special message type in SOAP called a SOAP Fault that tells the client that something went terribly wrong on the server side. The description of SOAP faults can be placed into the service's WSDL to tell the clients what kind of errors to expect.

The interface of the service was enhanced with a method getOrWaitforNewMessages, which throws your custom NoMessageArrivedException. When WASP deploys an application's service classes as Web services, it stores information about its methods' exceptions into the WSDL as SOAP Faults. When you create a client using the wizard, the wizard reads the SOAP Faults from the WSDL and generates the exception classes. In this instance, it generated the NoMessageArrivedException. During runtime, all the SOAP plumbing is handled by WASPJ. When an exception is raised in the service, the WASPJ server infrastructure sends back a SOAP Fault. The WASPJ client infrastructure receives the fault and raises the exception in the client code.

All together, the SOAP specification lets you transfer error states from the service to the client. WASP Server for Java's smart SOAP runtime can map generic SOAP faults right into Java exceptions transparently, so you don't have to be concerned about the plumbing at all. All you need to know is the service interface. Simply be ready for exceptions when they come.

Step II: Asynchronous API
The asynchronous API of any messaging runtime should let the client fire the request, forget about it, do other work, and either be notified when the response arrives or wait until it arrives. We are running into the realm of multithreaded applications, synchronization etc., which inevitably leads into more complicated code samples that are harder to read. I assume that your knowledge of Java also covers multithreaded programming.

The WASPJ Asynchronous invocation API provides two basic patterns of response arrival processing: callbacks (listeners) and polling. Callbacks are user-registered listeners, that are called by the framework when the response comes back from the server. The polling API lets the client code check whether the response has arrived already. I personally prefer callbacks (although there are use cases where polling is a better strategy), and so this tutorial shows the usage of callbacks.

Before jumping into the updated source code, let me present it in outline. You'll initiate the asynchronous invocation of the service, and register a callback that gets called when the response is returned. Later on, before the response arrives, you'll process other code—for simplicity, a loop that waits until the response arrives. Once it has the response, you'll break the loop and finish the client process. Please note that the usage of the async API doesn't say anything about the way the message is sent/received on the transport level at this moment. You'll be using an async API over a sync transport for now.

The full listing of the updated client is in Listing 5 (See also ChatServiceClientAPIAsync.java in DEMO_HOME/src). Here's a snippet of the main method of the client:

service = (ChatService)serviceClient.createProxy(ChatService.class); // now, call the methods on your Web Service interface // let's start with some synchronous calls, print the existing messages long lastMessageId; ChatMessage msgs[]; service.postMessage("Enter", "Sandman"); msgs = service.getAllMessages(); lastMessageId = msgs[msgs.length - 1].id; printMessages(msgs); // now let's wait for another messages to arrive System.out.println(">>> Client: Making the asynchronous call, " + "waiting for response to arrive..."); //1. initiate the async invocation; // read new messages from the server with timeout 10s AsyncConversation async = service.beginGetOrWaitforNewMessages(lastMessageId, 10000); //2. setup the callback that will be called when the response arrives MyCallbackClass callback = new MyCallbackClass(service); async.setCallback(callback); //3. the following dumb code demonstrates that // the client keeps running // my callback decides if it's been enough already while (!finishedWork) { //The client now either sleeps (read: "does other important work"); System.out.println(" Client: ... zzzzZZZ ... " + "doing other work ... zzZZ ..."); Thread.sleep(2000); System.out.println(" Client: " + "Sending another post to the server."); service.postMessage("Wake Up!", "Sandman"); } System.out.println("--- Client: All work done, exiting.");

  1. The method onResponse gets called whenever a response from the server arrives. In the first step, read the result from the service by calling the endGetOrWaitforNewMessages method on the service proxy. This method either returns the new messages or rethrows our service's exception.
  2. When the response is processed, tell the framework not to wait for more messages to come. WASPJ is able to process more responses for a single asynchronous call. When finished, set the finishedWork to true to make the main client thread escape from the loop.

And that's it! Run the client using the runner that you've already created and see the results:

# Thu Sep 18 19:38:26 EDT 2003 Sandman > Enter # Thu Sep 18 20:02:06 EDT 2003 Sandman > Enter >>> Client: Making the asynchronous call, waiting for response to arrive... Client: ... zzzzZZZ ... doing other work ... zzZZ ... Client: Sending another post to the server. Client: ... zzzzZZZ ... doing other work ... zzZZ ... <<< Callback: The asynchronous response from the ChatService has arrived! # Thu Sep 18 20:02:08 EDT 2003 Sandman > Wake Up! --- Callback: Leaving! Client: Sending another post to the server. --- Client: All work done, exiting.

The actual chat conversation may be different for you, depending on the number of times you already run your clients. As you can see, the client sends the async request to the server (the message that starts with >>>). Then, the server does other interesting work (zzzZZZ) and sends a new message to the server. At that moment, the response is returned from the server and sent to the callback (the <<< message). At the end, the callback sets finishedWork to true, closes the conversation and leaves. The client leaves the loop as soon as it gets the chance to do so, and exits.

This client code used the asynchronous API, but on the transport level, the call was still synchronous. The http connection opened by the client remained open all the time until the response was returned. The server has no notion about the client's asynchronicity at all in this use case.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date