Multiple ORDS instances in WebLogic Server or Apache Tomcat

ORDS 22.1.0 introduced a substantial set of changes: Java 11 as minimum, new command line interface and a new configuration directory structure. In fact it is a release that introduces a whole new deployment paradigm.

Deployment Options

What we knew as Standalone Mode in previous ORDS releases still exists and is now initiated through a serve command. The embedded Eclipse Jetty web server and servlet container engine is still at the heart of this convenient way to have ORDS listen HTTP/HTTPS traffic. The significant change is how the configuration directory is determined at startup. There is no longer a requirement to modify the distributed ords.war to set the configuration directory location.

Deployment on a supported servlet container, such as Oracle WebLogic Server or Apache Tomcat, is similarly impacted by this principle that the distributed ords.war should not be modified. A new mechanism for specifying the configuration directory when the application is deployed is required. The ORDS documentation covers the standard approach for a typical setup, use a Java System Property ( -Dconfig.url=/ords_config/ ), startup your server(s) and deploy the web application.

Single Server

For some developers that may not have a full production environment scaled out for high availability, or may be restricted in the Apache Tomcat or WebLogic Server deployment options, the approach to set different servers with their own ords.war and configuration is not always feasible. With previous ORDS releases they may have had the practice of deploying multiple ORDS web applications with different contexts and configurations. At first it would appear that the new direction in ORDS 22.1.0 makes that impossible but it is not. All that is required are a few extra steps.

Bake your own

For deploying to Apache Tomcat or WebLogic Server you can make your own, separate web application with the config.url baked in. Moreover, you can call it whatever makes sense in your context.

Heres a Python script to do that for you: create_deploy_war.py

This script produces a new web application archive file with the jars from the distributed ords.war and web.xml deployment descriptor has the configuration directory path set. That way, wherever it is deployed, it will refer to the specified configuration directory.

Usage: create_deploy_war <source ords.war> <destination war filename> <configuration directory>

For example, if I want to have two ORDS instances deployed called tom and jerry with two separate configuration directories and I have extracted the ORDS 22.1.0 to /opt/oracle/ords-22.1.0.105.1723/. The jerry web application will be configured with a default pool pointing to an Oracle 19c database. The tom web application will be configured with a default pool pointing to an Oracle 21c database. We will show both web applications have these configurations by using the REST Enabled SQL service in ORDS to return database version information. Before that, the web application files must first be created…

./create_deploy_war.py /opt/oracle/ords-22.1.0.105.1723/ords.war /scratch/ords_webapps/tom.jar /scratch/ords_configs/tom/
./create_deploy_war.py /opt/oracle/ords-22.1.0.105.1723/ords.war /scratch/ords_webapps/jerry.jar /scratch/ords_configs/jerry/

That will produce two web application war files in /scratch/ords_webapps/ and I can then deploy them…

Oracle WebLogic Server

Two ORDS web applications deployed to a single WebLogic Server
curl -u hr:hr http://localhost:7001/jerry/hr/_/sql

{
   "database_major_version" : 19,
   "database_minor_version" : 0,
   "database_product_name" : "Oracle",
   "database_product_version" : "Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production\nVersion 19.3.0.0.0",
   "env" : {
      "defaultTimeZone" : "GMT",
      "ordsVersion" : "22.1.0.r1051723"
   }
}
curl -u hr:hr http://localhost:7001/tom/hr/_/sql

{
   "database_major_version" : 21,
   "database_minor_version" : 0,
   "database_product_name" : "Oracle",
   "database_product_version" : "Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production\nVersion 21.3.0.0.0",
   "env" : {
      "defaultTimeZone" : "GMT",
      "ordsVersion" : "22.1.0.r1051723"
   }
}

As you can see from the above, the different web applications have different context paths and are configured to use two different databases.

Apache Tomcat

Two ORDS web applications deployed to Apache Tomcat
curl -u hr:hr http://localhost:8080/jerry/hr/_/sql

{
   "database_major_version" : 19,
   "database_minor_version" : 0,
   "database_product_name" : "Oracle",
   "database_product_version" : "Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production\nVersion 19.3.0.0.0",
   "env" : {
      "defaultTimeZone" : "GMT",
      "ordsVersion" : "22.1.0.r1051723"
   }
}
curl -u hr:hr http://localhost:8080/tom/hr/_/sql

{
   "database_major_version" : 21,
   "database_minor_version" : 0,
   "database_product_name" : "Oracle",
   "database_product_version" : "Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production\nVersion 21.3.0.0.0",
   "env" : {
      "defaultTimeZone" : "GMT",
      "ordsVersion" : "22.1.0.r1051723"
   }
}

Similar behaviour with Apache Tomcat with two different web applications with their own, separate, configuration.

Summary

What I have demonstrated is a script which produces a new web application for deployment in Apache Tomcat or WebLogic Server. The script is written for Python 2 because that’s the version distributed with Oracle WebLogic Server. It creates a new web application based on the distributed ords.war but without the META-INF content. That content includes a signature digest of the web.xml which will be invalid when the new deployment descriptor is written to the new WAR file.

This is what makes it possible to have multiple ORDS instances deployed to the same server all with different configuration directories.

Loosely typed interfaces – The Normalizer Pattern and Oracle SOA Suite

