ESBREQUEST in Oracle ESB Routing Services

Oracle’s Enterprise Service Bus (ESB) is designed to implement service-oriented architecture (SOA) and event-driven architecture (EDA), providing a responsive, low-cost, high-impact framework for matching technology needs to business problems.

One of the powerful capabilities of Oracle’s ESB is the ‘Routing Service’ which caters for service virtualization through content based routing. It supports one way and request response operations. One of the challenges with service virtualization and the request response pattern is matching the response from the implementation service to the response that the routing service should return. There is no easy answer to this one, but the Oracle ESB provides some help. One is the transformation capabilities, but you would expect this from any ESB system. The really useful feature is being able to refer to the request in the response transformation. Oracle ESB does this by declaring a parameter to the XSLT called $ESBREQUEST.

Elements in the request can be referred to through XPATH. For example:

This is great, but there are a few things I need to draw to your attention:

  1. $ESBREQUEST refers to the root element of the request sent to the service implementation and not the request sent to the routing service. So, if your implementation service request structure is DoMethodRequest/MyParam then refer to MyParam as $ESBREQUEST/MyParam not $ESBREQUEST/DoMethodRequest/MyParam.
  2. You need to enter the XPATH manually because the mapper does not know the structure of the request.
  3. You have to specify ‘Include Request in the Reply Payload’ when defining the routing rule. This can not be added to the routing rule or XSL file through the tools afterwards.

The latter point is what I really wanted to cover in this article. At the moment, in version 10.1.3, you can not retrospectively ‘Include Request in the Reply Payload’ using the JDeveloper or the ESB console. When you use JDeveloper the first time it puts
in the XSL file and sets attachRequestPayload=”true” in the transformation element of the routingRule section of the routing service esbsvc file.

So, you can do this manually to retrospectively add ‘Include Request in the Reply Payload’ to your existing routing rules. Unfortunately the only way I have found to update the running ESB routing service routing rules with these changes is to to delete the routing service (through ESB console), shutdown JDeveloper, edit the esbsvc file manually, restart JDeveloper and then register the ESB project with the integration server.

The Oracle Mapper tool in JDeveloper which is used to edit XSL files does understand the parameter concept, so you can test your stylesheet in JDeveloper before deploying it. Just open the XSL file in JDeveloper, right click in the design view and select Test. Be sure to enter the ESBREQUEST parameter as an XML fragment. Don’t forget that ESBREQUEST corresponds to the request structure sent to the service implementation and not the request received by the routing service!

This ESBREQUEST parameter gives you the benefit of manipulating the reply such as returning correlation information or using the data from the request to perform filtering and other manipulation that the service implementation does not provide.

Should you wish to use data from the original request received by the routing service then you have to add elements manually to the request transformation. This will work at runtime if the implentation service doesn’t validate the request for extra elements not part of the schema. However, once you add these elements to the XSL transformation you will not be able to use the JDeveloper mapper as it does validate the target document structure against the schema.

More problems with Dice service on WLS

As mentioned before, the Dice service does not auto deploy on WebLogic Server 10. According to the WLS Web Service documentation a weblogic ant task ‘JwscTask’ is needed to compile the annotated web service and produce the necessary WAR and EAR for deployment.

The build script I put together looks like this:

It successfully builds and deploys the web service. The deployed web service endpoint is /Dice/Dice so the service name makes up the context and the servlet url-pattern. As mentioned in a previous post both JBoss and OC4J default the servlet url-pattern to diceserviceport while Glassfish defaults to DiceService.

Also of note is that the WSDL on WLS is so different from the others by using the SOAP array type and ignoring the Die structure in the schema. That means that the size attribute is missing.

The big thing to note though is that there is a runtime error when trying to test the web service:
com.bea.xbean.values.XmlValueOutOfRangeException
at com.bea.xml.soap.SOAPArrayType.
at com.bea.staxb.runtime.internal.LiteralUnmarshalResult.extractSoapArrayType

