14 Replies Latest reply on Jun 23, 2012 12:11 PM by edevera

    JMS ObjectMessage with camel bindings

    edevera

       

      I would like to know if it is possible to use the @Transfomer annotation in a java to java transformation with a camel jms binding using a ObjectMessage containing a packagea.A instance and exposing the @Service operation with a packageb.B parameter.

       

      I have tried the following:

       

      {code}

      import packagea.A;

      import packageb.B;

       

      public class MyTransformer {

       

           @Tranformer

           public B transform(A a) {

                ...

           }

      }

      {code}

       

      {code}

      import packageb.B;

       

      @Service(IService.class)

      public class ServiceImpl implements IService {

           public void operation(B parameter) {

                ...

           }

      }

      {code}

       

      After having debugged a bit the code, based on the following facts:

       

      • I do see the transformer element being generated in the switchyard configuration file thanks to the maven plugin and I do see it being loaded during Weld initialization.
      • The result of the transformation is null, which is the value that arrives to the actual @Service implementation.
      • If I change the operation method to accept packagea.A parameters, then the JMSMessage to java Object seems to work perfectly.

       

      I have arrived to the hypothesis that the transformers are not chained and that I would need to implement my own JMSMessage to packageb.B transformer instead of packagea.A to packageb.B (which feels more natural).

       

      Note: From either the documentation or the quickstarts I see that all the transformations are XML to Java orientated using the @Transformer(from = "{urn:namespace:version}operation").


        • 1. Re: JMS ObjectMessage with camel bindings
          edevera

          After having debuged more, I see that Camel Converters kick in before Switchyard transfomers.

           

          The content returned by the Camel Converters is null (the code from the BaseTypeConverterRegistry.doConvertTo() returns a Void.Type which result into the BaseTypeConverterRegistry.convertTo() returning null which ultimately results into the ExchangeImpl class getting its content parameter as null.

           

          That looks like plausible explanation of why the java 2 java transfomer is not working as I expected.

           

          Of course this could also be a missunderstanding from my side about what the pupose of transformers is.

           

          Is there any documentation about when to use Camel Converters and when to use Switchyard transformers?

          • 2. Re: JMS ObjectMessage with camel bindings
            splatch

            Hey Eduardo,

            Could you please show your camel binding? If you receive message with camel-jms binding then camel conversion will always be executed first. So far switchyard uses camel type converters to handle some transformations.

             

            By default if you receive javax.xml.ObjectMessage then camel should set java.lang.Object as message body. To send javax.jms.ObjectMessage your message payload must be instance of java.io.Serializable.

            1 of 1 people found this helpful
            • 3. Re: JMS ObjectMessage with camel bindings
              edevera

              Thanks a lot for your response, which clarifies the issue.

               

              My binding is the following:

               

              <camel:binding.camel xmlns:camel="urn:switchyard-component-camel:config:1.0"

                                               configURI="jms://MyQueue?connectionFactory=%23JmsXA&amp;transactionManager=%23jtaTransactionManager&amp;transacted=true">

                              <camel:operationSelector operationName="save"/>

              </camel:binding.camel>

               

              So I understand I could have three alternatives:

              1. Implement my own Apache Camel @Converter making sure that it is available to the Apache Camel classpath (which I see could be problematic taking into account JBoss Modules and its restrictions and understanding that switchyard is a module installed on JBoss that is preferable not to modify for various reasons i.e. meaning adding dependencies to a inhouse converters in the module.xml).
              2. Create a java.lang.Object to packageb.B Switchyard @Transformer (which would potentially result into big Java to Java transformations).
              3. Leverage an Apache Camel service whose responsibility is basically to transform from one type to another (possibly the best solution).

               

              I do think the 3 option is an acceptable option. Nevertheless I would like to know if there is any plans for the implementation of any mechanism that enables one to register Switchyard @Transformers as Camel @Converters through some kind of configuration or annotation.

              • 4. Re: JMS ObjectMessage with camel bindings
                rcernich

                Hey Eduardo,

                 

                Another option might be to use a custom MessageComposer.  This allows you to create the message that ends up being passed through to the route.

                 

                That said, last time I tried there were some issues with MessageComposer on Camel bindings, so your mileage may vary.

                 

                Best,

                Rob

                • 5. Re: JMS ObjectMessage with camel bindings
                  splatch

                  Hey Eduardo,

                  I did some small test and it should work with Object messages:

                   

                  public class Item implements Serializable { }

                   

                  public interface SimpleCamelService {

                     String printItem(Item item);

                  }

                   

                  <sca:service name="SimpleCamelService" promote="ComponentName/SimpleCamelService">

                      <camel:binding.camel configURI="jms://queue?connectionFactory=#ConnectionFactory">

                          <camel:operationSelector operationName="printItem" />

                      </camel:binding.camel>

                  </sca:service>

                   

                   

                  Object message sent to queue is correctly received in service implementation.

                  • 6. Re: JMS ObjectMessage with camel bindings
                    edevera

                    Hi Lukasz,

                     

                    Yes, you are right. The object arrives correctly to the service as long as the object you put in the queue is of the same type as the parameter in the service. The problem arises when you have a object of class A being put in the queue and an object of class B being exposed as the parameter of the Service operation and trying to use a transformer to go from one to the other. My debugging experience tells me that camel messes up the transformation as it can't find a correct converter which results into a null message body.

                    • 7. Re: JMS ObjectMessage with camel bindings
                      kcbabo

                      Can you attach an example project that demonstrates this behavior?  The Camel gateway should use the object type declared in the composite service interface to do conversion.  The subsequent conversion between the composite service interface type and component service interface type should be handled by a SY transformer.  If this is not happening, then it's likely a bug (assuming the app config is correct).

                      • 8. Re: JMS ObjectMessage with camel bindings
                        edevera

                        I have attached the sample project. Please let me know if its my fault for not doing the things the right way, not understanding how the product works or if it is actually a bug.

                        • 9. Re: JMS ObjectMessage with camel bindings
                          kcbabo

                          First off, thanks for attaching the project source.  A project that can be used to quickly reproduce and debug an issue helps tremendously. That said, if you could include a test case and/or the output that you see when the project is deployed, that helps fill in the rest of the picture.  I took the project you attached, massaged it a bit, and added a test case to help debug it.  I have attached the revised version to this post.

                           

                          Once I added the test, I could see the NPE when the Camel route called OrderService.  It was a bit of a head scratcher since you did have a Bean1 -> Bean2 transformer registered.  Then I realized that the reference defined for the Camel route referenced a different type than what is used in the Camel route itself.  The Camel route has a message type of Bean1 and you define a service reference for that component with a message type of Bean2.  The service being called has a message type of Bean2, but the message type for your reference definition in the Camel route shouuld be Bean1.  That's what will trigger the transform from B1 -> B2.  I hacked up the switchyard.xml a bit to change the type used by the reference.  Note that I used interface.esb just to be quick, which allows me to state the input/output/fault type without using a Java or WSDL file.  This is just a shortcut and you could use a Java interface if you prefer.

                           

                          Build and test the attached project to confirm.

                           

                          hth,

                          keith

                          • 10. Re: JMS ObjectMessage with camel bindings
                            kcbabo

                            Oh, here's the attachment. :-)

                            • 11. Re: JMS ObjectMessage with camel bindings
                              edevera

                              Thanks for the example Keith! I'm sorry I haven't attached the test as I used mvn jar:sources which seems to have left out the test.

                               

                              I have gone over your code to see the differences and the only difference is the esb interface (besides the package names that I believe have no influence whatsoever). So my question is, is the esb interface the one tht fixes the null pointer problem? Or have I missed something else?

                              • 12. Re: JMS ObjectMessage with camel bindings
                                kcbabo

                                Right, the only change to the project was to the reference used by the Camel service component.  Since the Camel service is "sending" an object of type Bean1, the interface used by the reference needs to reflect that.  I went with interface.esb simply because I'm lazy and didn't want to create another Java interface for the consumer's contract.  A Java interface would work just as well, provided that the parameter type on the operation was of type Bean1.

                                • 13. Re: JMS ObjectMessage with camel bindings
                                  kcbabo

                                  I find that the visual tooling helps a lot in these situations.  Here's the model for your application:

                                  syApp2.jpg

                                   

                                  Walking from left to right:

                                   

                                  - The green service nub on MyServiceBuilder represents MyService and has a contract which indicates it accepts an object of type Bean1.

                                  - The purple reference nub on MyServiceBuilder has a contract which indicates it is using an object of type Bean1 for the invocation of OrderService.

                                  - The green service nub on OrderServiceBean represents OrderService and has a contract which indicates it accepts an object of type Bean2.

                                   

                                  The above scenario will trigger a declarative transformation on the invocation from MyService to OrderService of Bean1 -> Bean2.

                                  • 14. Re: JMS ObjectMessage with camel bindings
                                    edevera

                                    Nice diagram! I did install the tooling from the nightly builds but did not manage to obtain such diagram. I have to admit that I didn't try too hard, but just by double clicking and right clicking on the switchyard nodes of the project didn't take me too far. I do agree that tooling should increase the productivity and help to understand things easier. Thanks for the pic!