ServiceMix Scripting

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

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.

Maven Archetype

You can use Maven servicemix-scripting-service-unit archetype to create a Scripting service unit:

mvn archetype:create \
    -DarchetypeGroupId=org.apache.servicemix.tooling \
    -DarchetypeArtifactId=servicemix-scripting-service-unit \
    -DarchetypeVersion=2010.01 \
    -DgroupId=your.group.id \
    -DartifactId=your.artifact.id \
    -Dversion=your-version

Once you've customized the service unit, simply install the SU:

mvn install

Remember that to be deployable in ServiceMix, the ServiceUnit has to be embedded in a Service Assembly: only the Service Assembly zip file can be deployed in ServiceMix.
To add your SU in a SA, you need to define it in the dependency sets:

<dependency>
  <groupId>your.group.id</groupId>
  <artifactId>your.artifact.id</artifactId>
  <version>your-version</version>
</dependency>

Endpoint Configuration

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

Scripting 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

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.

  • No labels