package com.infor.cloverleaf.javadriver.samples.callback;
...
public class CallMeBack extends ToCloverleafLink {
private boolean runningB = true;
private Thread startThread = null;
@Override
public void doStart(String userS) throws Exception{
int idx = 0;
// debugger test for exception handling. To use this, set a wait in the driver control ini file, start the process, attach debugger
if (idx == 1) throw new Exception("debug test");
// this process just starts up and runs forever kicking off messages every 10 seconds
startThread = Thread.currentThread();
// create a "red" and "blue" callback handler
CallbackInterface redCallback = new CallbackInterface() {
public List<ToCloverleafMessage> doCallback(FromCloverleafMessage fromCloverleafMessage) throws BadDataException, RetryException {
System.out.println("RED callback executed at '" + (new Date()).toString() + "'and received message: " +
fromCloverleafMessage.getMessage());
return null;
}
};
CallbackInterface blueCallback = new CallbackInterface() {
public List<ToCloverleafMessage> doCallback(FromCloverleafMessage fromCloverleafMessage) throws BadDataException, RetryException {
System.out.println("BLUE callback executed at '" + (new Date()).toString() + "'and received message: " +
fromCloverleafMessage.getMessage());
return null;
}
};
// now register them as callback handlers
registerACallbackHandler("red", redCallback);
registerACallbackHandler("blue", blueCallback);
// loop and send out messages
while(runningB){
// send the message to cloverleaf, don't use recoverydb since this is just for testing
try{
Thread.sleep(10000);
// create a message to send
idx++;
// copy the int for the callback to remember (to demonstrate unique callback classes)
// A more realistic example of this need is in the CJDRequestServer where the callback
// has to remember the HttpResponse object to write back on (a stream essentially)
final int callbackInt = idx;
// create a unique callback to invoke for just this one message
CallbackInterface callback = new CallbackInterface() {
public List<ToCloverleafMessage> doCallback(FromCloverleafMessage fromCloverleafMessage) throws BadDataException, RetryException {
System.out.println("java callback " + callbackInt + " executed at '" + (new Date()).toString() + "'and received message: " +
fromCloverleafMessage.getMessage());
return null;
}
};
ToCloverleafMessage toCloverleafMessage = new ToCloverleafMessage(null, "", MessageTypeEnum.DATA, null, null, "callmeback message " + idx + " at " + (new Date()).toString());
sendToCloverleafWithUniqueCallback(callback, true, toCloverleafMessage);
/* now send a message to RED or BLUE registered callbacks, depending if idx is even or odd
* Whereas the unique callback can store any java object for later processing specific to the
* individual message (which is appropriate for stream and other temporary object handling), this
* mechanism should be used when processes could be long running or it is
* required that the messages should survive the thread being shut down and started
* up again later. For example, an asynchronous SOAP server could use something like this.
* You could add the message id and callback url into the driver control and extract that
* info in the callback handler for processing. Different services may need different
* handling which is why you might want to register different handlers and use them as needed.
* As long as the handlers are registered again when the server starts up after a shutdown, no
* messages will be lost.
*/
if (idx % 2 == 0){
toCloverleafMessage = new ToCloverleafMessage(null, "", MessageTypeEnum.DATA, null, null, "RED message " + idx + " at " + (new Date()).toString());
sendToCloverleafWithRegisteredCallback("red", true, toCloverleafMessage);
}else{
toCloverleafMessage = new ToCloverleafMessage(null, "", MessageTypeEnum.DATA, null, null, "BLUE message " + idx + " at " + (new Date()).toString());
sendToCloverleafWithRegisteredCallback("blue", true, toCloverleafMessage);
}
/* finally, send a message with automated callback handling. This demonstrates
* a manual callback where the callback is processed on another thread. The usage
* scenarios are similar to the registered callbacks but this lets you use another
* thread to handle the callbacks. You need to pass all the information the callback
* handler will need in the driver control or message body so your thread on the other
* side will know what to do with the message. Using the asynchronous soap server as
* an example again, you would pass the message id and the callback url in driver control
* here, then pull them out in the callback handling thread and use it to execute your
* response message to the waiting client.
* Technically the code here has no idea a "callback" type of scenario is even in play,
* as this thread just knows that it's dumping messages into the Cloverleaf engine. Your
* code will just process the driver control data appropriately to make it happen. Here
* we're just making up some arbitrary driver control data for the other side to use. The
* bounce thread is just looking for this data in the driver control to know where to send
*/
toCloverleafMessage = new ToCloverleafMessage(null, "MYCALLBACK " + idx + " messageid " + idx*17 + " url http://www.example.com:8080/callbackserver", MessageTypeEnum.DATA, null, null, "BLUE message " + callbackInt + " at " + (new Date()).toString());
sendMessagesToCloverleaf(true, toCloverleafMessage);
}catch (Exception e){
System.out.println("caught exception trying to sendToCloverleafWithCallback: " + e.getLocalizedMessage());
}
}
}