Oracle Service Bus 11g, Using Custom Xpath functions

In the new Oracle Service Bus 11g, Oracle gives us new functionality for the use of custom xpath functions.
These functions we eventually can re-use in for example the xslt or xquery transformations.

For this we need :

  1. 1. XML Configuration file (osb-custom.xml)
  2. 2. Property file (optional, osb-custom.properties)
  3. 3. Custom Function Class (jar package)

All these files need to be stored at the next location

<OSB_HOME>/config/xpath-functions

1. XML Configuration file

Create a new XML configuration file. I made a copy of the default file, osb-built-in.xml, edit that one, and change the settings.

<?xml version="1.0" encoding="UTF-8"?>
<xpf:xpathFunctions xmlns:xpf="http://www.bea.com/wli/sb/xpath/config">
    <xpf:category id="%OSB_FUNCTIONS%">
        <xpf:function>
            <xpf:name>customConcat</xpf:name>
            <xpf:comment>%FUNC_CUSTOM_CONCAT_COMMENT%</xpf:comment>
            <xpf:namespaceURI>http://nl.iteye/osb/custom/functions/OsbUtils</xpf:namespaceURI>
            <xpf:className>nl.iteye.osb.custom.functions.OsbUtils</xpf:className>
            <xpf:method>java.lang.String customConcat(java.lang.String, java.lang.String)</xpf:method>
            <xpf:isDeterministic>false</xpf:isDeterministic>
            <xpf:scope>Pipeline</xpf:scope>
            <xpf:scope>SplitJoin</xpf:scope>
        </xpf:function>
    </xpf:category>
</xpf:xpathFunctions>

A few notes on this file.

  • category, the name of the category how it will appear in the IDE or Console
  • function:name,comments, the description of the function how it will appear in the IDE or Console
  • namespaceURI, the namespace which will be imported in for example the xquery to identify the custom function
  • className, the java implementation of our custom xpath function
  • method, the name of the method which we will be using for the implentation of the function
  • isDeterministic, A value of true or false declaring whether or not the function is deterministic, the XQuery standard recommends the function to be deterministic (see documentation for further information)
  • scope, i assume the scope of the OSB flow in which the function can be used

2. Property file

%OSB_FUNCTIONS%=Service Bus Functions
%FUNC_CUSTOM_CONCAT_COMMENT%=Returns the concat of the first and the second parameter

Not much in here,just a few placeholders for the descriptions

3. Custom Function Class

Create a new Java project in your favorite IDE. Create a new package and java class. For this demo i created a custom concat function which will concat parameter1 and parameter2 and return the result.

package nl.iteye.osb.custom.functions;       

public class OsbUtils {
    public OsbUtils() {
    }
    
    public static String customConcat(String firstParam, String secondParam) {
        return firstParam + " " + secondParam;
     }
}

The method needs to be defined as static.
Compile the code and create a jar archive and store this at the location mentioned in the top of the article.
After this we should have 3 extra files in this directory :

  • osb-custom.xml
  • osb-custom.properties
  • osb-custom.jar

Restart the server, so the Oracle Service Bus will load the custom classes we just created. Check the output of the console to see if don’t see any errors come by. Wrong configuration (wrong methodname,package, etc) will end up with a little stacktrace in here.

Testing

To test the custom xpath function, create a new Oracle Service Bus project in Eclipse.

Add new XML Schema

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/NewXMLSchema" xmlns:tns="http://www.example.org/NewXMLSchema" elementFormDefault="qualified">
    <element name="Input" type="tns:InputType"></element>
    <element name="Output" type="string"></element>

    <complexType name="InputType">
    	<sequence>
    		<element name="Name1" type="string"></element>
    		<element name="Name2" type="string"></element>
    	</sequence>
    </complexType>
</schema>

Add new XQuery Transformation
In the list of expression functions we will see our custom function (customConcat)

(:: pragma bea:global-element-parameter parameter="$input1" element="ns0:Input" location="NewXMLSchema.xsd" ::)
(:: pragma bea:global-element-return element="ns0:Output" location="NewXMLSchema.xsd" ::)

declare namespace ns0 = "http://www.example.org/NewXMLSchema";
declare namespace xf = "http://tempuri.org/OSB%20Project%201/InputToOutput/";

declare function xf:InputToOutput($input1 as element(ns0:Input))
    as element(ns0:Output) {
        <ns0:Output>{ osbK3:customConcat($input1/ns0:Name1,$input1/ns0:Name2) }</ns0:Output>
};

declare variable $input1 as element(ns0:Input) external;

xf:InputToOutput($input1)

In the transformation i will map both the Name1 and Name2 to the input of the custom function, which will return the concat of both in output.

