Tuesday 6 January 2015

It's Spring for Oracle ACM API's

Before the holiday season I was working on a service to receive e-mails in BPM using the UMS-email-adapter. Then process the attachments and the body and upload them to the Oracle ACM-case the email was meant for.

I won't get in too much detail here, since there are some articles on the use of ACM-API's like the ones of Niall Comminsky.

Unfortunately, until now, there are no WSDL/SOAP or REST services available on the ACM-API's, as they are on the Workflow Task API's.

However, it is not so hard to make the API's available as services. The trick is to wrap them up in a set of Java-beans, with one class with methods that do the jobs and create 'request and response beans' for the input parameters of the methods and the response.

A few years ago I wrote an article on using Spring components in SOA Suite 11g. This approach is still perfectly usable for SOA/BPM12c. And gives you a WSDL interface on the API's in near to no time.

There is one remark on the API's, though. That is on the creation of the the ACM Stream Service, or actually the creation of the BPMServiceClientFactory to get the context.

In the blog of Niall you'll read that you need to set the following context-properties:

        Map properties =
            new HashMap();
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,
                       BPMServiceClientFactory.REMOTE_CLIENT);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL,
                       "t3://localhost:7001");
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS,
                       cPwd);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL,
                       cUser);
        caseMgtAPI.mServiceClientFactory =
                BPMServiceClientFactory.getInstance(properties, "default",
                                                    null);
Since in my case the service is running on the same server as the BPEL/BPM/ACM Process Engine is running, there's no need to create a connection (and thus provide an URL) and to authenticate as EJB_SECURITY_PRINCIPAL. So I found that the following suffices:
        Map properties =
            new HashMap();
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,
                       WorkflowServiceClientFactory.REMOTE_CLIENT);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_INITIAL_CONTEXT_FACTORY,
                       "weblogic.jndi.WLInitialContextFactory");
        BPMServiceClientFactory factory = BPMServiceClientFactory.getInstance(properties, null, null);
I would expect that  'WorkflowServiceClientFactory.REMOTE_CLIENT' should be'WorkflowServiceClientFactory.LOCAL_CLIENT', but need to verify that. The code above works in my case.
Update 12-1-2015: When using LOCAL_CLIENT I get the exception:
oracle.bpm.client.common.BPMServiceClientException: Cannot lookup Local EJB from a client. Try annotating it in the referred EJB. Veroorzaakt door: oracle.bpm.client.common.BPMServiceClientException: Cannot lookup Local EJB from a client. Try annotating it in the referred EJB.
So apparently you need to use REMOTE_CLIENT.

You do need to authenticate with the BPM user that is allowed to query the case, upload documents  etc. as follows:
 context = bpmFactory.getBPMUserAuthenticationService().authenticate(userName, userPassword.toCharArray(), null);
Hope this helps a little further in creating services on ACM.

No comments :