Using EPL to interact with Web Services
Apama applications that interact with Web Services need to use specific Apama Event Processing Language (EPL) code to do so.
Define the Apama events that are to be used specifically to interact with the Web Services. If the application will use a convention-based approach to mapping, design Apama events such that the event fields correspond to the elements of the associated Web Service messages. Note that fields that correspond to attributes in the Web Service messages should be prefixed with an underscore character (" _ "). For more information on convention-based mapping, see
Convention-based XML mapping.
For example:
event GetStockDailyValue{
string strStockExchange;
string strStock;
string strDate;
}
event Stock{
string stockexchange;
string stock;
string date;
}
event StockValue{
string response;
}
The com.apampa.ws and com.apama.statusreport packages define events that are helpful when invoking Web Services. For convenience, specify using statements for the events you want to use so that you do not need to specify their full paths. For example:
using com.apama.statusreport.Status;
using com.apama.ws.WSError;
using com.apama.ws.SetupContextListeners;
using com.apama.statusreport.SubscribeStatus;
Define a listener for an AdapterUp event that indicates that the Web Services Client adapter instance is available to pass your application's service requests to the Web Service. In this listener, be sure so specify the name of the adapter instance as it appears in the EPL file that Apama Studio generates. Also, in the body of the listener, enqueue an event to subscribe to the Web Service. For example:
on com.apama.adapters.AdapterUp(adapterName = service_id) {
enqueue SubscribeStatus(service_id,"","","");
}
Define a listener for an event that indicates that the Web Service is available to respond to requests. When the Web Service is availabe set up a listener for an event that you specified as the output event for an operation, that is, a listener for response messages from the Web Service. If the application depends on a correlation ID, this listener needs to test the value of the field specified as the correlation field. You can then invoke the Web Service by routing an event you specified as the input event for a particular operation. For example:
Status stat;
on Status():stat{
if (stat.available and stat.serviceID = service_id) then {
listenResponse();
route Stock("NASDAQ","MSFT","2011-07-12");
route Stock("NASDAQ","APMA","2011-07-12");
}
}
action listenResponse() {
StockValue stockRes;
on all StockValue():stockRes {
log stockRes.toString() at INFO;
}
WSError wsError;
on all WSError():wsError {
print "At service " + wsError.extraParams["serviceId"];
// wsError always contains service id
print "For the requested event " + wsError.requestEvent ;
print " got the error message as " + wsError.errorMsg ;
print " Failure message is " + wsError.failureType ;
// See WSConstants event for types of failure
}
}
The following code provides a complete example of how a monitor can invoke a Web Service in a private context. In this example, the monitor sends requests and listens for responses from the Web Service in a private context.
using com.apama.statusreport.Status;
using com.apama.ws.WSError;
using com.apama.ws.SetupContextListeners;
using com.apama.ws.TerminateContextListeners;
using com.apama.statusreport.SubscribeStatus;
/*
* Monitor that will spawn to a private context send requests,
* and listen for Web Service responses in that private context.
*/
monitor UsingContexts {
context privateContext;
constant string service_id := "Webservice_INSTANCE_1";
// ID that the Apama-Studio-generated EPL uses.
action onload() {
on com.apama.adapters.AdapterUp(adapterName = service_id) {
enqueue SubscribeStatus(service_id,"","","");
// Subscribe to Web Serivce.
}
Status stat;
on Status():stat{
if (stat.available and stat.serviceID = service_id) then {
spawnPrivateContext();
}
}
}
action spawnPrivateContext() {
privateContext := context("PrivateContext" , false);
// Create a private context.
// The application must send a SetupContextListeners event, which
// contains details such as the service ID (based on generated EPL)
// and information about the private context in which the monitor
// listens for service responses.
route SetupContextListeners(service_id,privateContext);
spawn sendAndListen() to privateContext;
}
action sendAndListen() {
print "Sending events to " + context.current().toString();
enqueue Stock("NASDAQ","APMA","2011-07-12") to context.current();
StockValue stockRes;
on all StockValue():stockRes {
log stockRes.toString() at INFO;
print "Terminating Private context service monitor";
terminatePrivateContext(); // Terminates service monitor in this context.
}
WSError wsError;
on all WSError():wsError {
print "At service " + wsError.extraParams["serviceId"];
// WSError always contains service ID.
print "For the requested event " + wsError.requestEvent ;
print " got the error message as " + wsError.errorMsg ;
print " Failure message is " + wsError.failureType ;
// See WSConstants event for types of failures.
}
}
action terminatePrivateContext() {
// The application must send a TerminateContextListeners event,
// which contains details such as the service ID and the private
// context that contains the service monitor that contains
// the service response listeners. When the response listeners
// terminate, the service monitor that contained them also terminates.
// The private context is still availabe to be used.
route TerminateContextListeners(service_id,privateContext);
//If a request is sent there should not be a response.
print "Sending request....expecting no response" ;
enqueue Stock("NASDAQ","APMA","2011-07-12") to privateContext;
}
}