A few days ago, I was asked to create an example using Mule 3. The only requirements I had were that the example should be interesting, it should at least make use of data coming from a database, throw in some REST services, and have some interesting routing. I was given “poetic license” to create any example I wanted; how cool is that?
I also wanted to make this example easily deployable, that is, avoid installing databases, schemas or any other similar pre-requisites. Hence, I opted for an embedded database that can be loaded in the same JVM as the example itself. I opted to use Apache Derby. The next choice to make was which ORM system to use, if any at all. Open JPA from Apache was my choice. I must add at this point that there are no particular reasons why I chose these two products and you can argue that I could have chosen lighter, better, faster, and easier to use open source products. My answer to this would be, yes, you are probably right. But this is just meant to be a simple example which is not going to be deployed in a production environment. My main concern was making the example integrate with external systems while also making it simple to deploy in Mule, convenient to test as well as making it easily manageable from Maven. For example, Open JPA requires classes to be enhanced, however, this enhancing process can very easily be integrated with Maven using a simple plug-in.
After this brief introduction, lets now talk about the example itself. The database will contain one simple table; ‘Person’, storing some simple information about people, like name, surname, their job, age, and ID. A Java class was created to represent the entity and annotated using Java persistence annotations. A REST interface was exposed from which you could request all persons in the database, search by a person’s name, or retrieve a person by ID. From the REST interface, the user can also generate a new person and store it in the database. A pinch of coolness was also added to this REST interface by making it able to return the data back either in XML or JSON. JAX-B was used for the conversion of our Java class to XML and JSON. Also, all persons having the name of “Barack” will be returned as encrypted, but this will only be performed if the user asks for a list of persons, or searches by name. The data will be returned unencrypted if the user queries for the person using the ID. Additionally, to make things simple for the purposes of this example, only XML replies will have the data encrypted. Of course, when encrypting the data, the XML tags themselves will not be encrypted; only the data itself.
Now let’s start delving into a more technical description of the example. We can first start by describing the People class. This class has two very important roles. Firstly, it will be the class used when we need to load or persist data to the Person table; data from the database will be mapped into this class and vice versa. Secondly, this class will also be translated into XML or JSON form.
The first objective was achieved by using Java persistence annotations. The Person class was annotated using @Entity, while the ID getter was given 2 annotations, @Id and @GeneratedValue(strategy = GenerationType.AUTO) which makes the ID automatically generated. JAX-B helped achieving the second objective. The Person class was also annotated with the @XmlRootElement annotation. In this example, default settings were used for both JAX-B and JPA. The class listing is shown below.
JPA also requires a small configuration file in META-INF/persistence.xml which contains database information such as the JDBC connection URL, username and password for database access, and the entities (the Java classes annotated with @Entity). Here is the persistence.xml file from our example. We are telling JPA that we will be using the EmbeddedDriver from Derby and the JDBC connection URL. We are also listing our Person entity explained above.
The next move was to create a class to be able to initialise the JPA’s entity manager with ease from Spring. This is a very simple class with a private constructor because the aim was to have PoeticEntityManager as a singleton. A close() method was also implemented to close off the JPAs entity manager and factory before terminating the application. Note that the call to Persistence.createEntityManagerFactory() requires a parameter which is the name of the persistence unit to use. This persistence unit is the same one we defined in persistence.xml earlier in this example.
Next we need a helper class to perform our JPA queries. As explained earlier, we basically want the following functionality:
- A findAll() method to return all persons currently in the database,
- A findByName() method which will return all persons with a given name,
- A generate() method which will create a new person and persist it in the database,
- A findById() method.
All of these invoked methods employ the PersistenceUnit class created above.
The following is a code snippet for our PersonDao class:
From JPA, lets now move onto REST and define our REST interface, which is basically our communication channel with the user. Here we are using a couple of JAX-RS annotations, together with our PersonDao class implemented above to perform our database calls and mappings. Firstly, we will be annotating this class with the @Path annotation, denoting on which path we want our REST resource to be available. Furthermore, all methods are also annotated with the @Path annotation denoting on which path that particular method will be exposed. The @PathParam annotation is used to extract data from the URL and have that data mapped onto a simple Java parameter. @GET simply denotes that we are expecting a GET HTTP request. Other options are @POST, @DELETE, @PUT.
As you can see in our REST resource class, most methods are defined twice, but internally they do exactly the same thing. The only difference between the two methods is the @Produces annotation. xml*() methods have the annotation @Produces(“application/xml”) while json*() methods are annotated using @Produces(“application/json”). This simple annotation tells our REST resource whether it should use JAX-B to return XML or JSON data, which for all intents and purposes, I find really cool. Remember that we did not need any long and boring Java code to add this feature, but only a simple annotation.
At this point we can move on to the more interesting parts, the Mule configuration. In here we will tie up all the pieces we explained earlier, and introduce some new items, such as the encryption transformer used to encrypt the sensitive data, together with a custom transformer, implemented for this purpose.
To clarify things, I show small snippets of our Mule configuration. At the end of this blog, you will find the full Mule configuration file. Lets kick off by defining 3 beans in Spring: the entity manager, the person DAO object which requires the entity manager to be wired in, and the REST resource which needs the person DAO to fire the queries on the database.
The Mule flow will go something like this:
- Jersey will be used in conjunction with the HTTP transport to expose the REST resource.
- After Jersey invokes the appropriate method, the result is tested for the string sequence; <people>.
- If it is found, it would mean that the user did not search the person by ID, but either triggered a search by name or requested the list of all persons. Hence we need to perform the encryption.
Here is the first part of the configuration:
The component element is wrapped in <jersey:resources> tags to be able to read and react to the JAX-RS annotations present in our component. The result is simply transformed to String using the standard Mule object-to-string-transformer, and the resultant string is tested for the sequence <people> using a groovy transformer. If the expression returns true, we should perform the encryption process encryption which we are doing by sending the message to the splitter endpoint. The splitter is actually a Mule service and its job is that of splitting the XML into multiple smaller messages, one for each person element. The main reason behind this thinking is that if our machine has multicores/multiprocessors and processing is heavy, then we can take advantage of the multi-threading based architecture of Mule. If we send a separate message for each person element, the messages will be processed in a multi-threaded fashion once they are available on the inbound queue of the next service. An XPath expression is used to split the message which will return a DOMDocument containing one simple person node. The resultant node is forwarded to the processor flow: the flow which will do the actual encryption. The splitter service also contains an async-reply router with a collection aggregator configured. This will allow for the processor to answer on a different endpoint while the collection aggregator will correlate the processed messages belonging to the same group using the correlation ID and route one single collection of results back to the original caller.
Next up is the processor flow. Here we evaluate the DOMDocument object using XPath and look for people called Barack. If we do find Barack, we simply encrypt the data. For this, we need a custom transformer to look inside the XML elements and encrypt that data, not the whole XML node. This can easily be achieved if we do it with the help of Mule’s OOTB encryption transformer to perform the transformation, and a simple loop calling the encryption methods on each element in the DOM document as shown below.
The transformer together with the flow can be configured like the following code snippet. First, we create the security manager in Mule and set up the encryption strategy to use. In our case, we used a simple password based encryption strategy with a very trivial password (not suggested for real deployments). The next thing to configure is our custom transformer, wiring in the encryption strategy just defined.
The flow is a one way flow, reading XML DOM structures at the inbound, and applying the custom encryption transformer if the XPath expression (searching for the name Barack) matches. One the processing is done, the flow converts the XML DOM document to String and returns the result on the aggregator endpoint, where the correlation asynchronous reply router will be waiting.
The last few things we need to mention regard the final response. If our request is split and gets routed to the processor flow, then the result of the final correlation from the asynchronous reply router will be a collection, in which case we need to create the XML message back from all the singular encrypted XML responses. This should not be very difficult if we create a simple Java transformer to do the job for us.
<custom-transformer name="collectionToStringTransformer" class="com.ricston.transformers.CollectionToStringTransformer" / >
Once we have the transformer coded and configured in Mule, then we can create our response configuration. Using Groovy, we can check the type of the payload and apply the transformer only if necessary. Also we are checking if the response contains any XML code, if yes, then we set the content-type HTTP response header to application/xml, otherwise to text/plain.
The final Mule configuration should look something like the following:
After deploying the whole project in Mule 3 following the Mule deployment strategy, let us start Mule and hit the REST interface. Some examples are shown below:
A few words to conclude this blog, first of all I really hope you enjoyed it, but I also wanted to point out that many things here are NOT optimised, we are doing a lot of full text search and converting XML to Strings when maybe it could be avoided. The main aim of this blog was to create a fun example with some interesting cool stuff, which I think we achieved quite well since we managed to use an embedded database, OpenJPA, REST, XML Path and Mule 3 with some interesting routing patterns.