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="https://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 = "https://gibaholms.wordpress.com/samples/xsd/2012/02/parameters";
declare namespace param = "https://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>https://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

Advertisements

30 thoughts on “Read XML Resource in Oracle Service Bus 11g

  1. Edwin Biemond 02/28/2012 / 9:37 AM

    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.

  2. Edwin Biemond 02/29/2012 / 5:46 PM

    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 03/01/2012 / 10:51 PM

    Great Post!

  4. Alessandro Ilardo 07/03/2012 / 9:12 AM

    why not simply rename the extension from xml to xq?

    • gibaholms 07/03/2012 / 11:09 AM

      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 08/02/2012 / 5:04 PM

    “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 08/03/2012 / 7:30 AM

      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 08/03/2012 / 9:50 AM

    Thank you very much. I’ll try it!

  7. ross 11/09/2012 / 12:38 PM

    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 11/12/2012 / 2:49 AM

      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 02/07/2013 / 12:30 PM

    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 02/07/2013 / 2:31 PM

      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 02/21/2013 / 3:19 AM

    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 02/21/2013 / 9:45 AM

      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 02/21/2013 / 1:24 PM

    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”.

    • gibaholms 02/21/2013 / 2:30 PM

      Great news Viv !! Thanks for your feedback. Regards !

  11. CV 10/24/2013 / 7:16 AM

    Hi…

    Can u give an example of a xmlRefPath ?

    Regards,
    CV

    • gibaholms 11/11/2013 / 7:56 AM

      Hi,

      The xmlRefPath is the xml file path in OSB, removing the (.xml) extension: “ReadXmlResource/xml/Parameters” .

  12. Carlos Herrera 10/31/2013 / 2:04 AM

    Good night, Gilberto, I wanted to see if you can do this in OSB 10gR3, or what would be the code of equivalence, since I need to read some XML’s in a dynamic but can not find the way eh tested with XQuery but the function fn: doc () not working.

    Regards,
    Carlos

    • gibaholms 11/11/2013 / 8:01 AM

      I think that fn:doc() will not work, because OSB works with references, not files. Did you tried the posted code to retrieve the XML contents ? The OSB 10gR3 and 11g have the same core.

  13. Hello Shree 05/06/2015 / 4:19 PM

    Hi Very nice article, i am having requirement to read wsdl document from other projects resources folder. but I am unable to get it i get following error

    WsdlEntryDocument wsdldoc = WsdlRepository.get().getEntry(ref);
    String wsdlcontent = wsdldoc.getWsdlEntry().getWsdl();

    can you help me please

  14. Hello Shree 05/06/2015 / 4:33 PM

    also to note additionally i am passing wsdl location as a string to xmlRefPath and refType as “WSDL”

    public static XmlObject readXml(String xmlRefPath, String refType) {
    Ref ref = new com.bea.wli.config.Ref(refType, Ref.getNames(xmlRefPath));
    XmlObject xmlObject = null;
    try {
    WsdlEntryDocument wsdldoc = WsdlRepository.get().getEntry(ref);
    //wsdldoc.getWsdlEntry().getWsdl();
    System.out.println(“wsdl read>>>> ” + wsdldoc.getWsdlEntry().getWsdl());

  15. Jason Pyeron 06/02/2015 / 1:49 PM

    Looking to fork and polish this up a bit, could you provide a license or state it is in the public domain? See commit comment on github, thanks.

    • gibaholms 06/02/2015 / 2:06 PM

      Hi Jason,

      MIT license created and commited in the root project level.

      Thanks,
      Gilberto.

      • Jason Pyeron 06/02/2015 / 4:53 PM

        Thanks! Starting coding now…

  16. shuttle 09/27/2016 / 5:25 AM

    It doesn’t work in oracle service bus 12c

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 )

Google+ photo

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

Connecting to %s