Java callout on the Oracle / AquaLogic Service Bus - Invoking static methods in any jar file

Jeroen van Wilgenburg

Sometimes a service bus is not sufficient for the job at hand. You can use EJB's and JMS queues, but that might be overkill. That's where a java callout might come to the rescue. This article will show you how to do a callout with 'complex' objects. On the bus you can pass around java objects or use them on the bus (this requires a small transformation step). I used the AquaLogic service bus version 10.2, but I think it should work any version that supports java callouts. The only difference can be the version of xmlbeans (AL 10.2 uses version 1.0.3)

At our customer we did a little proof of concept with a java callout but ultimately decided to go with another solution. The java callout however can be very useful so this article will show you how to get a head start with it. I assume that you have at least a little experience with the alsb and Maven 2. Creating a proxy service and editing a message flow should be sufficient.

The prerequisites for a java callout are simple. Any static method in a jar-file will do. You can even return your home made objects (they don't even have to be serializable). One downside is that you cannot do anything with these objects on the bus, they're just an object with an id. You can however pass these objects to another java callout and use them as your regular java objects.

The static method you want to call should be in a jar file that is loaded on the alsb (so it is NOT a library in WebLogic). It is allowed to put dependencies in this jar file, so in theory everything is possible. But idea is to keep it small and simple, otherwise go with EJB's and JMS with a library or application on WebLogic.

It is very inconvenient when you just can pass the objects around. There are however some type of objects that can be handled on the bus. Those objects  are primitives, String, BigDecimal, BigInteger, byte[], String[] and XmlObject. XmlObject is an object provided by the Apache Xml Beans framework and is basically an xml-representation of a java object. I know that converting an object to xml should happen on the bus and it would be nice when a java object can be passed to the bus, but this just isn't the fact and this is the cleanest solution I came up with.

Now that you know the theory let's get our hands dirty:

Preparation

Create a class with a static method and pacakge it in a jar file. I added the following maven dependency to an empty pom.xml:

<dependencies>
 <dependency>
 <groupId>xmlbeans</groupId>
 <artifactId>xmlbeans</artifactId>
 <version>1.0.3</version>
 <scope>compile</scope>
 </dependency>
</dependencies>

This will give you the Apache Xml Beans library at compile time. This library is excluded in the packaged jar because it lives in WebLogic.

The java class :

public class CalloutDemo {
    public static String getString(String input) {
		System.out.println("input: " + input);
		return "Buy a bicycle from " + input + "?";
    }

    public static XmlObject getCode(String input) throws XmlException {
		System.out.println("input: " + input);

		String xmlString = String.format("<root><mainCode>%s</mainCode><subCode>%s</subCode></root>", "mc", input);
		XmlObject instance = XmlObject.Factory.parse(xmlString);

		return instance;
    }

    public static Code getCode() {
		return new Code("hoofdCode", "subCode");
    }

    public static void printCode(Code code) {
		System.out.println("code: " + code);
    }
}

This class returns a main code and a sub code for an input String or just a new String based on an input String.
Apache Xml Beans is ued to return 'complex objects'. In this example I'll return a String and an XmlObject.

When you return a normal java object (ie. a domain object) and print this on the bus you will see something like this:
<con:java-content ref="jcid:5333178f:11fa2a0451c:-7fda" xmlns:con="http://www.bea.com/wli/sb/context"/>
It's just a pointer to an object. When you pass this pointer to another java callout it becomes an object again. It's not possible to do transformations or even view the java object on the bus, you can only pass it around (and probably only on the same VM instance)

No rocket science, just for the example. When you understand the code displayed above it's time to put everything on the bus. But first run the command 'mvn package' to compile the project and create a jar.

On the bus

Open the AquaLogic service bus console (I'm using the web interface by the way).
Create a session with the create button. Then create a new project in the Project Explorer (I called mine callout-test)
Click on callout-test in the project tree and create a jar resource.
Give the resource a name (ie. callout-test-jar) and upload the jar maven delivered to you (from the target folder).
When the jar is uploaded it's possible to browse the jar. You will see your brand new class with al its methods.
Now create a new Proxy Service (callout-ps), just give it a name, click last and then save.
Edit the message flow and add a pipeline pair. Add a stage at the request pipeline. Edit that stage and add an action:
Message processing, Java callout.
When you click on <method> it's possible to pick your jar and choose a method. The first method I want to show is  public static java.lang.String getString(java.lang.String). For the input expression enter xs:string('Harrie').
In real life this is a value somewhere from the bus of course.
Give the result String the name result, we can use that value later on.
Click on the icon left of Java Callout and add an Alert action. At the expression enter $result and leave the summary empty.
Make sure you save everything and activate the session.

java-callout-1

Putting it to the test

When everything is saved it's time to test the proxy service. Find the proxy service in your project explorer and click on the debug icon (the little bug icon in the action colum). Since we created an any xml-service it's okay enter anything in the payload field as long as it's xml. Click the execute button and you'll get the response you entered in the payload field. Of course we want to see what happened internally.
Click on home and then pipeline alerts. There probably is a new alert named 'AquaLogic Service Bus Alert' with a timestamp of a few seconds ago. Click on this alert and you'll see the new String in the Description field:

java-callout-2

Since we used System.out.println (I know it's evil, but I wanted no dependencies in my little jar) the server console shows:
input: Harrie

The next step

Now of course it's time to use the 'advanced' xml.
Re-open the flow of the proxy service, click on Stage1, click Edit, click on the getString method and change it to getCode (the one that returns XmlObject).
Enter xs:string('Arie') at the expression. Since the method is returning xml we can print the part of the message we want. Enter $result/subCode at the Alert message (or $result/subCode/text() if you just want the text without xml tags, but alerting the text you just entered isn't cool 😉 )
Save and activate and repeat the steps from 'Putting it to the test'

It's easy to predict what happens now.

Unfortunately we didn't find use for the java callout at our project, but it's pretty cool nonetheless.

Disclaimer

I used the term alsb and AquaLogic Service Bus in this article, it's probably called Oracle Service Bus. But everyone I know still talks about the AquaLogic Service bus.
I started this article a while ago and since Oracle removed edocs.bea.com I can't show you the sources where I got my information from.

Comments (3)

  1. nripa - Reply

    May 24, 2010 at 5:15 pm

    Hi

    Thanks for article.
    Useful for java developer who wants to enhance his skill by implementing alsb as well.

    I am one of them . If any body can provide me useful link on the same , Thanks in advance :).
    my id - nripa1@gmail.com

  2. Jhon Jairo Gamboa - Reply

    March 5, 2012 at 11:27 pm

    Hi, good post, but i need return a collection (List), how i do for read or convert to list in OSB message flow ?

    tks

  3. Flavio - Reply

    January 2, 2013 at 6:19 pm

    Hello Jeroen...

    I'm having a trouble... i tell you : In a ProxyService i make a JavaCallout which have 3 methods... here is the thing, in the Production Server, it works perfectly, BUT , has been created a new domain of Production Server , and on this , my Proxy Service see the .jar but doesn't see the methods.

    All the libraries and JARs are the same in both domains.

    Do you have any idea ?

    Thanks...

Add a Comment