So the mystery tour continues. I might just try the top down route based on a WSDL from the Dice service deployed on another platform. Naturally, I will keep you posted.

Dice Service does not auto deploy on WLS 10

I really wanted to see if WLS 10 would auto deploy the Dice Service WAR file just as easily as the OC4J, JBoss and Glassfish containers did. Since my early J2EE days (I started developing with Tengah WebLogic before BEA bought the small San Francisco based company) WLS has been a platform of choice for me. However, I have found that the Dice Service does not automatically deploy on WLS like it does on the other platforms.

The deployment error is:
weblogic.application.ModuleException: [HTTP:101216]Servlet: “DiceServicePort” failed to preload on startup in Web application: “WebServices.war”.
javax.servlet.ServletException: Servlet class: ‘soastation.jaxwsdice.Dice’ does not implement javax.servlet.Servlet

This will require some investigation, perhaps running through some of the WLS JAX-WS examples to find out what it’s real dependancies are. Watch this space.

Greater web service independence with JEE 5

One of the reasons I did the Dice web service example was to see if it really was possible to build a JEE 5 POJO web service (all be it a simple one) and deploy it in different JEE 5 containers without having to maintain separate deployment descriptors, or test classes, for the target platforms. The answer is a yes! Although it is a slightly qualified yes. More on that below, here are the target platforms first:

  • OC4J 11g Technology Preview (standalone version packaged in JDeveloper)
  • Glassfish v1 ur1 p01
  • JBoss 4.2.0 GA

The same WAR file built in JDeveloper 11g Technology Preview will deploy on all three containers without modification. To create the WAR file I followed the steps in the HelloService tutorial. However, I did have to change the project properties to set the output directory to public_html/WEB-INF/classes/ otherwise the classes would not be packaged in the WAR.

Deploying the web service on OC4J is covered in the tutorial. Deploying on the other platforms is just as easy, just take advantage of the auto deploy features by dropping the WAR file into the relavant directory of the running server:

  • Glassfish: glassfish/domains/domain1/autodeploy
  • JBoss: jboss-4.2.0.GA/server/default/deploy

It is worth taking a look at the WAR file as the only things in it are the classes (Dice and Die) and the web.xml which registers Dice as a servlet (DiceServicePort). It is the JAX-WS annotations on the Dice class that tell the container it is a web service and the container takes it from there generating WSDL, etc.

The service works on all three platforms without modification, which is good. However, there is difference in the WSDL files for each platform and that’s the qualification mentioned earlier. The end point structures are different. JBoss and OC4J keeping the servlet url-pattern and Glassfish opting for the service name (i.e. DiceService). This is only a slight difference as everything else remains the same. In fact you could generate a web service proxy client from one WSDL and use those proxy client classes for invoking the service on another platform. Just change the ENDPOINT_ADDRESS_PROPERTY. This is reassuring as the code and interface have not changed, only the platform. This is not a problem at all if test cases have the web service end point externalised.

One thing I need to point out here for those wanting to reproduce the excercise, I had to use JDeveloper 10.1.3.2 to generate the DiceServiceProxy classes because 11g Technology Preview version would treat the service ‘roll’ operation as a one way method and not return a response.

So there you have it. JEE 5 has brought us a step closer to build and test enterprise software components without the overhead of maintaining platform specific artefacts. Given more time I would try some more JEE 5 containers. Suggestions welcome.

JAX-WS & JAXB rock and roll…

During his Wednesday keynote at the JavaOne conference last week, Oracle Senior Vice President Thomas Kurian unveiled the next-generation architecture for Oracle Fusion Middleware. The 11g Technology Preview of JDeveloper and OC4J are currently available. Also available are some nifty tutorials and demos like Web Services Development in Oracle JDeveloper which shows off some great JEE 5 features like JAX-WS and JAXB 2.0. Although the latter is not really focused on much in the tutorial, it is the basis of what gets your java objects to and from XML.

