Read XML Resource in Oracle Service Bus 11g

Some time ago I was thinking in how to read XML Resources available in OSB projects at runtime. It would be very useful to hold some configuration data to be read by the proxy services through XPath or Java Call. After many searches in Google, I did not find any documentation or example in how to read OSB resources content programmatically at runtime. The popular OSB APIs and MBeans do not provide any method to get the resources content, but only their references. The question was how to get the resources content through their references.

With the help of JShrink I spent some time decompiling the OSB native jar functions and making a reverse engineering to discover how to do this. Fortunately, after some good tries I found what I was looking for. Using some internal OSB built-in libraries we can access any project resource at runtime.

In this article I will show how to read a sample XML Resource programmatically at runtime. In this sample I will use a Custom XPath to read a XML resource that holds application configuration parameters. Obs.: the same API shown here can also be used into a Java Call.

The sample project structure will look like this:

File “xsd/Parameters.xsd”: a simple schema that we’ll use in this scenario to describe the XML structure that holds the parameters:

<xsd:complexType name="Parameters">
	<xsd:sequence>
		<xsd:element name="ParameterList" type="tns:ParameterList"/>
	</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ParameterList">
	<xsd:sequence>
		<xsd:element name="Parameter" type="tns:Parameter" minOccurs="0" maxOccurs="unbounded"/>
	</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Parameter">
	<xsd:sequence>
		<xsd:element name="Key" type="xsd:string"/>
		<xsd:element name="Value" type="xsd:string"/>
	</xsd:sequence>
</xsd:complexType>

File “xml/Parameters.xml”: the sample XML that will be read by our XPath function at runtime:

<ns0:Parameters xmlns:ns0="http://gibaholms.wordpress.com/samples/xsd/2012/02/parameters">
	<ns0:ParameterList>
		<ns0:Parameter>
			<ns0:Key>Color</ns0:Key>
			<ns0:Value>Blue</ns0:Value>
		</ns0:Parameter>
		<ns0:Parameter>
			<ns0:Key>Size</ns0:Key>
			<ns0:Value>500</ns0:Value>
		</ns0:Parameter>
	</ns0:ParameterList>
</ns0:Parameters>

File “xq/ReadXmlParameters.xq”: a sample test XQuery that calls our XPath function passing as argument the full reference path to the XML parameters file:

xquery version "1.0" encoding "Cp1252";
(:: pragma bea:schema-type-return type="ns0:Parameters" location="../xsd/Parameters.xsd" ::)

declare namespace xf = "http://tempuri.org/ReadXmlResource/xq/ReadXmlParameters/";
declare namespace ns0 = "http://gibaholms.wordpress.com/samples/xsd/2012/02/parameters";
declare namespace param = "http://gibaholms.wordpress.com/xpath/ReadXmlResource";

declare function xf:ReadXmlParameters() as element() {
    param:readXml("ReadXmlResource/xml/Parameters")
};

xf:ReadXmlParameters()

Now, let’s create the custom XPath that does the magic. Create a simple Java project and add the following compile dependencies:

  • <MIDDLEWARE_HOME>\Oracle_OSB1\modules\com.bea.common.configfwk_1.5.0.0.jar
  • <MIDDLEWARE_HOME>\Oracle_OSB1\modules\com.bea.core.xml.xmlbeans_2.1.0.0_2-5-1.jar
  • <MIDDLEWARE_HOME>\Oracle_OSB1\lib\modules\com.bea.alsb.resources.core.jar
  • <MIDDLEWARE_HOME>\Oracle_OSB1\lib\modules\com.bea.alsb.resources.xml.jar

The XPath project structure is shown below:

In the file “osb-readxmlresourcefunction.xml” we describe the XPath functions contract. This file is a requirement of OSB and must be copied to the functions directory with the generated jar file:

<xpf:xpathFunctions xmlns:xpf="http://www.bea.com/wli/sb/xpath/config">
	<xpf:category id="Custom Functions">
		<xpf:function>
			<xpf:name>readXml</xpf:name>
			<xpf:comment>This function reads a XML Resource file from OSB</xpf:comment>
			<xpf:namespaceURI>http://gibaholms.wordpress.com/xpath/ReadXmlResource</xpf:namespaceURI>
			<xpf:className>com.wordpress.gibaholms.xpath.ReadXmlResource</xpf:className>
			<xpf:method>org.apache.xmlbeans.XmlObject readXml(java.lang.String)</xpf:method>
			<xpf:isDeterministic>true</xpf:isDeterministic>
			<xpf:scope>Pipeline</xpf:scope>
			<xpf:scope>SplitJoin</xpf:scope>
		</xpf:function>
	</xpf:category>
</xpf:xpathFunctions>

The secret to access OSB resources at runtime is the various “*Repository” classes. The code of our “readXml” XPath function is shown below:

package com.wordpress.gibaholms.xpath;

import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;

import com.bea.wli.config.Ref;
import com.bea.wli.config.component.NotFoundException;
import com.bea.wli.sb.resources.config.XmlEntryDocument;
import com.bea.wli.sb.resources.xml.XmlRepository;

public class ReadXmlResource {

	public static XmlObject readXml(String xmlRefPath) {
		Ref ref = new com.bea.wli.config.Ref("XML", Ref.getNames(xmlRefPath));
		XmlObject xmlObject = null;
		try {
			XmlEntryDocument xmlEntryDocument = XmlRepository.get().getEntry(ref);
			String xmlContent = xmlEntryDocument.getXmlEntry().getXmlContent();
			xmlObject = XmlObject.Factory.parse(xmlContent);
		} catch (NotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException("XML Resource not found.");
		} catch (XmlException e) {
			e.printStackTrace();
			throw new RuntimeException("Error parsing XML content.", e);
		}
		return xmlObject;
	}
	
}

