Saturday, March 22, 2008

Programmatically determining BPEL manual recovery status

It's been a while since I've written an article, and I hope no one has been waiting all this time for part 2 of my BAM/BPEL alert article. I promise to complete that write up soon.

Today, however, I'd like to talk about an interesting problem I ran across this week. If anyone has experience with Oracle's BPEL product you know that sometimes BPEL processes can go to manual recovery. The two most common issues are: 1) an issue on the invoke of the process (BPEL server Out of Memory error for example), and 2) an issue with the callback on an asynchronous BPEL process.

BPEL process manager has a nice UI for looking at and managing these, but what if we need to be alerted when a process goes into one of these states? Well, BPEL PM doesn't have that capability, so we need to write our own. Another useful thing might be to always clear the processes, especially those that are in manual recovery for callback. Typically in that situation the callback failed, most often because the original calling process is no longer around to receive the callback.

In the rest of the article we talk about finding processes in both invoke and callback manual recovery. For both cases, it will be necessary to get a reference to the Locator object via the BPEL Java API. I talk about that in an earlier post, so I've assumed that you've read up on that before continuing.

Getting process manual recovery for inoke:

            String Buffer buf = new StringBuffer();

WhereCondition where = new WhereCondition(buf.append(SQLDefs.IM_state).append( " = " ).append(IDeliveryConstants.STATE_UNRESOLVED ).toString() );

IInvokeMetaData imd[] = locator.listInvokeMessages(where);

String ids[] = new String[imd.length];

// print out the partial process information
// for processes in manual recovery status on invoke
for (i = 0; i <>
{
System.out.println("ConversationId=" +
imd[i].getConversationId());
System.out.println("ProcessId=" +
imd[i].getProcessId());
System.out.println("State=" + imd[i].getState());

ids[i] = imd[i].getConversationId();
}

// if we wanted to automatically recover these processes
// we would uncomment the following line:
// locator.lookupDomain().recoverInvokeMessages(ids);

That's it! For callbacks the code flow is the exact same. Instead of IInvokeMetaData, we get an array of ICallbackMetaData using the locator.listCallbackMessages(where) method. One other slight change is the where clause itself -- for callbacks the where clause should be built as:

WhereCondition where = new WhereCondition(buf.append(SQLDefs.DM_state).append( " = " ).append(
IDeliveryConstants.TYPE_callback_soap ).toString() );

The last change for callbacks is how they are recovered -- locator.lookupDomain.recoverCallbackMessages(ids) will do the trick!

Using the API's above you can see how we could build a custom notification process or an automatic or work flow based recovery method that does not involve the actual BPEL PM.

No comments: