Sunday, November 18, 2007

Invoking EJB from a BPEL process using WSIF

BPEL is about integration. It is about standard governed by a world body. It is about Open standards. I am helping one of my clients with BPEL integration with system interfaces ranging from JMS, Relational Database, E-Business suite, FTP/File and EJBs. And I recently got a call about HTTP posts, but thats for a later day. Oracle's BPEL process manager has pre-defined adapters for almost all the interfaces we can think of. If not, then it provides an Embedded Java Activity that can be used to write custom codes. I found some challenges with EJB. Oracle BPEL PM implements these integration using Apache's WSIF infrastructure. WSIF requires system's interface to be exposed as a WSDL. Quite powerful it is as it can be done for standalone Java APIs to services exposed as EJBs. But as lazy-ass I am, I do not want to hand-write WSDLs. Oracle has a product WSA which makes life much easier. Following are the steps to be taken with caveats and bugs/problems I ran into.

1. With every Oracle application server installation you would find a wsa.jar in the $ORACLE_HOME/webservices/lib directory. wsa.jar can be used to generate WSDL for the EJBs.

2. Problem (1): The EJB interface has to implement javax.rmi.Remote interface and its' methods has to throw RemoteException. Anyone who is familiar with EJB3.0 specification knows that its not required anymore. On top, the EJB implementation does not even need to implement any interface as long as @Remote annotation defines what interface to expect. Quite a powerful specification indeed. Unfortunately WSA needs to catch up a little. Not too behind though.

3. So if you have a fancy EJB and you have a control over its' source code, make sure you make the changes described in step (2).

4. Run the following command:

java -jar wsa.jar -genWsdl -output <directory> -wsifEjbBinding true \
-style rpc -use encoded \
-jndiName SessionEJB -jndiProviderUrl ormi://localhost:12401/<context_name> \
-initialContextFactory oracle.j2ee.rmi.RMIInitialContextFactory \
-interfaceName <EJB_INTERFACE> -className <EJB_CLASS_IMPL> \

5. The WSDL is generated in the directory specified. Edit the file to remove any HttpSoap ports and bindings. Another a must to note is only RPC-encoded style of WSDL has to be generated.

6. Now, in the BPEL process add a partner link and import this generated WSDL. Invoke the appropriate methods.

7. Make sure in the bpel.xml file EJB authentication/credentials properties are set for the EJB partner link.

<partnerLinkBinding name="IEJBA">
<property name="wsdlLocation">IEJBARef.wsdl</property>
<property name="">oc4jadmin</property>
<property name="">admin123</property>

8. Make sure the EJB classes are in the CLASSPATH for bpel process to find out.

Deploy the EJB and deploy the BPEL process.

Problem (2):The wsa.jar does not work with EJB2.1. If you create an EJB2.1, its' interface extends EJBObject which extends Remote. But wsa.jar fails on methods it does not understand part of EJBObject. I highly discourage hand-writing WSDL for even simple interfaces, the task becomes daunting for complex ones. Of course either I do not understand something or it is an unsupported feature in WSA. Hope soon to be resolved.
Solution:I encourage to change the EJB version to 3.0 if it is under control and can sell the advantages to your business units. With little faith they usually have on its' IT, there exist a work around. With all the dislikes I have for vertical stacks we still can introduce a custom EJB3.0 deployed locally which in turn can invoke the EJB2.1 internally. The BPEL process instead of talking to 2.1 can talk to 3.0 and 2.1 problem can be circumvent.
The other solution is to use jDeveloper that has a graphical interface that lets you choose the methods you want to import. When WSDL is generated this way, you can deselect the methods specific to EJBObject interface.

No comments: