6 Replies Latest reply on Sep 29, 2010 2:53 AM by davsclaus

    Exposing REST interface using Camel and SMX

    ramesh.ramakrishnan

      Hello All,

       

      I have a beginner's question in integrating REST service with Camel. My requirement is to expose a REST service as http endpoint (takes both JSON and XML) and transform the input request to output by following a route sequence.

       

      I used cxf:rs server element to expose my REST as http endpoint and here is my sample route.

       

      from("cxfrs://bean://orderService") // STEP 1

          .convertBodyTo(CustomOrderPojo.class)  // STEP 2

          .to("xslt:convertCustomOrder.xsl)  // STEP 3

          .to("jbi:servce:WSDL_LOCATION?mep=In-OUT")  // STEP 4

          .to("xslt:convertSOAPResponseToCustomOrder.xml")  // STEP 5

          .convertBodyTo(CustomOrderPojo.class)  // STEP 6

       

      STEP 1: Receive a JSON or XML when client involes REST Soap

      STEP 2: Convert incoming XML or JSON to the object as expected by REST method

      STEP 3:Convert POJO to xml which will act as Payload (soap:body) for JBI soap call

      STEP 4: Invoke SOAP service using jbi:service endpoint

      STEP 5: TRansform the result of SOAP call back to Custom Order pojo with populated values

      STEP 6: Unmarshal it back to POJO.

       

      My understanding is, once the last part of chain is reached, the BODY is sent back to the original sender i.e. the person calling the Service.

       

      Is this the right approach?

       

      Problems am facing.

       

      1. With ConverBody at step 2, its throwing

      Caused by: org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: java.lang.Object[] to the required type: CustomOrderPojo.class

       

      2. If i remove the convertBodyTo and feed the input XML/JSON to the xsl, am getting the following exception

      org.apache.camel.ExpectedBodyTypeException: Could not extract IN message body as type: interface javax.xml.transform.Source body is: [Ljava.lang.Object;@54c90c7

       

      Can anyone pointme to a working example which performs this logic?

       

      Thanks.

        • 1. Re: Exposing REST interface using Camel and SMX
          davsclaus

          Is this the right approach?

          Yes the message to send back to the client after step 6.

           

          See unit tests in the camel-cxf component for the cxfrs for examples

          https://svn.apache.org/repos/asf/camel/trunk/components/camel-cxf/

          • 2. Re: Exposing REST interface using Camel and SMX
            davsclaus

            I also created a ticket at Apache so we will add a REST based example in a future release

            https://issues.apache.org/activemq/browse/CAMEL-3168

            • 3. Re: Exposing REST interface using Camel and SMX
              ramesh.ramakrishnan

              Hello Claus, thanks for your quick response. However, I still have issue as the incoming XML (or JSON) isn't getting converted in to the JAXB custom pojo.

              If i do,

               

              from("cxfrs://bean://myService").process(new Processor() {

              @Override

              public void process(Exchange exchange) throws Exception {

              Message inMessage = exchange.getIn();      

              MyJaxBPojoClass myPojo= inMessage.getBody(MyJaxBPojoClass .class);

              }}).convertBodyTo(MyJaxBPojoClass .class)

               

              I get the following exception, Caused by: org.apache.camel.NoTypeConversionAvailableException: No type converter available to convert from type: java.lang.Object[] to the required type:test.package.MyJaxBPojoClass. Also, myPojo object is null.

               

              Do I need to have custom type converter that transforms incoming generic object to custom JaxB object?

               

              Many thanks.

              • 4. Re: Exposing REST interface using Camel and SMX
                davsclaus

                Yeah could be.

                 

                I bet CXF-RS may store the incoming message in some CXF specific way which may not be easily converted using JAXB.

                 

                Use a Camel Processor and see what Exchange contains.

                 

                We can maybe do some improvement in CXF-RS. I think we did that for CXF-WS so it had a fallback type converter feature. Most likely CXF-RS needs something similar.

                 

                You are welcome to create a small project and ZIP it we can use as an example to improve CXF-RS. If needed.

                • 5. Re: Exposing REST interface using Camel and SMX
                  ramesh.ramakrishnan

                  Hello Claus,

                   

                  Thanks for the response. If not for your response, would have spent sometime thinking that something wrong with my configuration. I did a quick workaround by creating a custom Processor and retrieved 0th element from the Object array and converted it to the JAXB object. This worked like magic

                   

                  My CustomProcessor code is,

                   

                  public class MyCustomProcessor implements Processor {

                         @Override

                  public void process(Exchange exchange) throws Exception {

                  /* Extract the incoming Object[] and get the 0th element from it.

                  * This 0th element should be then set to the Body of IN Message */

                  ObjectArray objects = (Object[]) exchange.getIn().getBody();

                  exchange.getIn().setBody(objects[0]); }}

                  Note: ObjectArray is actually array of Object. Since there arent any markup to post, its interpreting array notation as URL.

                   

                  My final route,

                   

                  from("cxfrs://bean://myRESTService").process(new MyCustomProcessor())

                  .to("xslt:convertCustomOrderToSOAP.xsl) // Perform XSLT

                  .to("jbi:servce:WSDL_LOCATION?mep=In-OUT") // Call SOAP endpoint

                  .convertBodyTo(String.class) // transform response to String

                  .to("xslt:convertSOAPToCustomOrder.xsl") // Perform XSLT to get SOAP body

                  .convertBodyTo(CustomOrderPojo.class) // Final conversion before sending it back to caller

                  • 6. Re: Exposing REST interface using Camel and SMX
                    davsclaus

                    Thanks for reporting that you found a solution.

                     

                    I have created a ticket to improve CXF-RS in the future so you most likely don't need your custom processor workaround

                    https://issues.apache.org/activemq/browse/CAMEL-3175