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

Script Mediator

The Script Mediator is used to invoke the functions of a variety of scripting languages such as JavaScript, Groovy, or Ruby.

The  ESB  profile of WSO2 EI uses Rhino engine to execute JavaScripts. Rhino engine converts the script to a method inside a Java class. Therefore, when processing large JSON data volumes, the code length must be less than 65536 characters, since the Script mediator converts the payload into a Java object. However, you can use the following alternative options to process large JSON data volumes.

  • Achieve the same functionality via a Class mediator.
  • If the original message consists of repetitive sections, you can use the  Iterate mediator  to generate a relatively small payload using those repetitive sections. This will then allow you to use the Script mediator.
  • From WSO2 EI 6.2.0 onwards, the Script Mediator supports using Nashorn to execute JavaScripts, in addition to its default Rhino engine. For more information, see Script Mediator with Nashorn Support.

A Script mediator can be created in one of the following methods.

  • With the script program statements stored in a separate file, referenced via the Local or Remote Registry entry.
  • With the script program statements embedded inline within the Synapse configuration.

Synapse uses the Apache Bean Scripting Framework for scripting language support. Any script language supported by BSF may be used to implement the Synapse Mediator. With the Script Mediator, you can invoke a function in the corresponding script. With these functions, it is possible to access the Synapse predefined in a script variable named mc. The mc variable represents an implementation of the MessageContext, named ScriptMessageContext.java, which contains the following methods that can be accessed within the script as mc.methodName.

Return?Method NameDescription
YesgetPayloadXML()This gets an XML representation of SOAP Body payload.
NosetPayloadXML(payload)This sets the SOAP body payload from XML.
NoaddHeader(mustUnderstand, content)This adds a new SOAP header to the message.
YesgetEnvelopeXML()This gets the XML representation of the complete SOAP envelope.
NosetTo(reference)This is used to set the value which specifies the receiver of the message.
YessetFaultTo(reference)This is used to set the value which specifies the receiver of the faults relating to the message.
NosetFrom(reference)This is used to set the value which specifies the sender of the message.
NosetReplyTo(reference)This is used to set the value which specifies the receiver of the replies to the message.
YesgetPayloadJSON()This gets the JSON representation of a SOAP Body payload.
NosetPayloadJSON(payload)This sets the JSON representation of a payload obtained via the getPayloadJSON() method and sets it in the current message context.
YesgetProperty(name)This gets a property from the current message context.
NosetProperty(key, value)This is used to set a property in the current message context. The previously set property values are replaced by this method.

Implementing a Mediator with a script language has advantages over using the built-in Synapse Mediator types or implementing a custom Java class Mediator. The Script Mediators have the flexibility of a class Mediator with access to the Synapse MessageContext and SynapseEnvironment APIs. Also, the ease of use and dynamic nature of scripting languages allow the rapid development and prototyping of custom mediators. An additional benefit of some scripting languages is that they have very simple and elegant XML manipulation capabilities, which make them very usable in a Synapse mediation environment. e.g., JavaScript E4X or Ruby REXML.

For both types of script mediator definitions, the MessageContext passed into the script has additional methods over the standard Synapse MessageContext to enable working with XML natural to the scripting language. Example are when using JavaScript getPayloadXML and setPayloadXML, E4X XML objects and when using Ruby, REXML documents.

The Script mediator is a content-aware mediator.



Prerequisites

Listed below are the prerequisites for writing a Script mediator using JavaScript, Groovy, or Ruby.

Scripting LanguagePrerequisite
GroovyDownload the groovy-all-2.4.4.jar file and copy it to the  <EI_HOME>/dropins directory. Note that when you define the script, you need to start by importing Groovy.
Ruby

Install the JRuby engine for mediation. This is available in the WSO2 P2 repository as a feature (WSO2 Carbon - JRuby Engine for Mediation). See the instructions on how to install features in WSO2 EI.

Alternatively, you can download and install the JRuby engine manually: Download the jruby-complete-1.3.0.wso2v1.jar file from the WSO2 P2 repository and copy it to the  <EI_HOME>/dropins directory.

