23 Creating and Using Custom XPath Functions

Oracle Service Bus provides an extensible framework for creating custom XPath functions you can use in the XQuery expression editors in the development or run-time tooling, such as in proxy service message flows, Split-Joins, and XQuery Mapper transformations.

This section describes how to create, register, and use custom XPath functions in XQuery expressions. The high-level process includes:

Note:

Oracle Service Bus does not support custom functions that have side effects; for example, updating a database table or participating in a global transaction. Create custom functions that contribute only to an XQuery result, and perform side-effect behavior with other features such as Java Callouts.

23.1 Registering Custom Functions with Oracle Service Bus

Custom functions are available to all Oracle Service Bus projects and services in an installation; they are not scoped to specific domains.

Registering a custom function involves creating an XML file with an optional properties file for localization. The built-in functions that Oracle Service Bus provides use this function framework, so you can use those existing registration resources for guidance. Those files are located at:

OSB_ORACLE_HOME/config/xpath-functions/

The Oracle Service Bus functions file is called osb-built-in.xml. In that file, keys wrapped in % symbols, such as %OSB_FUNCTIONS%, get their value from the corresponding .properties file.

Following is the basic structure of a custom function registration file, followed by descriptions of the elements.

category id
    group id
        function
            name
            comment
            namespaceURI
            className
            method
            isDeterministic

Elements have an xpf: prefix.

Custom Function Element Descriptions 

  • category id – The name of the group that physically categorizes your group of functions in the expression editors. For example, "Service Bus Functions." Use the id attribute to provide the name. If you are using a corresponding .properties file for localization, enter the key that contains the text value in the .properties file. For example, %MY_FUNCTIONS%. Category ids, which include the properties file key name and the actual name value, must be unique.

  • group id – Optional. The name of a subcategory for grouping functions in the user interface; for example, "General" or "Accessors." The naming guidelines for category id apply to group id.

  • name – Name of the function as it appears in XQuery expressions. Function names (composed of the namespaceURI and prefix as well) must be unique. Oracle Service Bus does not support function overloading with different method arguments. Identical function names that have different namespaces (hence different prefixes) are allowed.

  • comment - Function description. While the description does not appear in the Oracle Service Bus user interface, you should provide guidance that shows how to invoke the function with meaningful argument names.

  • namespaceURI – The namespace of the function. For example, the Oracle Service Bus functions namespace is http://www.bea.com/xquery/xquery-functions. Namespaces and namespace prefixes must be unique. Custom namespaces that you provide appear in the Oracle Service Bus default namespaces list in the XQuery editor.

  • className – The fully qualified custom Java class that implements the function.

  • method – The custom Java method that implements the function, preceded by the return type. For example: boolean isUserInGroup(java.lang.String, java.lang.String).

    If your method uses a single-dimensional array, see Section 23.2.1.1, "Using Single-Dimensional Arrays" for guidance in making the entry in the XML file.

  • isDeterministic – A value of true or false declaring whether or not the function is deterministic. Deterministic functions always provide the same results; for example, a function that concatenates Strings. Non-deterministic functions return unique results; for example, a function that returns the time of day. Though you can use non-deterministic functions, the XQuery standard recommends that functions be deterministic to ensure XQuery engine optimization.

You custom functions do not appear in the XQuery expression editor until Oracle Service Bus can find you custom class. The following section describes how to create your custom class and package it so that Oracle Service Bus can locate it.

23.2 Creating and Packaging the Custom Function Java Classes

Use the following guidelines to create and package the class for a custom XPath function.

23.2.1 Creating the Class and Method

Use the following guidelines for creating Java class and method for a custom function.

  • class – The class must be public.

  • method – The method must be public and static.

  • arguments and return values – Table 23-1 lists the supported types for method arguments and return values. If a type is not listed, it is not supported. Inner classes and multi-dimensional arrays are not supported.

    Table 23-1 Supported Java Method Types for Custom Functions

    Java Type XQuery Type XSLT Type

    java.lang.String

    xs:string

    string

    int, java.lang.Integer

    xs:int

    number

    boolean, java.lang.Boolean

    xs:boolean

    boolean

    long, java.lang.Long

    xs:long

    number

    short, java.lang.Short

    xs:short

    number

    byte, java.lang.Byte

    xs:byte

    number

    double, java.lang.Double

    xs:double

    number

    float, java.lang.Float

    xs:float

    number

    char, java.lang.Char

    xs:string

    object

    java.math.BigInteger

    xs:integer

    number

    java.math.BigDecimal

    xs:decimal

    number

    java.util.Date

    xs:datetime

    See footnoteFoot 1 

    java.sql.Date

    xs:date

    See footnote

    java.sql.Time

    xs:time

    See footnote

    javax.xml.namespace.QName

    xs:Qname

    See footnote

    org.apache.xmlbeans.XmlObject

    element()

    See footnote

    org.w3c.dom.Element

    element()

    The XSLT node-set type is not supported with custom XPath functions.


    Footnote 1 Converted to a string, then passed back as its original type.

