Enabling Modern Scripting in AnypointStudio
Mule Mixed JVM Languages Series
MuleSoft's AnypointStudio 3.5 and Mule 3.5 are the most current versions of the Mule integration platform tools. Mule scripting support at the flow components and transforers level is excellent but the actual scripting engines that shipping with it are stale and buggy (Jython 2.2.1 and Groovy 1.8.1). Any serious Mule development that relies on scripting must update these scripting engines for the AnypointStudio IDE and for the Mule stand-alone server.
Python, Groovy, and JavaScript, Oh My!
The authors of this HOWTO have over 5 years of experience delivering Mule applications and components written in Python for
high volume enterprise and consumer applications. Most were not just code scriptlets
but full-fledged Python modules deployed to $MULE_BASE/lib/user
and enabled in Mule flows. Groovy
wasn't a priority for this team because of its lack of portability outside JVM environment when compared
to Python. JavaScript was left to wiser developers in the web browser world.
The setup and techniques described here apply to Groovy and JavaScript as well. If you know these languages, all you have to do is replace the appropriate .jar files and versions in the scripts, and otherwise follow the same steps in the next sections.
Pre-Installation
- Download a copy of the latest stable, stand-alone version of the scripting engine - Jython
- Download a release candidate if you want; for your purposes, this may be stable enough - Jython
- Stop any stand alone running Mule servers
- Exit AnypointStudio
Scripting Engine Version
The rest of this document uses Jython 2.7 beta 2 because it's very stable when it comes to language and standard Python library support. The application validation tests passed for this version with flying colors. Use the Jython 2.5.3 run-time if there are any concerns about running the beta code in production.
AnypointStudio Upgrade
Find the stand alone scripting engine .jar in the file system. This is often in $HOME/Downloads
.
Find the AnypointStudio directory. This is often in $HOME/AnypointStudio
.
Execute in the shell:
freshEngine=$(find $HOME/Downloads -name "*jython*")
staleEngines=$(find $HOME/AnypointStudio -name "*jython*")
# DO NOT encase $staleEngines in quotes in this 'for' loop:
for staleEngine in $staleEngines; do engineHome=$(dirname "$staleEngine"); rm -vf "$staleEngine"; cp -v "$freshEngine" "$engineHome"; done
The Jython run-time is installed using this sequence because it must start along with the main server container. Including the scripting engine .jar file in the Maven or project Build path is not enough because the scripting engine must be loaded and available to all apps in the server. The scripting engines work side-by-side with other Mule components, such as the Mule Expression Language, loggers, transformers, etc. They are part of the server bootstrapping infrastructure, not application-level objects.
Start AnypointStudio, and create a simple flow that uses a Python component for testing the new configuration.
The Mule flow configuration file:
<flow name="CurrentPythonValidationFlow" doc:name="CurrentPythonValidationFlow" initialState="started" processingStrategy="synchronous">
<http:inbound-endpoint exchange-pattern="request-response"
host="localhost" port="8090" doc:name="CheckPythonVersion" path="python_version"/>
<scripting:component doc:name="PythonVersionComponent">
<scripting:script engine="jython"><![CDATA[#
# Flush left like this - Python indentation sensitivity
import sys
versionInfo = dict()
versionInfo["language"] = "py"
versionInfo["version"] = (u"%d.%d" % (sys.version_info[0], sys.version_info[1]))
versionInfo["transformedPayload"] = payload.upper()
result = versionInfo
]]></scripting:script>
</scripting:component>
<json:object-to-json-transformer encoding="UTF-8" mimeType="application/json" doc:name="PythonVersion2JSON"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
And a validation test that shows the script being called, and the resulting Python object being converted to JSON in the payload:
curl -i http://localhost:8090/python_version
# Output:
HTTP/1.1 200 OK
Date: Tue, 10 Jun 2014 00:03:52 -0700
Server: Mule EE Core Extensions/3.5.0
Content-Type: application/json;charset=UTF-8
X-MULE_SESSION: rO0ABXNyAC...4269
X-MULE_ENCODING: UTF-8
Content-Length: 61
Connection: close
{"language":"py","version":"2.7","transformedPayload":"/PYTHON_VERSION"}
The sample script validates the success of the scripting engine upgrade becase it includes two lines that will break the default Jython 2.2.1 that comes with AnypointStudio and Mule 3.5 CE and EE:
- The import statement isn't supported in Jython 2.2.1
- The
payload.uppper()
method invocation will fail on any Jython version older than 2.5.0.
Mule Stand Alone Upgrade
Install the Jython run-time .jar in $MULE_BASE/lib/user
as described in the Dynamic App Runtime Updates Using Mule Punching HOWTO.
Run the same cURL command as in the previous section and validate the output in the command line and the Mule log:
Production Deployment
Production deployments that rely on scripting must handle Mule Integration Platform installation in two steps:
- Install the Mule ESB (and the enterprise license file, if applicable) per the MuleSoft provisioning instructions
- Write a script for deleting the stale scripting engines and installing the new ones
Chef, Puppet, and Docker are excellent tools for handling a production deployment and the nuances of a customized installation.