ESB services involve working with a variety of different data formats and structures e.g. XML, JSON, CSV, spread sheets, key-value structures. Transformations between XML and other data structures are quite common when it comes to developing an ESB layer. Mule ESB provides a wide range of choices when it comes to scripting and data transformation. There’s enough choice to satisfy the proclivities of any developer.
Scripting languages have become popular in recent times because of their first-class support for data structures such as arrays and maps which become a natural complement for markup languages such as XML and JSON. On the JVM, one popular scripting choice is Groovy.
Groovy Primer
The language syntax is mostly similar to Java and it supports calling any existing Java code/libraries. However Groovy’s dynamic typing and optional semi-colons and parentheses make Groovy code more succinct.
For example, compare this simple Java:
import java.util.List; | |
import java.util.ArrayList; | |
List mylist = new ArrayList<String>(); | |
myList.add("Hello"); | |
myList.add("World"); | |
System.out.println(list); |
With the corresponding Groovy
// no type declarations needed | |
// optional semicolins | |
// literal string syntax | |
def myList = ['Hello', 'World'] | |
// easy STDOUT printing | |
// optional method parentheses | |
println myList |
Groovy also has very clean and powerful syntax for building complex nested data structures (common in data mapping tasks).
// list literal syntax (java.util.List under the hood) | |
def aList = [1,2,[4,5,6]] | |
// map literal syntax (java.util.Map) | |
def aMap = [ | |
'name' : 'Tom Smith', | |
'dob' : [ | |
'year':1980, | |
'month':3, | |
'day': 20 | |
] | |
] |
For more information on the Groovy language, see the Groovy project home page, this Groovy Syntax Cheat Sheet or this Language Tutorial.
Groovy Builders
Construction of complex hierarchical data structures in Groovy and similar languages uses the ‘builder’ concept. Builders use closures and meta-programming to let developers create the kinds of data structure found in XML, JSON, UI widget hierarchies etc. For example, a basic mapping using a MarkupBuilder
:
def xml = new groovy.xml.MarkupBuilder() | |
xml.courses(year:"2013") { | |
courseName("Software Engineering") | |
courseName("Mechanical Engineering") | |
courseName("Electronics Engineering") | |
} | |
/* OUTPUT | |
<courses year='2013'> | |
<courseName>Software Engineering</courseName> | |
<courseName>Mechanical Engineering</courseName> | |
<courseName>Electronics Engineering</courseName> | |
</courses> | |
*/ |
And a more complex mapping, with namespaces, using a StreamingMarkupBuilder
:
def comment = "<![CDATA[<!-- address is new to this release -->]]>" | |
def builder = new groovy.xml.StreamingMarkupBuilder() | |
builder.encoding = "UTF-8" | |
// MAPPING | |
def person = { | |
// use mkp object which provides features like setting the namespace | |
mkp.xmlDeclaration() | |
mkp.declareNamespace('xsi':'http://www.w3.org/2001/XMLSchema-instance') | |
mkp.declareNamespace('ca':'http://org.org.org/xsd') | |
//start with the XML root node closure | |
ca.getEnrolledCoursesResponse { | |
//nested mapping | |
student{ | |
identifier("96678963") | |
} | |
courseEnrolment { | |
status("ACTIVE") | |
phoneNumberProvided("true") | |
//use mkp object to set the CDATA comment | |
mkp.yieldUnescaped(comment) | |
} | |
} | |
} | |
// WRITING | |
def writer = new StringWriter() | |
writer << builder.bind(person) | |
println writer.toString() | |
/* OUTPUT | |
<?xml version="1.0" encoding="UTF-8"?> | |
<ca:getEnrolledCoursesResponse xmlns:ca='http://org.org.org/xsd' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> | |
<student> | |
<identifier>96678963</identifier> | |
</student> | |
<courseEnrolment> | |
<status>ACTIVE</status> | |
<phoneNumberProvided>true</phoneNumberProvided> | |
<![CDATA[<!-- address is new to this release -->]]> | |
</courseEnrolment> | |
</ca:getEnrolledCoursesResponse> | |
*/ |
Hopefully this post has given you a taste of Groovy and how it can be used for creating data structures and writing data mappings. In Part 2 we’ll cover some approaches and helper code to tidy up Groovy data mapping scripts and make your mappings as clear and concise as possible.