The easiest way to test the result is by running the XQuery on a connected server. Right mouseclick on the .xq file > Run As > Run on Server
The Oracle Service Bus Test Console will pop up.
Fill in the input data and execute.

And the result

About these ads

About Eric Elzinga
Eric Elzinga I'm an integration consultant located in The Netherlands. Mainly doing projects based on Oracle integration stacks (Oracle SOA Suite/Oracle Service Bus (OSB)), Java development, and opensource integration products.

22 Responses to Oracle Service Bus 11g, Using Custom Xpath functions

  1. Sergi says:

    Fantastic article.

    One question, why prefix is osbk3? Is possible to change this?

    Thanks!

  2. Eric Elzinga says:

    You could add your own prefix

    declare namespace test1 = “http://nl.iteye/osb/custom/functions/OsbUtils”;

    and then use : test1:customConcat()

  3. Eric Elzinga says:

    Did it work for you ?

  4. Sergi says:

    Yes, it works.

    But i need to declare namespace in all XQuery Transformations. It’s possible declare global namespace? For example, fn-bea prefix it’s general for all XQuerys….

    Thanks!

  5. konrad says:

    I have a similar problem. I can not set the custom prefix. Did you found a solution?

  6. Alessandro Ilardo says:

    Does it work for 10.3 as well?

  7. hisaak says:

    Eric, thank you for great article!

    To everybody struggling to set custom default prefix: Boys, this is Oracle! Its software usually covers 99% of your needs, but you just can’t implement that missing percent no matter effort you dedicate. ;-)

  8. Nupur says:

    Yes it did. I’m too happy

  9. foofighter says:

    Is it possible to hold these xqueries in Eclipse project?

    Description Resource Path Location Type
    line 4, column 5: {err}XQ0017: “{http://nl.iteye/osb/custom/functions/OsbUtils}customConcat”: unknown function (or number of arguments (2) is wrong) test_custom_xpath.xq line 4 ALSB Conflict

  10. Martin Vergara B. says:

    Hi Eric,

    If i want to create a customized data type in java.
    for example, you created a class called OsbUtils that includes a method “String customConcat”
    I would like to know if i can return an Employee class for instance. Is possible doing that in osb ?
    I tried to do it but in osb console raise an error.

    Thank & regards,
    Martín

  11. Mani says:

    Hi Eric,
    Thanks for nice post,It is very helpful.I have a query regarding the prefix,If I add name space in Xq I am able to get custom prefix,but In my message flow there is no need of using XQ,just in assisgn activity I am using custom functions,in that case I am getting default prefix,how to set custom default prefix?Actually I tried in osb-custom.xml file we have the ” http://www.bea.com/xquery/xquery-functions” if we use this uri we getting fn:bea prefix other than this like in ur
    sample http://nl.iteye/osb/custom/functions/OsbUtils prefix is came like osbk3 that is first 3 characters of class name two other characters.Is it possible to set custom prefix?

    Thanks
    Mani

  12. Mike says:

    This feature is a real piece of crap. Unless you use it inside of a transformation or a stage where you can define your own prefix, forget about it. Not only that you cannot define the prefix like the other posters already mentioned but also the prefix is randomly generated and it will change from one environment to another.

    So you do your development in one place, all the testing works fine and when you deploy the code on the real production environment you realize that all the objects in your project are invalid because Oracle just changed the prefix and all your custom functions cannot be found anymore.

  13. pankaj says:

    Hi Eric,
    Is there any function in XQuery which will covert any incoming date format to MM/DD/YYYY. I have tried fn:matches and fn:pattern but still not working. Is there any way to convert any input date format lets say YYYY-MM-DD or YYYY/MM/DD or MM-DD-YYYY or DD-MM-YYYY to MM/DD/YYYY. Currently date format is fix and I am using substring and it is working fine but as per the requirement date format may get change.
    Thanks in advance.

    Best Regards,
    Pankaj

    • Eric Elzinga says:

      Hi Pankaj,

      I don’t think there is any function which accepts any input date format and just formats it. Shouldn’t your backend system or the invoker of your service just supply the date field in the format you agreed on ?

  14. Parthiban says:

    hi,

    I am getting the below error while creating the xquery

    An error occurred creating the resource:
    line 9, column 23: {err}FONS0003: “osbK3″: prefix not defined in static context

    • Eric Elzinga says:

      have you tried adding something like this : declare namespace test1 = “http://nl.iteye/osb/custom/functions/OsbUtils”;

      and use test1 for the prefix?

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

Follow

Get every new post delivered to your Inbox.

Join 37 other followers

%d bloggers like this: