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 service="test:myScriptingService" endpoint="scriptingEndpoint" script="classpath:MyGroovyScript.groovy" />
<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:
<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.