When getting two or more systems working together, the making a connection part is generally the easiest, identity propagation is a bit trickier, but many times, the syntax and semantics of one system is at odds with another one. Over the decades this has been manifest in many ways and thankfully there are tools and techniques to work through them. A collation of such techniques is Enterprise Integration Patterns. The book, along with the associated website, is worthy of a dedicated article or two, and is not the real subject of this article. One message transformation pattern the book describes is the Normalizer Pattern where different formats for essentially the same object are catered for.
An example where this form of message translation becomes necessary is when using a service with a loosely typed interface. This can often happen when an existing system or utility (such as a batch / command processor) gets exposed as a web service. The request / response payload is little more than a collection of key / value pairs. There are a couple of ways to cater for this using Oracle SOA Suite 11g which I will outline in this article. One has full tool support. The other, a solution using XSLT, is not fully supported, but has an advantage in that the XSLT can be used both with the BPEL and Mediator components.

Troublesome Payloads
The challenge is to get something that is strongly typed into something that is loosely typed

Strongly Typed Loosely Typed


Furniture
Pam Beech
50000
20000
47000


NAME
Furniture


MANAGER
Pam Beech


BUDGET
50000


SPENT
20000


COMMITTED
47000

Now this is quite a simple example and the real world has a lot more complicated cases out there. Ones that would involve number formatting, character encoding, attribute concatenation, and so on. For the purposes of this exercise however, it is ideal to illustrate the point. All the files in this example are free and available for you to use, modify or incorporate into your own solution as you see fit. The example was produced and tested using Oracle Fusion Middleware 11.1.1.2.0. That is JDeveloper Studio 11.1.1.2.0 and WebLogic Server 11gR1. To reduce the number of files and dependencies involved, the example is a simple service (BPELProcessExample.wsdl) that takes a strongly typed request payload and returns a loosely typed response payload. The SOA composite project contains two BPEL processes that provide slightly different implementations for this same WSDL.

BPEL assign with copy and insertAfter
You can cater for the key / value pair structure by repeatedly appending a new ‘property’ element and then, using an XPATH predicate to specify which ‘property’ element is the target, copying the desired values. In the BPEL process this can all be done in a single ‘assign’ command, using the insertAfter instruction from the Oracle BPEL extension library. The BPEL designer supports this approach, and it is used extensively in production systems around the globe. It can get difficult to maintain and hard to read if the payload is large though. If dealing with a large payload see if you can split the copy / insertAfter instructions into two or more ‘assign’ commands. Ideally, you would give these ‘assign’ commands logical names such as ‘assign_part_1_admin_details’ and ‘assign_part_2_finance_details’. What is a large payload in this case then? Well, I would say that if you have more than 10 key value pairs you should be seriously thinking about splitting them up and if you have more than 20, you should be definitely splitting them up. Remember, you might be familiar with the structure and understand how it is constructed, but what about the college graduate brought in by the consulting firm in a months time, or even you having to come back to this in 6 months time? Go on, make the maintenance a bit easier for everyone and break that assign behemoth into manageable chunks!

BPEL transform with XSLT
If experienced in dealing with XML documents then this approach will probably be very familiar to you. Extensible Stylesheet Language Transformations is used to convert XML data into some other format, which may also be XML data. In this case the stylesheet explicitly describes the target XML structure, making it somewhat easier to read than the BPEL assign approach described earlier. For example…



MANAGER






The ‘client’ is a namespace prefix for the schema and in this SOA composite example the request and response happen to be defined in the same schema. This is easier to read, even if one is not all that familiar with XSL. For large payloads it is not necessary to split up the transformation as one might consider for the BPEL assign, but it could be done. The single transformation file could have a whole set of templates. However, the XSL Mapper does not support this approach yet, so if using this approach you will have to work in the Source editor, not the Design mode. Since this is using XSLT, the same XSL file can be used by the Mediator too, so it is not only a BPEL solution.

Which one is right for me?
As one can see from the diagrams there is not much difference in the BPEL designer between the two examples and the decision on which technique to use would be based on factors which are different from company to company, but clearly use of the XSL mapper is an important factor.
The complete example application with SOA composite is available at http://sites.google.com/site/soastation/soastation_looselytyped_normalizer.zip

ModuleException http:101216 on WebLogic

A number of people have asked about the ‘ModuleException: [HTTP:101216]Servlet:’ error I came across as part of the multi-platform Dice Service example. The experiences are covered in three (first problem, second problem, solved) separate articles which I will collate and summerise here.

Use ant to build web app
Some JEE 5 containers allow you to define your annotated classes and then drop them in an ‘autodeploy’ folder. Not with WebLogic Server v10 though, an ant script is required to do some more work on the web application. Interestingly, the WLS documentation does not refer to autodeploy for web services, in fact 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.

Without the JwscTask, simply dropping a JAX-WS web app in the deplopyment folder will give you an deployment error like this:


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

Tell JwscTask the type
Not only is an ant script required to invoke weblogic.wsee.tools.anttasks.JwscTask but when using it with JAX-WS web services you must set the type attribute. The guidelines in the WLS documentation states that the ant tasks need to have a type=”JAXWS” attribute set. Without this, WLS will treat the web service as a JAX-RPC service.







Summary
To deploy JAX-WS web services on WebLogic Server v10 use JwscTask, with type=”JASWS”, in an ant script. Of course, if you are going to the effort of putting an ant script together to build the web application, it might as well have it deploy the web app too.

Dice service working on WLS

As mentioned in a previous post the Dice service, which is my JAX-WS example for a cross platform service implementation, was not working on BEA WebLogic Servier v10. It turns out I missed a key part of JAX-WS & WLS documentation when putting the build script together. The guidelines in the WLS documentation states that the ant tasks need to have a type=”JAXWS” attribute set. Without this, WLS was treating the web service as a JAX-RPC one and that was the cause of the strange WSDL and the runtime exception.

The build-service target now looks like this:







So the only change is setting the type attribute to JAXWS. The WSDL generated for this service is identical to the one generated on Glassfish.

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.