com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

Script Mediator with Nashorn Support

From WSO2 EI 6.2.0 onwards, the Script Mediator of the ESB profile uses Nashorn to execute JavaScripts in addition to its default Rhino engine. You can perform all Script Mediator functionalities that the Rhino engine provides, with the Nashorn engine as well.

You need to install JDK 8 version update 112 or later to use Nashorn support, If not, you get the following exception when you call the setPayloadJSON() method: java.lang.ClassCastException: jdk.nashorn.internal.runtime.Undefined cannot be cast to java.lang.String

For more information, see the bug that causes this, which is fixed in JDK 8 version update 112 or later.

The Rhino engine uses E4X XML objects to handle XML payloads. However, E4X is deprecated in the Nashorn engine. Instead, Nashorn supports the AXIOM XML parser to parse XML streams. You can use the getParsedOMElement(InputStream stream) method to parse an XML stream into an OMElement, and the getXpathResult(String expression) method to retrieve the AXIOMXPath using an Xpath query expression to access and modify it.

The XPath equivalents for a few common XML navigation operations are as follows.

OperationXPath expressionE4X equivalent
Select all the children of an elementelement/*element.*
Select all the attributes of elementelement/@*element.@*
Select all the descendants (children, grandchildren, etc.) of an elementelement//descendentelement..descendent
Select the parent of an element.. or parent::elementelement.parent()
Select a specific child (e.g. foo:bar ) of an element, where 'foo' is the prefix of a declared namespace

xmlns:foo="..." element/foo:bar


var foo = new Namespace(...);

element.foo::bar


Return the full name (including prefixes if available) of an elementname(element)element.name()
Return the local name of an elementlocal-name(element)element.localName()
Return the namespace URI of an element (if available) namespace-uri(element)element.namespace()

Return the collection of namespaces.

  • For E4X: returns as an Array of Namespace objects
  • For XPath: returns as a set of Namespaces nodes
element/namespace::*element.inScopeNamespaces()
Return the processing instructions of the specified children of an element (returns all if omitted)element/processing-instructions(name)element.processingInstructions(name)
Return the concatenated text nodes and descendants of an element string(element)stringValue(element);

You can create a Script mediator with Nashorn support using one of the following methods.

  • Store the JavaScript program statements in a separate file, and refer it via a Local or Remote Registry entry.

  • Embed the JavaScript program statements inline within the Synapse configuration.

You can invoke a function within the corresponding script using the Script Mediator. Hence, you can predefine the Synapse configuration in a script variable named mc, and access it via these functions. The mc variable represents an implementation of the NashornScriptMessageContext.java MessageContext. It is an implementation of the ScriptMessageContext interface, which contains the following methods. You can access these methods within the script (e.g., mc.methodName).

Method nameDescriptionIf a value is returned or not
getParsedOMElement(stream)Converts the input stream of an XML String or document into an OMElement. This is useful to traverse the XML document.Yes
getXpathResult(expression)Converts a String, which represents an Xpath expression into an AXIOM Xpath. This is useful to traverse the XML document.Yes
addHeader(mustUnderstand, content)Adds a new SOAP header to the message. Content can be XML, String, parsed w3c.dom.Document, or an OMElement returned by the getParsedOMElement(stream) method.No
getEnvelopeXML()Retrieves the XML representation of the complete SOAP envelope.Yes
getPayloadJSON()Retrieves the JSON representation of a SOAP Body payload.Yes
getPayloadXML()Retrieves the XML representation of a SOAP Body payload. This method Returns a OMElement so the user can directly access elements using Xpath.Yes
getProperty(name)Retrieves a specified property from the current message context.Yes
setPayloadJSON(payload)Sets the JSON representation of a payload obtained via the getPayloadJSON() method in the current message context.No
setPayloadXML(payload)Sets the SOAP body payload from the XML.  Payload can be XML, String, parsed w3c.dom.Document or an OMElement returned by the getParsedOMElement(stream) method.  No
setProperty(key, value)Replaces the existing property values a property in the current message context. No

The Script Mediator has the flexibility of a class Mediator, with access to the Synapse Message Context and Synapse Environment APIs. For both types of script mediator definitions, the Message Context passed into the script has additional methods over the standard Synapse Message Context, to enable working with natural XML to JavaScript.

The Script mediator is a content aware mediator.



Syntax

Click on the relevant tab to view the syntax for a script mediator using an Inline script, or a script mediator using a script of the Registry.

Configuration

Click on the relevant tab to view the required UI configuration depending on the script type you have selected. The available script types are as follows:

  • Inline: If this script type is selected, the script is specified inline.
  • Registry Key: If this script type is selected, a script which is already saved in the registry will be referred using a key.

Examples

Assume the below SOAP envelope for the following examples:

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<AuthenticationInfo xmlns="http://www.x" soapenv:mustUnderstand="0">
<userName>”wso2”</userName>
<password>”wso2”</password>
</AuthenticationInfo>
</soapenv:Header>
<soapenv:Body>
<company>
	<staff id="1001">
		<firstname>”yong”</firstname>
		<lastname>”mook kim”</lastname>
		<nickname>”mkyong”</nickname>
		<salary>100000</salary>
	</staff>
	<staff id="2001">
		<firstname> “low”</firstname>
		<lastname>”yin fong”</lastname>
		<nickname>”fong fong”</nickname>
		<salary>200000</salary>
	</staff>
</company>
</soapenv:Body>
</soapenv:Envelope>

 Example 1 - Using an inline script

The following configuration is an example of using a Nashorn JavaScript script inline in the Script Mediator. In this script, you get the message payload in XML and you use an Xpath query to access the elements of it.

<script language="nashornJs"><![CDATA[var symbol = mc.getPayloadXML();
var expression = "//firstname";
var xpath = mc.getXpathResult(expression);
var c1l = xpath.selectNodes(symbol);
var first_name = c1l.get(0).getText();
]]></script>

Example 2 - Using a script saved in the registry

In the following example, the script is loaded from the Registry using the key repository/conf/sample/resources/script/test.js.

<script language="nashornJs"
    key="repository/conf/sample/resources/script/test.js"
    function="testFunction"/>

The script language="nashornJs" property indicates that the invoked function should be in the Nashorn JavaScript language. You need to save the function named testFunction, which is invoked in the above example as a resource in the Registry. Following is an example for the script of the function.

function testFunction(mc) {
var symbol = mc.getPayloadXML();
var expression = "//firstname";
var xpath = mc.getXpathResult(expression);
var c1l = xpath.selectNodes(symbol);
var first_name = c1l.get(0).getText();
}

Examples for methods

The following Script Mediator configuration examples show how you can include some of the commonly used methods in the invoked script.

MethodsSOAP envelopeSample Script Mediator configuration
  • setPayloadXML(payload)

  • getPayloadXML(mustUnderstand,content)

  • addHeader()

  • getEnvelopeXML()

  • getXpathResult(expression)

  • getParsedOMElement(stream)

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<AuthenticationInfo xmlns="http://www.x" soapenv:mustUnderstand="0">
<userName>”wso2”</userName>
<password>”wso2”</password>
</AuthenticationInfo>
</soapenv:Header>
<soapenv:Body>
<company>
	<staff id="1001">
		<firstname>”yong”</firstname>
		<lastname>”mook kim”</lastname>
		<nickname>”mkyong”</nickname>
		<salary>100000</salary>
	</staff>
	<staff id="2001">
		<firstname> “low”</firstname>
		<lastname>”yin fong”</lastname>
		<nickname>”fong fong”</nickname>
		<salary>200000</salary>
	</staff>
</company>
</soapenv:Body>
</soapenv:Envelope>
<script language="nashornJs"><![CDATA[
var symbol = mc.getPayloadXML();
 
var expression = "//firstname";
var xpath = mc.getXpathResult(expression);
var nameList = xpath.selectNodes(symbol);
var name = nameList.get(0).getText();
mc.setPayloadXML(symbol); //here we are setting payload by a parsed xml document or this coud be done                      by passing xml string as well
var password = "wso2";
var username = "wso2";
var headerXml =
 "<AuthenticationInfo xmlns=\"http://www"
                    + ".w3.org/1999/xhtml\"><userName>" + username + "</userName><password>"+     password + "</password"
                    + "></AuthenticationInfo>";
mc.addHeader(false, headerXml ); 
var envelope = mc.getEnvelopeXML();
 
expression = "//nickname";
stream = new byteArrayStream(envelope.getBytes());
var docEnvelope = mc.getParsedOMElement(stream);
xpath = mc.getXpathResult(expression);
var nickNameList = xpath.selectNodes(docEnvelope);
var nickname = nickNameList.get(0).getText();
]]></script>
  • setProperty("key", value);

  • getPayloadJSON()

  • setPayloadJSON(payload)

<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<jsonObject>
<appointmentNo>55</appointmentNo>
<doctorName>thomascollins</doctorName>
<patient>JohnDoe</patient>
<actualFee>7000.0</actualFee>
<discount>0</discount>
<discounted>7000.0</discounted>
<paymentID>c3b7cab3-8e22-4319-a43f-b1bef3de2693</paymentID>
<status>Settled</status>
</jsonObject>
</soapenv:Body>
</soapenv:Envelope>
<script language="nashornJs"><![CDATA[
var doctor = {
		name : "x",
		fee : 200
	  };
mc.setProperty("scriptObject", doctor);
 
var payload = mc.getPayloadJSON();
var results = payload.actualFee;
doctor.fee = results;
mc.setPayloadJSON(doctor);
]]></script>
com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.