Showing posts with label REST. Show all posts
Showing posts with label REST. Show all posts

Thursday, June 16, 2011

REST Services with Lombardi

This article is a supplement of Lombardi on mobile, in which it was discussed to have Lombardi services exposed as REST API for enabling mobile communication. REST is a very sought after API for any product due to the fact that REST is capable of emitting JSON which can be easily consumed by Web 2.0 and mobile applications. Lombardi support provides a REST API which extensively uses Lombardi Web API which Lombardi does not recommend after TeamWorks version 6. The objective of this article is to outline an approach to expose RESTful services of Lombardi API without using Lombardi Web API.

This post outlines a methodology to expose RESTful services for some of the common tasks of Lombardi like, process initiation and adding comments to a process instance taking them as examples. Any API call from Lombardi which needs to be exposed as REST should be exposed as a SOAP Webservice, since Lombardi does not provide the capability to directly expose the API calls as RESTful service. If a BPD needs to be invoked, a general system service needs to be exposed as SOAP Webservice. The actual instantiation of the process should happen with the general system service.




For example, a BPD can be invoked using the following command, embedded in a Server script activity of general system service.

// to start a process var processInstance = tw.system.startProcessByName(processName, InputParameterMap); // to add comment to a process instance var processInstance = tw.system.findProcessInstanceByID(processId); processInstance.addComment("Hello!");

Lombardi provides a Webservice implementation component which can be used to expose general system service as SOAP Webservices. A stand alone service layer built on Spring3 framework would consume the SOAP Webservices and convert them to RESTful services using Spring3 REST support. Stand alone services can decouple the transformation logic from Lombardi. Also, deploying them as stand alone would mean that Lombardi product code is not tinkered and hence not endangering future product patches and also this helps fully leveraging Lombardi warranty support.

Below are the examples of code snippets of Spring controller which calls a SOAP Webservice (Lombardi API exposed as SOAP Webservice) and exposes the method as RESTful service which would emit XML or JSON.

// controller method to invoke a process @RequestMapping(method = RequestMethod.GET, value = "/startCalcGDPProcess", headers = "Accept=application/xml, application/json") public @ResponseBody String startCalcGDP() throws Exception { RunGDPPortTypeProxy proxy = new RunGDPPortTypeProxy(); String pi = proxy.startGDP(); return pi; } // controller method to add a comment to a process instance @RequestMapping(method = RequestMethod.POST, value = "/addCommentToGDP", headers = "Accept=application/xml, application/json") public ModelAndView addCommentToGDPProcess(@RequestBody String body) { Source source = new StreamSource(new StringReader(body)); ProcessInstance e = (ProcessInstance) jaxb2Mashaller.unmarshal(source); addCommentToGDPProcess.add(e); return new ModelAndView(XML_VIEW_NAME, "object", e); }
A sample Spring servlet configuration for REST based services.
<!-- To enable @RequestMapping process on type level and method level --> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="marshallingConverter" /> <ref bean="atomConverter" /> <ref bean="jsonConverter" /> </list> </property> </bean> <!-- Client --> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"> <property name="messageConverters"> <list> <ref bean="marshallingConverter" /> <ref bean="atomConverter" /> <ref bean="jsonConverter" /> </list> </property> </bean> <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>dw.spring3.rest.bean.ProcessInstance</value> </list> </property> </bean> <bean id="lombardiRestAPI" class="org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg ref="jaxbMarshaller" /> </bean> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="mediaTypes"> <map> <entry key="xml" value="application/xml" /> <entry key="html" value="text/html" /> </map> </property> <property name="viewResolvers"> <list> <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </list> </property> </bean> <bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> <constructor-arg ref="jaxbMarshaller" /> <property name="supportedMediaTypes" value="application/xml" /> </bean> <bean id="atomConverter" class="org.springframework.http.converter.feed.AtomFeedHttpMessageConverter"> <property name="supportedMediaTypes" value="application/atom+xml" /> </bean> <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes" value="application/json" /> </bean>

This approach might sound little bit awkward for having a RESTful service invoking a SOAP Webservice, however this methodology effectively decouples the Lombardi API calls from generating RESTful services.