As we can see in the code, the class “com.bea.wli.sb.resources.xml.XmlRepository” does the magic of retrieve the XML resource content through it “com.bea.wli.config.Ref” reference. Following the same principle, we can use the other various “*Repository” classes to access other types of resources in projects at runtime, like Schemas, XSLTs, WSDLs and so on.

To test the function, just run the XQuery “xq/ReadXmlParameters.xq” in the sbconsole:

The test XQuery has no parameters, so just execute it:

Then you must see the parameters XML loaded at runtime, like shown below:

I’m glad to share this discovery with other ALSB / OSB developers and I hope help you to do more useful things with this knowledge.

If someone already has another solution to read OSB project resources at runtime or already use this API for some other purpose, please share the experience with us through comments. Thanks.

Attachments

Source Code:
https://github.com/gibaholms/articles/tree/master/Read_XML_Resource_in_OSB

About these ads

Tags: , , , , , , , , , , , ,

17 Responses to “Read XML Resource in Oracle Service Bus 11g”

  1. Edwin Biemond Says:

    Really nice,

    Great we can then have a central MDS project which contains all the xml entries.

    maybe you can also make a MDS implementation, where you have your osb partition in MDS or re-use the soa one for the xml ( the soa already has the required upload and delete scripts )

    for the OSB book ,Eric Elzinga make a recipe where he used a file adapter to do the same.

    thanks for sharing.

    • gibaholms Says:

      Thanks for the feedback Biemond.

      Im planning to use this technique to make something about integrating JUnit to create automated testing support to XQuery and XSLT transformations, and even to automate Proxy Services message flow unit testing.

      What do you think about it ?

  2. Edwin Biemond Says:

    Hi,

    I know somebody already tried to do this for Xquery , I know the jdev xquery jars are different then that of OSB.

    but it would be really cool.

    good luck

  3. Rafael Icibaci Says:

    Great Post!

  4. Alessandro Ilardo Says:

    why not simply rename the extension from xml to xq?

    • gibaholms Says:

      Hi Alessandro,
      Thanks for the reply!
      For the case of data parametrization your suggestion is valid, I already did this xq approach in many clients. The only cons I’ve come across was the need to use a assign task to get all the parameters every time and the time spent to explain the sysadmin what is a xq and no support for caching the parameters.
      But the data parametrization is only a practical sample to show the possibilities, much more things can be done using this approach. The main purpose was to show the possibility to get programmatically at run-time not only xml, but any resource from OSB, like cannonical models, xqueries, xslts, do unit testing of transformations with JUnit, etc.

  5. dhiego Says:

    “This file is a requirement of OSB and must be copied to the functions directory with the generated jar file”. Where is this function directory?

    • gibaholms Says:

      Hi Dhiego,
      To install a custom xpath function in OSB 11g, you must copy the jar file and the xml descriptor to the folder “\Oracle_OSB1\config\xpath-functions”, then you must restart the server.

  6. dhiego Says:

    Thank you very much. I’ll try it!

  7. ross Says:

    excellent post. in my case I have some parameters which changes from environment to environment . I wanted to add to customization xml file and have proxy read it from it. couldn’t find a way to add/read custom variable to customization file. Any ideas?

    • gibaholms Says:

      Hi Ross,

      With customization files you will be able to do search and replace in your xml parameters or xquery, but i never tried it With a pattern, maybe you must replace the exact value. Letme know if worked. Regards.

  8. Viv Says:

    Nice post.

    I followed this article to access an osb resource (xsd) within a jar called from a proxy service via java callout. But I am getting an error – java.lang.RuntimeException: XML Resource not found at line

    Ref ref = new com.bea.wli.config.Ref(“XML”, Ref.getNames(schemaRefPath));

    I verified the path of the resource and everything is ok. Could you please help.

    • gibaholms Says:

      Hi Viv,

      If your resource is a xsd, you must try:
      Ref ref = new com.bea.wli.config.Ref(“XSD”, Ref.getNames(schemaRefPath));

      Each type of resource have its own “type name” (XML, XSD, WSDL, etc…)

      Regards,
      Gilberto

  9. Viv Says:

    Hi Gib,

    Changes it to XSD leads to this error -

    java.lang.IllegalArgumentException: Expected a query of type XML but got XSD

    at this line of code -

    XmlEntryDocument xmlEntryDocument = XmlRepository.get().getEntry(ref);

    • gibaholms Says:

      Hi Viv,

      The BEA naming conventions are pretty consistent, the classes XmlEntryDocument and XmlRepository works only for “XML” resources…
      For “XMLSchema” resources, you must replace it to “SchemaEntryDocument” and “SchemaRepository”, from the jar file “com.bea.alsb.resources.schema.jar”.

      Another thing, in the previous post I said “XSD”, but I guess the correct String is “XMLSchema”. Try with both please and then let me know which worked.

  10. Viv Says:

    Appreciate your help Gib. It worked with following line of codes -

    Ref ref = new com.bea.wli.config.Ref(“XMLSchema”, Ref.getNames(schemaRefPath));
    try {

    SchemaEntryDocument schemaEntryDocument = SchemaRepository.get().getEntry(ref);

    String xsdContent = schemaEntryDocument.getSchemaEntry().getSchema();

    Another thing to note that the schema name should NOT suffix “.xsd”.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: