A little know feature of the WebLogic Server implementation is something called the XML Registry. In many applications it is still common to receive an XML document as a post to a servlet and then parse that document and translate the contents into calls to various local services. This approach was a common early step in the movement towards web services and there are are still plenty of applications out there with similar logic.
In the WebLogic Server the XMLRegistry interposes a server specific implementation of the various SAX and DOM parsers and the services used to resolve the entities that are encountered during parsing. As part of optimizing the server for optimal benchmark performance we spent a bunch of cycles during the 10.3 release to improve the efficiency of this code and to eliminate a number of areas of contention. We also noticed that the default parsers were repeatedly downloading the dtd for the documents that were being parsed. By configuring the XML registry we were able to dramatically reduce the number of outbound requests to download the dtds during our testing.
To see what is going on lets look at a diagram of a somewhat typical application. In this case we have two applications which are exchanging order and delivery documents each of which is validated with a DTD. It can be seen that the way the application was written each request is parsed in the servlet. While it is parsed the underlying XML parser retrieves the DTD that is needed to validate it and thus blocked. This ties up a thread on both the sending and receiving application servers.
By enabling the XMLRegistry the request to retrieve the required entity is trapped in the XML Registry and resolved against a local cache. This avoids repeated calls between servers and eliminates the latency in the initial processing and also in the session that is making the initial post. This reduces the number of active threads on both servers that are involved in the processing.
This works because it in most cases the contents of the DTD are very, very unlikely to change. Any change would be well coordinated between the communicating parties. The downside to such an approach is that if the DTD or XSD were to change there could be any number of failed requests. Handling that would require special coding in the applications In the 10.3 release additional functionality was added to address even this unlikely occurrence (http://e-docs.bea.com/wls/docs103/issues/known_resolved.html).
The “handle-entity-invalidation” feature that was added to the XML Registry tells the interposed parser handler to trap any parsing failures and first verify if they are the result of changes to the XML entity that is being used to validate the document. When it encounters these errors it will download a fresh copy of the entity and compare it to the entity in the cache. If it is changed it will reinitiate the parse. If that parse is successful the application will continue on as if nothing happened and be none the wiser. Subsequent failure are reported in the standard way.
Enabling this set of features is a great way to get better performance out of existing applications without having to do any code rework. The example code below shows how to configure this capability in the WLS config.xml It can also be configured through WLST scripting. The only trick is to make sure that the system-id and public-id match the values that are in the documents that you are receiving from the counterparty.
Another little tweak that might help performance some even if you don’t enable entity caching, is replacing the default document builder factory. We found that the implementation below was working better than the default implementation of “weblogic.apache.xerces.jaxp.DocumentBuilderFactoryImpl” specified in releases prior to 10.1. In 10.3 this was updated and so you won’t need to make this change to get the performance benefit.
<xml-registry>
<name>dtdCache</name>
<document-builder-factory>
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
</document-builder-factory>
<xml-entity-spec-registry-entry>
<name>deliveryResponse</name>
<public-id>DELIVERY</public-id>
<system-id>
http://acme:7011/Emulator/dtd/delivery.dtd
</system-id>
<entity-uri>
http://acme:7011/Emulator/dtd/delivery.dtd
</entity-uri>
<when-to-cache>cache-on-reference</when-to-cache>
<cache-timeout-interval>60000</cache-timeout-interval>
<handle-entity-invalidation>true</handle-entity-invalidation>
</xml-entity-spec-registry-entry>
</xml-registry>