Announcing: Technology Preview for SOA Suite 11g

Within the past week the 3rd technology preview of JDeveloper 11g was made available on the Oracle Technology Network (OTN) website. For me, the most significant aspect of this preview is that it includes a preview of the long awaited SOA Suite 11g which supports the Service Component Architecture (SCA) specification. This Technology Preview release of Oracle SOA Suite 11g showcases the support for SCA through the new composite assembly editor in JDeveloper as well as a unified service engine foundation for the full set of SOA Suite components.

The SOA Suite 11g software is available within the JDeveloper 11g environment – yes, that’s right! You only install JDeveloper and you also get the SOA Suite server side for deploying your 11g composite applications!

Go to OTN for instructions and details for the SOA Suite 11g Technology Preview. Be sure to read the Quick Start & Installation Guide and remember that you will need an Oracle database installed. This one is definitely worth taking for a test drive!

JAX-WS Handlers

Web service handlers are not a new concept. One obvious issue with developing a web service is catering for common behaviour. If each operation requires the same set of services, such as security or logging, how do you provide those services? A web service handler is the solution for both common client-side as well as server-side behaviour. Handlers allow you to process SOAP messages before and after the message is sent through the network.

Web service handlers are a part of the JAX-RPC specification, and the JAX-WS specification caters for the same concept, but in a slightly different way. There are some handler examples on the net but most just deal with logging the request and response. This article will introduce something a bit more complicated, putting a Software As A Service handler on the Dice web service. For an overview of JAX-WS handler infrastructure, as well as the difference between SOAPHandler and LogicalHandler see the excellent Handlers Introduction on java.net.

In this Dice SAAS example JDeveloper 11g Technology Preview 2 is used. It supports JAX-WS and has an embedded OC4J server for running the web service. To get started, download the Dice project, which is ready to go with the annotated web service code and add it to your JDev workspace. Details about the Dice web service and how it is constructed can be found in a previous article.


The first thing to do is test that the web service works in your environment. To do this launch the Test Web Service utility by right clicking on the Dice web service in the Application Navigator.

This will start the embedded OC4J server, deploy the web service and launch the HTTP Analyzer with the WSDL for the Dice web service loaded. In the SOAP Structure panel enter a number of sides for the Die and press the Send Request button. Of course you can choose to add more Die by clicking on the + symbol beside the die: Array, or editing the request in the HTTP Content panel.

After pressing the Send Request button you should see the response showing each Die and their value after rolling.

Once you have that working you can move on to writing a handler class and configure the web service to use it. In this example, the SOAP handler class will use resource injection (i.e. @Resource annotation and environment entry elements) for initialisation parameters rather than using the init-params element in the deployment descriptor. This is a little emphasised difference between JAX-RPC and JAX-WS.

There is one more download to get for this example, the handler class and the handler chain descriptor which refers to it. A handler chain defines a set of handlers that should be used for the web service. The web service implementation will have an annotation stating where the handler chain descriptor file is. Extract these two files to the project. To use them add the following to the Dice.java, just after the @WebService annotation:

@HandlerChain(file = “DiceService-HandlerChain.xml”)

Note that you will need to import javax.jws.HandlerChain.

The SaaSServerHandler class in this case checks that the calling client is allowed to invoke the web service by looking in the SOAP header for a ‘key’ element with a namespace of urn:soastation:saas. It will also check that the value matches a ‘ValidKeyValue’ environment entry in the web app deployment descriptor. You could further modify the handler to only allow a single Die element in the SOAP envelope if no valid key is provided. That is, a client with the key can use multiple Die while a client without, such as a guest or demonstration client can only use one. Alternatively you could keep track of registered keys and usage. The software as a service options are endless.

Back to the example, looking at the SaaSServerHandler the handleMessage method checks if the message is inbound (request coming in) or outbound (response going out). If the handler was being used for a web service client the outbound message would be the request being sent and the inbound message would be the response beng received. In our example we are interested in the inbound message because we are expecting a particular element. Note that the handler class has a instance variable called saasKeyValue which is set be the ‘ValidKeyValue’ environment entry. To set this, edit the web.xml and add the following:



eValidKeyValue
java.lang.String
soastation

Test the web service as before. You should get the following fault:

javax.xml.ws.WebServiceException: Invalid service key in SOAP Header. Expecting {urn:soastation:saas}key

