Request Handling and Threading
This code creates a custom listener class:
 
#include <rwsf/core/Config.h> //1
#include <rwsf/webservice/listener/MessageListenerImp.h>
 
 
class MyListener : public rwsf::MessageListenerImp {
 
public:
MyListener();
 
protected:
virtual void doInit(const rwsf::Config& initParams);
virtual void initServer();
virtual void doStart();
virtual void doStop();
virtual void doReset();
 
private:
int port_;
client_; //2
example::SocketThread mainThread_;
};
//1 The rwsf::Config class holds initialization parameters passed to the listener from the listener configuration file, client-transports.xml. For more information on the data and methods available through this class, see its class description in the HydraExpress C++ API Reference Guide.
//2 Note that client_ and SocketThread are not HydraExpress classes but are just used for illustration purposes in this example.
NOTE: For threading and network capabilities in HydraExpress services, you can use the network and threading classes of Rogue Wave’s SourcePro.
The following lines are pseudo code for creating a threading framework. This framework is needed so the doStart() method can be implemented as non-blocking.
 
namespace example {
class SocketThread : public Thread {
public:
SocketThread(Socket socket, MyListener listener); //1
void run(); //2
 
private:
Socket socket_;
MyListener listener_;
};
}
 
void SocketThread::run()
{
while( not end ) { //3
client = socket.accept(); //4
RequestHandler(client, listener).start(); //5
}
}
//1 Create a socket thread based on the supplied socket.
//2 Define the main listener thread.
//3 The run() method must test some condition that lets it know when to return.
//4 The socket accepts the message off the line and stores it in some kind of object.
//5 The message off the socket is executed in a RequestHandler thread. The start() method starts the thread and then calls the run() method of RequestHandler. See below for a pseudo code implementation of this class.
A listener needs to do the following work:
*Collect incoming requests off the wire and place data into an rwsf::CallInfo instance. See the description of this class for information on the data structures and methods it provides.
* Invoke the service implementation for handling the request.
This sample code declares the RequestHandler class:
 
class RequestHandler : public Thread {
public:
RequestHandler(client, MyListener listener);
void run();
 
private:
client_;
MyListener listener_;
};
 
void RequestHandler::run()
{
listener_.handleRequest(client_);
}
The RequestHandler’s run() method invokes the listener’s handleRequest() method, which actually processes the request:
 
void MyListener::handleRequest(client)
{
std::string payload = client.getPayload(); //1
rwsf::CallInfo callInfo;
callInfo.setRequest(payload); //2
 
invoke(callInfo); //3
 
std::string response = callInfo.getResponse(); //4
client.write(response); //5
}
//1 Reads the data taken off the line by the socket into a string.
//2 Sets the request payload on an rwsf::CallInfo object.
//3 Invokes the service implementation.
//4 Gets the response from the rwsf::CallInfo object.
//5 Writes the response message to the socket.
When the invoke has completed, the rwsf::CallInfo should contain any information needed to send back a response. This information might include a response payload, headers, a status code, and so on. You need to implement code for writing that information to a location where the client can retrieve it.
Finally, use the following convenience macro that generates code to create a listener instance.
 
RWSF_DEFINE_RWSF_LISTENER(MyListener)