2 Replies Latest reply on Aug 28, 2013 10:06 AM by davidlilley

    json transformer for inbound jms topic?

    davidlilley

      I've read the documentation and I've tried the Json example, but I'm still not getting it I guess. I've bound a jms topic (HornetQ topic on JBoss 7.2) to a service. The incoming messages are json text.  I'd like to transform them to a Java object, so I added a transformer in the switchyard xml. Below is what I've tried so far. I'm sure this is wrong, but I don't understand how it is supposed to work. I was able to make it work with ObjectMapper, but I'd like to understand how JSon transformers are supposed to work when defined in the switchyard.xml.

       

      Thanks, Dave

       

      <?xml version="1.0" encoding="UTF-8"?>

      <switchyard xmlns="urn:switchyard-config:switchyard:1.0" xmlns:bean="urn:switchyard-component-bean:config:1.0" xmlns:jca="urn:switchyard-component-jca:config:1.0" xmlns:jms="urn:switchyard-component-camel-jms:config:1.0" xmlns:jpa="urn:switchyard-component-camel-jpa:config:1.0" xmlns:resteasy="urn:switchyard-component-resteasy:config:1.0" xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:trfm="urn:switchyard-config:transform:1.0" name="ngp-switchyard" targetNamespace="urn:org.test:ngp-switchyard:1.0">

        <sca:composite name="ngp-switchyard" targetNamespace="urn:org.test:ngp-switchyard:1.0">

          <sca:service name="JmsService" promote="JmsServiceBean/JmsService">

            <sca:interface.java interface="org.test.JmsService"/>

            <jms:binding.jms>

              <operationSelector operationName="processSession"/>

              <jms:contextMapper/>

              <jms:messageComposer/>

              <jms:topic>testTopic</jms:topic>

              <jms:connectionFactory>#ConnectionFactory</jms:connectionFactory>

            </jms:binding.jms>

          </sca:service>

          <sca:component name="JmsServiceBean">

            <bean:implementation.bean class="org.test.JmsServiceBean"/>

            <sca:service name="JmsService">

              <sca:interface.java interface="org.test.JmsService"/>

            </sca:service>

            <sca:reference name="PersistService">

              <sca:interface.java interface="org.test.PersistService"/>

            </sca:reference>

            <sca:reference name="LoggingService">

              <sca:interface.java interface="org.test.LoggingService"/>

            </sca:reference>

          </sca:component>

          <sca:component name="PersistServiceBean">

            <bean:implementation.bean class="org.test.PersistServiceBean"/>

            <sca:service name="PersistService">

              <sca:interface.java interface="org.test.PersistService"/>

            </sca:service>

          </sca:component>

          <sca:component name="LoggingServiceBean">

            <bean:implementation.bean class="org.test.LoggingServiceBean"/>

            <sca:service name="LoggingService">

              <sca:interface.java interface="org.test.LoggingService"/>

            </sca:service>

          </sca:component>

        </sca:composite>

        <transforms>

          <trfm:transform.json from="{urn:org.test:ngp-switchyard:1.0}messageData" to="java:org.test.model.MessageData"/>

        </transforms>

        <domain>

          <properties/>

        </domain>

      </switchyard>

       

      public interface JmsService {

         public void processSession(MessageData messageData);

      }

       

      @Service(JmsService.class)

      public class JmsServiceBean implements JmsService  {

         

          @Inject @Reference("LoggingService")

          private LoggingService _log;

         

          @Inject @Reference("PersistService")

          private PersistService _persist;

       

        @Override

        public void processSession(MessageData messageData) {

             _log.log(messageData);

             _persist.persist(messageData);

        }

      }

        • 1. Re: json transformer for inbound jms topic?
          kcbabo

          Declarative transformation (transform.json in this case) kick in when SY detects that the consumer and provider use different types for a message.  In the example you posted above, the provider is JmsServiceBean and it's interface is org.test.JmsService.  The consumer is represented by the composite service binding (think of this as a proxy through which external consumer communicate with a service inside your application) is JmsService and it's interface is also org.test.JmsService.  Since the consumer and provider have the same contract (and therefore the same message types), the transform.json you have defined does not kick in.

           

          Based on the following transformer definition:

          <trfm:transform.json from="{urn:org.test:ngp-switchyard:1.0}messageData" to="java:org.test.model.MessageData"/>
          

           

          I would expect to find an operation in the org.test.JmsService with a parameter of org.test.model.MessageData.  For the consumer contract, I would expect to see a different interface definition on the service binding.  You can either use a Java interface with annotations to specify the JSON type:

           

          package org.test;
          public interface JSONService {
                  @OperationTypes(in = "{urn:org.test:ngp-switchyard:1.0}messageData")
                  public void process(String msg);
          }
          

           

          <sca:service name="JmsService" promote="JmsServiceBean/JmsService">
                <sca:interface.java interface="org.test.JSONService"/>
          

           

          Or you can skip adding an additional Java interface and just use interface.esb to set the message type in switchyard.xml

           

          <sca:service name="JmsService" promote="JmsServiceBean/JmsService">
                <sca:interface.esb inputType="{urn:org.test:ngp-switchyard:1.0}messageData"/>
          

           

          I generally recommend against using interface.esb in composite services since Java and WSDL are more portable as a contract type.  That said, it's certainly possible to use interface.esb if you find the requirement to add a specific interface for the consumer to be overkill.

          • 2. Re: json transformer for inbound jms topic?
            davidlilley

            Thank you! I get it now. I was trying to use one interface both the incoming JMS service the bean. Once I separated them into two separate services with different interfaces, one for JmsJson and the other for the MessageData, the transform worked perfectly.