fredag 5 juli 2013

RESTful MongoDB and Mule ESB Community Edition pattern

There are some alternative ways to go when RESTifying your flows in Mule. However they are poorly described in manuals and forums and the components and tools available are not very active projects in the community. Struggling with Mule's REST router and other alternatives I settled for the built in Jersey way of doing it. However all examples from the Mule documentation and forums describe only how to enable REST components to your Http endpoint and return directly. The do not describe how to integrate the RESTful endpoint with your Mule ESB integration flows and hence take advantage of Mule ESB's other powerful integration abilities.

Here is how I do it:




I use a Http endpoint or Https if secure and couple it with a REST element like this:
 <jersey:resources doc:name="REST">  
      <component class="se.redpill.mulecomponents.mongo.RedpillRESTMongo"/>  
 </jersey:resources>  


The actual REST component is just plain Jersey Java, like this:
 @GET  
      @Path("mypath/{singleelement}")  
      @Produces({MediaType.APPLICATION_JSON})  
      public Map<String, Object> getQueryByName(@PathParam("singlelement") String name )   
      {   
           Map<String, Object> query = new HashMap<String, Object>();  
           query.put("MyCoolDocument.Type", "Cool");  
           query.put("MyCoolDocument.Unit", name);  
           query.put("Year", new Integer(2012));  
           return query;  
      }  


All fine. Now we use a Choice element to check on the inbound property if the request is
'http.method' GET, POST, PUT or DELETE and route each choice to its corresponding component. In my case I have a mapping to my own MongoDB components which are in the same format as my last blogpost.

Now to the real HACK to get this working:

If you tried something like this and failed you have probably seen that the object passed from the REST element  to your component is actually
org.mule.module.jersey.MuleResponseWriter$1
which is a pain to handle. But the payload can be casted to a
org.mule.api.transport.OutputHandler since its implementation comes from
org.mule.module.jersey.MuleResponseWrite

To avoid having to serialize / deserialize your own return value (in my case a Map) from your REST service to your next element (in my case my MongoDB query component) with casting techniques describe above you can instead do it in a much sager manner using the following statement:

           ContainerResponse cr = (ContainerResponse) eventContext.getMessage().getInvocationProperty("jersey_response");  
           Map<String, Object> map = (Map<String, Object>)cr.getResponse().getEntity();  

VOILA! We now have our Map back that we sent from our REST component.
My MongoDB Query component and all the others for PUT, POST and DELETE are implemented in this fashion like this:

 package se.redpill.mulecomponents.mongo;  
 import java.util.Map;  
 import org.mule.api.MuleEventContext;  
 import org.mule.api.lifecycle.Callable;  
 import com.mongodb.BasicDBObject;  
 import com.mongodb.DBCursor;  
 import com.mongodb.DBObject;  
 import com.sun.jersey.spi.container.ContainerResponse;  
 public class QueryMongoComponent extends AbstractMongoComponent implements Callable  
 {  
      @Override  
      public Object onCall(MuleEventContext eventContext) throws Exception {  
           ContainerResponse cr = (ContainerResponse) eventContext.getMessage().getInvocationProperty("jersey_response");  
           Map<String, Object> map = (Map<String, Object>)cr.getResponse().getEntity();  
           DBObject queryFields = new BasicDBObject(map);  
        String json = "[";  
        if(queryFields.keySet().size()>0)  
        {  
          DBCursor cursor = db.getCollection("mycollection").find(queryFields);  
             try {  
               while(cursor.hasNext()) {  
                 json += cursor.next() + ",";  
               }  
             } finally {  
               cursor.close();  
               json = json.substring(0,json.length()-1) + "]";  
             }  
        }  
        return json;  
      }  
 }  

And that's it!

REST enabled MongoDB with the power of Mule ESB CE integration flows at hand!

3 kommentarer:

  1. where is source of this example.

    SvaraRadera
  2. Great Article. its is very very helpful for all of us and I never get bored while reading your article because, they are becomes a more and more interesting from the starting lines until the end.

    Mulesoft online training

    SvaraRadera
  3. the blog is good and Interactive it is about Mule ESB – The best way to Integrate Amazon S3 it is useful for students and Mulesoft Developers for more updates on Mulesoft follow the link

    mulesoft Online Trainig Hyderabad

    For more info on other technologies go with below links

    Python Online Training

    tableau online training hyderabad

    ServiceNow Online Training

    SvaraRadera