Web Service Development Guide : PART IV Extending your Applications : Chapter 13 Asynchronous Messaging : The Async Example
The Async Example
Let’s take a look at the shipped example Async located in the <installdir>\examples\webservices\Async directory. This example illustrates two service operation methods that are implemented asynchronously, one a request-response method, the other a one-way method.
For more information on one-way operations and how they work, see “The One Way Pattern.”
This section discusses how to implement the client’s asynchronous service operation methods and assumes knowledge of how to generate code and build a client. For background information on creating a client with various options, see Chapter 7, “Developing Clients.”
Implementing the Request-Response Method Asynchronously
Following is the implementation of the request-response invoke() method in AsyncClient.cpp, the provided implementation of the client.
 
void invoke_longRunningMethod(AsyncProxy& proxy) //1
{
std::string input_in("Hello World");
std::string return_ret;
try {
std::cout << "Invoking longRunningMethod" << std::endl;
rwsf::CallInfo info;
rwsf::AsyncHandle handle =
proxy.longRunningMethodStart(info, input_in); //2
if(handle.isFinished()) { //3
return_ret = proxy.longRunningMethodEnd(handle); //4
// return_ret is ready for use!
// handle's callInfo has response headers, etc.
rwsf::CallInfo retInfo = handle.getCallInfo(); //5
}
else {
std::cout << "Still waiting" << std::endl;
return_ret = proxy.longRunningMethodEnd(handle); //6
}
std::cout << "Return value = " << return_ret << std::endl;
} catch(const rwsf::SoapFaultException& e) { //7
std::cout << "Fault Code: "
<< e.getFault().getFaultcode().asString() << std::endl;
std::cout << "Fault String: " << e.getFault().getFaultstring()
<< std::endl;
}
}
//1 A request-response method that simulates a wait in order to illustrate its asynchronous behavior.
//2 Calls the asynchronous process longRunningMethodStart() method.
//3 Tests whether the response is available, calling isFinished() on the handle.
//4 Retrieves the response.
//5 If the response message rwsf::CallInfo object has data of interest, retrieves the object so calls can be made against it.
//6 Calls the asynchronous process longRunningMethodEnd() method, which in this position causes the client to block until the response arrives.
//7 Catches an rwsf::SoapFaultException.
Implementing the One-Way Method Asynchronously
This section discusses implementing a one-way method asynchronously. Even though a one-way method expects no response, you may wish to implement it asynchronously, allowing you to make another call on the proxy without waiting for the transport to return.
This discussion assumes background knowledge on one-way methods and how they work. For information, see “The One Way Pattern.”
Now let’s look at the implementation of the one-way invoke() method in AsyncClient.cpp in the <installdir>\examples\Async directory.
 
void invoke_oneWayMethod(AsyncProxy& proxy) //1
{
std::string input_in("Hello World");
 
rwsf::CallInfo info;
std::cout << "Invoking oneWayMethod" << std::endl; //2
rwsf::AsyncHandle handle = //3
proxy.oneWayMethodStart(info,input_in);
proxy.oneWayMethodEnd(handle); //4
 
std::cout << "Finished executing the one way method"
<< std::endl; //5
}
//1 Invokes a one-way method that expects no response.
//2 Because no response is expected with a one-way method, the generator prints “Invoking one-way method” to std::out to indicate to the user that the service is doing its work.
//3 Calls the asynchronous oneWayMethodStart() on the proxy, assigning the result to an async handle. This method returns immediately, even though not everything necessary may have been done to send the message.
//4 Calls the oneWayMethodEnd() method, while it may seem counter-intuitive for a one-way method, allows the main thread to block until the thread that is preparing and sending the one-way message has completed its work. This also protects against exiting the program while the threads are still executing.
//5 Note that there is no catch block for rwsf::SoapFaultException exceptions for one-way operations, since they will never be thrown.
Running the Async Example
NOTE >> Make sure that you have set up your environment as described in Chapter 2, “Setup,” in the HydraExpress User Guide. On Windows, be sure you have set up your command window with the MSVC environment.
To run this example:
1. Generate code by opening a command prompt and navigating to the directory <installdir>\examples\webservices\Async. Enter
 
<prompt> rwsfgen example-project.xml
to direct HydraExpress to generate code into the directory AsyncExample based on the Async.wsdl. You could also enter the options and WSDL file manually, as follows:
 
<prompt> rwsfgen -projectname AsyncExample Async.wsdl
NOTE >> The HydraExpress project file example-project.xml includes all options and files to be used as an argument to the code generator, so using this file results in exactly the same generated code as providing the options and files directly on the command line. For more information on the use of HydraExpress project files in the shipped examples, see Chapter 2, “Setup,” in the HydraExpress User Guide.
2. Before building this example, copy the provided sample files from the <installdir>\examples\webservices\Async to the new AsyncExample directory, allowing the provided files to overwrite the generated files, as follows:
AsyncClient.cpp Copy to AsyncExample\app\client
AsyncImp.cpp Copy to AsyncExample\app\server
3. Navigate to the directory AsyncExample, and build the example by entering nmake (Windows) or make (UNIX/Linux).
4. To deploy the service, shut down the Agent if it is running, run nmake (Windows) or make (UNIX/Linux) for the deploy target, and restart the server. The command sequence to deploy the service is shown below:
Windows
rwsfserver stop
nmake deploy
rwsfserver start
UNIX/Linux
rwsfserver stop
make deploy
rwsfserver start
5. Change to the directory, AsyncExample\bin, and run the client by entering
 
prompt>AsyncClient
The service returns the following:
 
Invoking longRunningMethod
Still waiting //service simulates a 5 second delay
Return value = Hello World
Invoking oneWayMethod
Finished executing the one way method