Now test it again, but add the required element to the SOAP header. To do this edit the request in the HTTP Content tab. The request should look like this:




soastation







The corresponding result should be the same as when you originally tested the web service before adding the handler. If so, you have successfully implemented the soap handler.

This article discussed how to implement a server side JAX-WS SOAP Handler using the second technology preview of JDeveloper. It has provided code examples of how the handler concept work, including externalising properties in the environment entry elements. Also mentioned were ideas for further development such as reducing the capabilities for ‘guest’ clients. There really is a lot one can do with web service handlers.

trailing block elements must have an id attribute

A couple of weeks back some colleagues working on a POC came across this runtime error when invoking a web service through a generated web service proxy client:

trailing block elements must have an id attribute

This exception was being thrown within the web service proxy client when parsing the response from the web service. Using HttpAnalyzer in JDeveloper (versions 10.1.3.1 & 10.1.3.2 were used) we could see that the request was being sent and a response was being received, so clearly nothing wrong with the web service being invoked. Or so we thought…

It turned out that the published WSDL & XSD and the web service implementation were not matching. The XSD for an element in the response said that Address had a maxOccurs=”1″ however, the web service implementation was returning multiple Address elements. The web service proxy client is generated from the WSDL & XSD so it is only expecting one Address element in the response stream, hence the error at runtime.

We had to double check which was correct, and a quick check through documentation showed that the schema had not been updated when the object model had changed. Once that was determined, it was straight forward to correct the schema entry, maxOccurs=”unbounded”, and regenerate the web service proxy client.

So, if you get this obscure ‘trailing block elements must have an id attribute’ error message at runtime double check that the published interfaces (WSDL & XSD) match the implementation.

Custom XSLT functions in Oracle BPEL and ESB

In the Oracle SOA Suite there is a Custom XSLT function example. You can find it in bpel/samples/demos/XSLMapper/ExtensionFunctions. It is not immediately obvious that this approach of enabling access to static methods on a java class works for transformations in the ESB too. This is because both BPEL and ESB use the same Oracle XSLT processor.

The principle is simple:

To illustrate how straight forward this is I’ll go through an example that converts HEX to Decimal. So, with a class called xsltfunctions.HEX2DEC the namespace is defined in an XSL file as xmlns:sample = “http://www.oracle.com/XSL/Transform/java/xsltfunctions.HEX2DEC”.

The class HEX2DEC has static method called toDecimal:


public static String toDecimal(String hex) {
String dec = new BigInteger(hex, 16).toString(10);
return dec;
}

In the XSL file this method is invoked like this:

Note that the namespace prefix ‘sample’ is defined as mentioned earlier using the http://www.oracle.com/XSL/Transform/java/ combined with the classname.

So, you could compile the HEX2DEC class, add it to a jar and put that jar in /j2ee/home/applib so that any transform using the custom function in BPEL or ESB will work. It’s that simple.

All that’s left is to inform JDeveloper of your custom function so that you can easily refer to it in the XSL Mapper to do this you need to do two things:

  1. Create an XML file detailing the extension functions you have and tell JDeveloper about it in the “User Defined Extension Functions Config File” field of the XSL Map preferences (Tools->Preferences->XSL Map). This will list the functions in the User Defined Extension Functions section of the XSL Map component palette so you can drag and drop it into the XSLT at design time.
  2. Add the class to the JDeveloper classpath so that you can run the transform using the test feature with JDeveloper.

The extension functions XML looks like this:

To add the class to the JDeveloper classpath involves defining a JDeveloper extension. For JDeveloper 10.1.3.2 the extension needs to be a valid JSR 198 extension. Documentation on this can be found in /doc/extension/ide-extension-packaging.html.

Do this by defining a simple ‘extension.xml’ like this:

<extension version="1.0" esdk-version="1.0" id="xstlfunctions"
xmlns=”http://jcp.org/jsr/198/extension-manifest”&gt;
SOAStationXSLTFunctions
Peter O’Brien

The extension.xml (naming convention for these files) needs to be in the meta-inf folder of the jar containing the classes. The filename for the jar needs to be a combination of the extention id and esdk-version so in this case it would be xsltfunctions.1.0.jar. This jar should then be copied into the /extension directory.

Restart JDeveloper to pick up the changes for both the ‘User Defined Extension Functions Config File’ and the JDeveloper extension and you’re ready to go.

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.