JavaScriptThe JavaScript/E4X support is enabled by default in the WSO2 Enterprise Integrator distribution and ready for use.

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 a 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: If this script type is selected, a script which is already saved in the registry will be referred using a key.




Examples

Example 1 - Using an inline script

The following configuration is an example of an inline mediator using JavaScript/E4X which returns false if the SOAP message body contains an element named symbol, which has a value of IBM.

<script language="js"><![CDATA[mc.getPayloadXML()..symbol != "IBM";]]></script>

Example 2 - Using a script saved in the registry

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

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

script language="js" indicates that the function invoked should be in the JavaScript language. The function named testFunction which is invoked should be saved as a resource in the Registry. The script can be as shown in the example below.

function testFunction(mc) {
     var symbol = mc.getPayloadXML()..*::Code.toString();
     mc.setPayloadXML(
        <m:getQuote xmlns:m="http://services.samples/xsd">
           <m:request>
              <m:symbol>{symbol}</m:symbol>
           </m:request>
        </m:getQuote>);
}

Example 3 - Adding an Include key

The following configuration has an include key.

<script language="js" key="stockquoteScript" function="transformRequest">
	<include key="sampleScript"/>
</script>

The script is written in JavaScript. The function to be executed is transformRequest. This function may be as follows in a script saved in the Registry.

// stockquoteTransform.js
function transformRequest(mc) {
transformRequestFunction(mc);
}

function transformResponse(mc) {
transformResponseFunction(mc);
}

In addition, the function in the script named sampleScript  which is included in the mediation configuration via the  include key sub element  is also executed in the mediation. Note that in order to do this,   sampleScript  script should also be saved as a resource in the  Registry. This script can be as follows.

// sample.js
function transformRequestFunction(mc) {
var symbol = mc.getPayloadXML()..*::Code.toString();
mc.setPayloadXML(
	<m:getquote m="http://services.samples">
		<m:request>
			<m:symbol>{symbol}</m:symbol>
		</m:request>
	</m:getquote>);
}
 
function transformResponse(mc) {
var symbol = mc.getPayloadXML()..*::symbol.toString();
var price = mc.getPayloadXML()..*::last.toString();
mc.setPayloadXML(
	<m:checkpriceresponse m="http://services.samples/xsd">
		<m:code>{symbol}</m:code>
		<m:price>{price}</m:price>
	</m:checkpriceresponse>);
}

Example 4 - Adding a custom SOAP header

You can add custom SOAP headers to a request by using the addHeader(mustUnderstand, content) of the Script Mediator in a proxy service as shown in the example below.

<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="CustomSOAPHeaderProxy"
       startOnLoad="true"
       statistics="disable"
       trace="disable"
       transports="http,https">
   <target>
      <inSequence>
         <log level="full">
            <property name="Message" value="IncomingRequest"/>
         </log>
         <script language="js">mc.addHeader(false, &lt;ns:sampleCustomHeader xmlns:ns="gsb:http://wso2.org/sample"&gt;&lt;ns:customInfo&gt;CustomHeader&lt;/ns:customInfo&gt;&lt;/ns:sampleCustomHeader&gt;);</script>
         <log level="full">
            <property name="Message" value="UpdatedMessage"/>
         </log>
         <drop/>
      </inSequence>
   </target>
   <description/>
</proxy>

Example per method

The following table contains examples of how some of the commonly used methods can be included in the script invoked by the following sample Script mediator configuration.

  <script language="js"
                 key="conf:/repository/EI/transform.js"
                 function="transform"/>
Return?Method NameExample
YesgetPayloadXML()

The script invoked can be as follows.

// sample.js02.function transformRequestFunction(mc) {
var symbol = mc.getPayloadXML()..*::Code.toString();
mc.setPayloadXML(
	<m:getquote m="http://services.samples">
		<m:request>
			<m:symbol>{symbol}</m:symbol>
		</m:request>
	</m:getquote>);
}