What these two standards bring to the table from a web service development point of view is a more lightweight POJO oriented way of developing services. They will not make for better SOA in the enterprise though. In fact, they may even make things worse since a poorly designed interface can easily get a false SOA badge of credibility amongs the uninitiated by being exposed as a web service. Enough with the rant already, on with the example…

I thought it would be interesting to expand upon the bottom up HelloService tutorial by making things a bit more complicated with some old world technology: Dice. The Dice class in this example has a roll(List) operation that rolls the dice (plural of die) passed to it and returns the result. So there are really only two classes in this example:

  • Die represents (you guessed it) a die. It has two properties, number of sides and value.
  • Dice provides the collective operation of rolling dice.

This is the Die source:

package soastation.jaxwsdice;

public class Die {
protected int numberOfSides;
protected int value;
public Die() {
this(6); //Default number of sides is Six;
}
public Die(int sides) {
if (sides < 2)
throw new throw new IllegalArgumentException();
this.numberOfSides = sides;
}
public int getNumberOfSides() {
return numberOfSides;
}

public int getValue() {
return value;
}

public void roll() {
int rollValue = (int) (this.getNumberOfSides() * Math.random()) + 1;
if (rollValue > this.getNumberOfSides())
rollValue -= 1;
this.value = rollValue;
}
}

Note that the number of sides property is immutable and the value defaults to zero until the die is first rolled. It would seem natural to extend something like Integer to hold the ‘value’. This can’t be done in Java as these classes (Number, Integer, BigInteger, etc) are immutable so changing the value on every roll is not a runner. Besides, Integer is final so can’t be extended anyway.

You’ll probably also note the lack of comments on the code too. Tell me if you are for or against comments in code!

Here is the Dice source:

package soastation.jaxwsdice;

import java.util.Iterator;
import java.util.List;

public class Dice {

public List roll(List dice) {
Iterator diceIterator = dice.iterator();
while (diceIterator.hasNext()) {
Die die = diceIterator.next();
die.roll();
}
return dice;
}
}

The rest of the steps are identical to the HelloService example (which you can also get to from the Build Web Service link on the Start page of the JDeveloper 11 Technology Preview ).

  1. Add an @WebService annotation to the Dice class
  2. In the code fix menu select Configure project for web services
  3. Choose the Java EE 1.5 option and press OK
  4. Add an @WebMethod annotation to the roll method
  5. Right click on Dice service (note that the icon has changed) and select Test Web Service
  6. Gaze in awe at the handy HTTP Analyzer with Web Service support. That’s all you can do at this stage because JAX-WS doesn’t know what to do with the Die class.

This is where JAXB really comes into play. We want the properties of the Die object to be properly represented in the web service. Lets make the number of sides an attribute and the value of the Die appear as the value of the element. Do this by:

  1. Add @XmlAttribute(name=”sides”) to the numberOfSides field.
  2. Add @XmlValue to the value field.

Now you can test the web service again by right clicking on the Dice service in the Applications Navigator and selecting Test Web Service. In the HTTP Analyzer window you can enter the details of each die you want to roll. By clicking on the plus sign you can add more die to the SOAP request. The value attribute is in the schema but has no relavance to the operation (unless you want to implement a LoadedDie object?). Actually, you could leave the number of sides blank too as it will default to 6.

This example takes advantage of convention over configuration features of JEE 5. The property inspector in JDeveloper 11g Technology Preview provides some great tooling around the annotations. It is worth playing with it to see the extent of configuration possible.

We can improve the WSDL and XML representations with annotations. In the Dice class add a @WebResult(name=”die”) annotation to the roll method so that the result is not called ‘result’ by default. Also, in the roll method arguments add @WebParam(name=”die”) annotation so that the die element does not get call ‘arg0’ by default.

These JAX-WS and JAXB annotations make the web service and XML representation of the java operation and classes much more suitable. Of course these simple examples only scratch the surface of what can be achieved. It is a good idea to get familiar with capabilities of both technologies.

Let me know how you get on.