ServiceMix Scripting

The ServiceMix Scripting component provides support for processing scripts using JSR-223.

Availability

Note that this component is only available in releases >= 3.3.

What is JSR-223

Scripting for the Java Plaform (JSR-223) is a API that standardizes the way scripting language are integrated within a Java application. Have a look at the project site to get an overview what languages are available and what dependencies they have (https://scripting.dev.java.net/).

The servicemix-scripting engine is packaged with the following engines:

  • Groovy (1.5.6)
  • JRuby (1.1.2)
  • Rhino JavaScript (1.7R1)

You don't need to care about dependencies for these 3 languages. For every other language take care to put the dependencies into your SU or the container classpath.

Installation

Installing the servicemix-scripting component can be done in several ways:

  • drop the installer zip in an hotdeploy directory monitored by ServiceMix
  • using ant tasks

Note that when using ant tasks, the component is not started, you will have to start it manually using ant tasks or a console.

Creation

You can use Maven to create a service unit.

mvn archetype:create \
    -DarchetypeGroupId=org.apache.servicemix.tooling \
    -DarchetypeArtifactId=servicemix-scripting-service-unit \
    -DgroupId=com.mycompany.myproduct \
    -DartifactId=mycomponent.artifact

or simply use the smx-arch tool from ServiceMix's bin folder.

Endpoints

Endpoint for InOut MEP
<scripting:endpoint service="test:myScriptingService" 
                    endpoint="scriptingEndpoint"
                    script="classpath:MyGroovyScript.groovy" /> 
Endpoint for InOnly MEP
<scripting:endpoint service="test:myScriptingService" 
                    endpoint="scriptingEndpoint"
                    script="classpath:MyGroovyScript.groovy" 
                    targetService="test:anotherService"/> 

The following table shows the additional configuration possibilities of the endpoint.

endpoint attributes
Name Type Description Default
marshaler class org.apache.servicemix.scripting.ScriptingMarshalerSupport DefaultScriptingMarshaler
script String Spring Resource for the script file null (must be spec'd)
language String script language to use (groovy, jruby, js etc) autodetect (via file extension)
logResourceBundle String Log Resource Bundle for Script Logger null
scriptLogger class java.util.logging.Logger null
disableOutput boolean flag if no out message should be sent false
copyProperties boolean flag if the message header will be copied to out message false
copyAttachments boolean flag if the message attachments will be copied to out message false
bindings class java.util.Map null
targetInterface QName the target interface null
targetOperation QName the target operation null
targetService QName the target service null
targetEndpoint String the target endpoint null
targetUri String target uri null

For all xbean file endpoint configuration take a look at Xml schemas

The script resource

The script resource can be defined in different ways:

 
script="classpath:MyScript.js"
  OR  
script="file:///home/lhein/scripts/groovy/MyGroovyScript.groovy"

The user bindings

You can specify user bindings to be available from inside the script as variables. For doing this you can specify the
attribute bindings inside the endpoint's configuration.
The bindings object is a simple Map<String, Object> which contains key - value pairs.

Example:

<beans xmlns:scripting="http://servicemix.apache.org/scripting/1.0"
       xmlns:test="http://servicemix.apache.org/test"
       xmlns:util="http://www.springframework.org/schema/util">
       
    <!-- JavaScript JSR-223 Endpoint  -->
    <scripting:endpoint
        service="test:js-jsr223" 
        endpoint="endpoint"
        script="classpath:MyJavaScriptFile.js"
        bindings="#myCustomBindings" />
            
    <util:map id="myCustomBindings">
        <entry key="company" value="My Company" />
        <entry key="logo" value="/home/lhein/myLogo.png" />
    </util:map>   

</beans>

These values (company and logo) are available from within the MyJavaScriptFile.js via a global variable called "bindings".
You could now just do the following inside your javascript: (adapt this for other languages)

var companyName = bindings.get("company");
var companyLogoPath = bindings.get("logo");

Marshalers

You can write your own marshalers to have a possibility to influence the bahviour of the engine.
To do this you simply need to subclass the org.apache.servicemix.scripting.DefaultScriptingMarshaler or even create a new class
implementing the interface ScriptingMarshalerSupport if you don't want to start from scratch.

onStartup (...)

This method is called by the endpoint when the endpoint is starting.

onShutdown (...)

This method is called by the endpoint when the endpoint is shutting down.

getScriptCode (...)

This method is called to get the input stream for the script defined in script attribute of the xbean configuration.

registerUserBeans (...)

This method is called after all scope variables of the endpoint where set, just before starting the script.

After finishing your marshaler you can simply configure your endpoints to use it:

Marshaler example
<scripting:endpoint service="test:myScriptService" 
             endpoint="scriptingEndpoint"
             script="classpath:MyScript.rb" > 

    <property name="marshaler">
        <bean class="com.mycompany.MyScriptingMarshaler" />
    </property>

</scripting:endpoint>

Global variables

While inside the script you have a access to the following variables / objects:

Variable Description Type
componentContext The JBI Component Context javax.jbi.component.ComponentContext
deliveryChannel the Delivery Channel javax.jbi.messaging.DeliveryChannel
exchange The JBI Message Exchange javax.jbi.messaging.MessageExchange
inMessage The in message javax.jbi.messaging.NormalizedMessage
outExchange The JBI Message Exchange for the answer javax.jbi.messaging.MessageExchange
outMessage The out message for answer javax.jbi.messaging.NormalizedMessage
log The script logger object java.util.logging.Logger
endpoint the scripting endpoint which executes the script org.apache.servicemix.scripting.ScriptingEndpoint
endpointname the name of this endpoint java.lang.String
servicename the name of this service java.lang.String
interfacename the name of this interface java.lang.String
script the absolute path of the script or the script itself if path can't be determined java.lang.String or org.springframework.core.io.Resource
bindings a map containing user defined values java.util.Map<String,Object>

Migration from ScriptComponent / GroovyComponent

The servicemix-scripting is a full replacement of the lightweight components for "script" and "groovy".
As the lightweight components are no longer maintained and also won't work in ServiceMix 4 you are strongly encouraged to switch to this new engine.

What are the differences?

The GroovyComponent knew a binding / variable called builder which in fact was a DOMBuilder. This variable isn't available now. To have it again you could write your own marshaler and provide such a variable in the registerUserBeans(...) method.

Both components, GroovyComponent and ScriptComponent, knew the following configuration attributes:

  • scriptEngineName
  • compiledScript
  • scriptText

These attributes are no longer available.
Instead of scriptEngineName you could use the language attribute to define the language to use.

Instead of scriptText you could write your own marshaler overriding the getScriptCode (...) method to provide your scriptText.