mc.getPayloadXML() returns the response received in XML form.

NosetPayloadXML(payload)See the example above for the getPayloadXML() method. mc.setPayloadXML( <m:getquote m="http://services.samples"> <m:request> <m:symbol>{symbol}</m:symbol </m:request> </m:getquote> ) is used in that script to set the XML representation of the SOAP body (obtained using the getPayloadXML() method) to the current message context.
NoaddHeader(mustUnderstand, Object content)

The script invoked can be as follows.

<script language="js"> 
<![CDATA[
var wsse = new Namespace('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'); 
var envelope = mc.getEnvelopeXML(); 
var username = envelope..wsse::Username.toString(); 
var password = envelope..wsse::Password.toString();   
mc.addHeader(false, <urn:AuthenticationInfo><urn:userName>{username}</urn:userName><urn:password>{password}</urn:password></urn:AuthenticationInfo>); 
]]>
</script> 

The addHeader method configured as

mc.addHeader(false, <urn:AuthenticationInfo><urn:userName>{username}</urn:userName><urn:password>{password}</urn:password></urn:AuthenticationInfo>) in the above script is used to extract user name and password values included in the request and add them to the header structure required for the backend service.

NogetEnvelopeXML()

The script invoked can be as follows.

<script language="js"> 
<![CDATA[
var wsse = new Namespace('http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'); 
var envelope = mc.getEnvelopeXML(); 
var username = envelope..wsse::Username.toString(); 
var password = envelope..wsse::Password.toString();   
mc.addHeader(false, <urn:AuthenticationInfo><urn:userName>{username}</urn:userName><urn:password>{password}</urn:password></urn:AuthenticationInfo>); ]]> </script> 
See more at: http://sajithblogs.blogspot.com/2013/08/wso2-EI-adding-complex-soap-headers-to.html#sthash.jqpiEmf0.dpuf
YesgetPayloadJSON()

The script invoked can be as follows.

function transform(mc) {
    payload = mc.getPayloadJSON();
    results = payload.results;
    var response = new Array();
    for (i = 0; i < results.length; ++i) {
        location_object = results[i];
        l = new Object();
        l.name = location_object.name;
        l.tags = location_object.types;
        l.id = "ID:" + (location_object.id);
        response[i] = l;
    }
    mc.setPayloadJSON(response);
}

mc.getPayloadJSON() returns the JSON payload (received as the response) as a JavaScript object. This object can be manipulated as a normal JavaScript variable within a script as shown in the above JavaScript code. See JSON Support for further information about how this script is used.


NosetPayloadJSON(payload)

See the example script for the getPayloadJSON() method.

The mc.setPayloadJSON() method can be used to replace the existing payload with a new payload. In the above script, we build a new array object by using the fields of the incoming JSON payload and set that array object as the new payload. See JSON Support for further information about how this script is used

YesgetProperty (name)

The script invoked can be as follows.

<script language="js">
<![CDATA[
 var time1 = mc.getProperty("TIME_1");
 var time2 = mc.getProperty("TIME_2");
 var timeTaken = time2 - time1;
 print("Time Duration :  " + timeTaken + " ms ");
 mc.setProperty("RESPONSE_TIME", timeTaken);
]]>
</script>

In this example, the getProperty method is used to get two time durations. The difference between the two time durations is calculated and the setProperty method is used to set this difference in the message context.

NosetProperty(property)

See the example for the getProperty method. The setProperty method is used to set the response time calculated from the time durations obtained (using the getProperty method) in the message context.

In the  ESB  profile due to a Rhino engine upgrade, when strings are concatenated and set as a property in the message context, you need to use the toString() method to convert the result to a string.

In the following example, var result = "a" and then result = result + "b". When concatenating these strings, the script invoked needs to be as follows:

<script language="js">
<![CDATA[
{var result = "a";
 result = result + "b";
 mc.setProperty('result_str', result.toString()); 
}]]>
</script>


Samples

The following samples demonstrate how to use the Script mediator.

See also /wiki/spaces/EI6xx/pages/49611304