23.2.1.1 Using Single-Dimensional Arrays

Single-dimension arrays (using supported Java types) are mapped to corresponding XQuery types with an asterisk *, which is a wild card to imply the multiple cardinality of the array. For example:

public static XmlObject[] getArrayOfXmlObjects(XmlObject[] a)

is mapped to

namespace:getArrayOfXmlObjects($arg1 as element()*) as element()*

In function signatures that have single-dimensional array input arguments or return values, you must use the type encoding described at http://java.sun.com/javase/6/docs/api/java/lang/Class.html#getName(). The following examples show how to specify single-dimensional array methods in your custom function XML file using the required array encoding:

Java Method Entry in Custom Function XML File
public static String[] myUppercaseStringArray(String[] arg) Ljava.lang.String; myUppercaseStringArray([Ljava.lang.String;)
public static int[] myAddInts(int[] arg) [I myAddInts([I)

23.2.2 Packaging the Custom Function Class

Oracle Service Bus must know about your custom function class in order to include your custom functions in the XQuery editors and let you use those functions.

Package your custom function class in a JAR file, then put the JAR in the OSB_ORACLE_HOME/config/xpath-functions/ directory. At IDE and server start-up, Oracle Service Bus looks for custom function classes in this directory. Be sure to correctly reference your custom class and method in the custom function XML file, described in Section 23.1, "Registering Custom Functions with Oracle Service Bus."

Note:

You can also provide run-time-only access to your custom function class by putting your custom JAR anywhere in the Oracle Fusion Middleware home and adding the JAR to the server classpath.

After you add new custom functions, you must restart the IDE and any servers that will use the new functions.

23.3 Using Custom Functions

This section describes how to use custom functions in Oracle Service Bus.

23.3.1 Using Custom Functions in Inline XQuery Expressions and XQuery Resources

You can include custom functions in both inline XQuery expressions and in XQuery resources just as you would use functions provided by Oracle Service Bus.

23.3.2 Using Custom Functions in XSLT Resources

The syntax for invoking a custom function from within an XSLT resource varies by the XSLT engine you use with Oracle Service Bus. Given the following custom function code, Example 23-1 shows the syntax for invoking a custom function using the Xalan XSLT engine (the default on Microsoft Windows with the Sun JDK).

package tests.pipeline;
public class CustomXQFunctions
{
    public static String myUppercaseString(String arg)
    {
       return arg.toUpperCase(); 
    }
}

Example 23-1 Syntax for Invoking a Custom Function with the Xalan Engine

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"   version="1.0">
  <xsl:param name="arg-string"/>
  <xsl:template name="myUppercaseString" 
              xmlns:ns0="xalan://tests.pipeline.CustomXQFunctions">
   <xsl:variable name="upcase" select="ns0:myUppercaseString($arg-string)" />
   <originalInput>
     <xsl:value-of  select="$arg-string" />
   </originalInput>
   <result>
     <xsl:value-of select="$upcase" />
   </result>
 </xsl:template>
  <xsl:template match="*">
    <xsl:copy>
        <xsl:call-template name="myUppercaseString"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

With an input document of <example /> and an input arg-string value of hello, the transformation becomes:

<example>
   <originalInput>hello</originalInput>
   <result>HELLO</result>
</example>

23.4 Testing Custom XPath Functions in Eclipse

In Eclipse, when testing XQuery resources that contain custom XPath functions, the best practice is to run the XQuery resources on a connected server using the Run > Run As > Run on Server command, which runs the resource in the Test Console.

23.5 Deploying Custom Functions in a Cluster

In a multiple-server environment with multiple Oracle Fusion Middleware product homes, you must manually add all custom function resources to any of those environments where the custom functions will be used. Clustering does not automatically distribute custom function resources across managed servers.