Topic
10 replies Latest Post - ‏2012-02-24T22:37:21Z by SystemAdmin
SystemAdmin
SystemAdmin
126 Posts
ACCEPTED ANSWER

Pinned topic How to use custom wire format handlers with the JMS binding

‏2012-02-03T20:22:15Z |
I'm creating this new thread to respond to both this post in our open SCA forum as well as this one in the OSGi/JPSA forum.

Each post asks the same question: how to overwrite the replyTo so that the JMS binding's response will be sent to this destination rather than the replyTo on the incoming requestMessage sent by the original message producer.

Let me build on Steve's suggestion of using a custom wire format handler a bit.

First, I'm not sure how we really intended for the function to be used in this manner, and it is an undocumented usage. We originally intended the custom support to be used to handle custom, user-defined message headers and properties and custom payload formats.

Like Steve, I think this would work, and to Sriram and Matt, I would say to use it, and we will try to work with you to carry forward this type of support going forwards in future releases. (Obviously that applies in general, to everyone reading this forum as well.)

Now, I know the doc isn't as clear as it could be, but we'd be happy to work through some examples here on the forum.

The first thing to decide is what your SCA service interface to be.

Say you have methods with signature like:

public MyOutputType myMethod(MyInputType in);

Now the wire format handler interface is simply:

public Object transform(Object source)

So the logic of your transform method is going to look something like:




public Object transform(Object source)  
{ 
// if request path Message requestMsg = (Message)source; 
// reset replyTo on requestMsg 
// ... do anything else ... 
// produce MyInputType from message body 

return inputVal; 
// if response path 
// take source which is the Java return value 
// construct JMS Message using helper APIs 
// set Message somehow with return value 
}


This is a simple explanation since I'd like to wait to hear what you'd like your interface to look like before going into more detail. I didn't even show how to distinguish between request vs. response but I can in a follow-up post.

Note you do not have to use your custom wire format handler on the response path, simply because you use it on the request path. You may configure your binding with a different response wireformat (that's true in general with the JMS binding in WAS and it's true with custom wire format handlers in particular).

One more issue to note relates to a packaging issue involved with using OSGi as an SCA component implementation, as in Matt's example. (Sriram didn't mention an impl type).

As mentioned here
in section "Custom wire format and operation selector", there is a special attribute flag, 'deferLoad', which is needed when using user-defined types (such as MyInputType, MyOutputType in the example I mentioned).

So I'll stop there and look forward to some more details on your thoughts on the interface you'd like to use then.. or for any other questions.

Scott
Updated on 2012-02-24T22:37:21Z at 2012-02-24T22:37:21Z by SystemAdmin
  • SystemAdmin
    SystemAdmin
    126 Posts
    ACCEPTED ANSWER

    Re: How to use custom wire format handlers with the JMS binding

    ‏2012-02-05T22:54:11Z  in response to SystemAdmin
    Thank you scott. Matt and myself work for the same customer but tackling 2 different issues in SCA and OSGI space, hence the questions might have overlapped. Let me give a run down on the issues we are facing.

    We have SCA - JMS Text binding wire format as request response flow invoking OSGI Application. (See the composite XML below). The problem is request message producer creates a JMS ReplyTo queue manager information in the message header which SCA->OSGI does'nt want to use to send the response, as this process should go to a different destination than what is specified in Message header. If we blank out the ReplyTo Queue manager and queue, we can let SCA response destination configuration settings. Here is the sample SCA composite xml.

    <?xml version="1.0" encoding="UTF-8"?>
    <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:ns1="http://www.ibm.com/xmlns/prod/websphere/sca/1.0/2007/06" xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" autowire="false" name="JMSBindingReqResComposite" targetNamespace="http://com.sca.service.jms">
    <component name="InvokeBusinessProcess">
    <ns1:implementation.osgiapp applicationSymbolicName="com.foundation.osgi.appentry" applicationVersion="1.0.0"/>
    <service name="ProcessMessageBeanService" requires="exactlyOnce">
    <binding.jms name="TextBinding">
    <destination create="never" name="jms/RequestQueue" type="queue"/>
    <activationSpec create="never" name="jms/SCA_TWOWAY__AS"/>
    <response>
    <destination create="never" name="jms/ResponseQueue" type="queue"/>
    <connectionFactory create="never" name="jms/osgiapp.qcf.01"/>
    <tuscany:wireFormat.jmsText/>
    </response>
    <tuscany:wireFormat.jmsText/>
    </binding.jms>
    </service>
    </component>
    </composite>
    Here is the sample implementation method in OSGI application which consumes the message for processing.

    public class ProcessMessageImpl implements ProcessMessage {
    @Override
    public Object onMessage(Object messageContent)
    {
    System.out.println("onMessage Invoked from ProcessMessage OSGI Bundle");
    String text = messageContent.toString();
    System.out.println("onMessage Invoked with Text message " + text);
    }
    }

    I need one of the following scenarios to work.

    1. Need to strip the JMS ReplyTo queue manager and queue information from the request message, so SCA figure out the response destination thru it's configuration details.
    2. Make SCA as one way messaging and have custom logic to perform WAS connection factory and connection lookup and build response message and place it in the response queue. Unfortunately, we get hammered here as well because the lookup performed does not use container manager authentication and message gets populated without security credentials causing consumer to reject the message. Since there is no component managed authentication settings in WAS 7, we pretty much hit the wall. There is a separate high severity PMR opened by my colleague Matt on a bluprint - resource lookup issue.

    Coming back to your suggestion on having a transformation method to either strip out the incoming message request header details or building the response message, are you suggesting to change the SCA JMS binding from TextBinding to Custombinding and have logic flow thru with "transform" methods instead of "onmessage" in the implementation class. While I do understand the concept behind, would it be possible to elaborate the implementation details step by step. Really appreciate your help.
    • SystemAdmin
      SystemAdmin
      126 Posts
      ACCEPTED ANSWER

      Re: How to use custom wire format handlers with the JMS binding

      ‏2012-02-06T18:34:34Z  in response to SystemAdmin
      Sriram,

      Thanks for elaborating.

      When suggesting that you could override the request message replyTo, I didn't appreciate that you wanted to set the value to the same value already configured as the response destination on your JMS binding definition. (I was just thinking you had some other logic for determining this destination).

      Unfortunately though, there's no API you can use to get the binding config (e.g. response destination). Without this capability, I don't see that it's worth going down the custom wire format handler approach.

      I wonder if a better solution would be to use a one-way interaction in each direction. That is, instead of using a single request-response service, you could define an SCA component with a one-way service, with a JMS binding of course, and then on that component define a reference with a one-way operation which is separately bound (via JMS binding) to your response destination.

      As far as authenticating on the response path, let me start by mentioning that we do include the ability (as a WAS extension to OSOA) to define an auth alias directly on the binding, e.g.:

      
      <composite xmlns=
      "http://www.osoa.org/xmlns/sca/1.0" ... xmlns:websphere=
      "http://www.ibm.com/xmlns/prod/websphere/sca/1.0/2007/06" <component ... <reference ... <binding.jms websphere:authentication-alias=
      "SCA_Auth_Alias"> ...
      


      which will be used to create the JMS connection en route to creating and sending the response message.

      Does that help?

      Please note that when working bottom-up (starting from Java, rather than WSDL), an operation is denoted as one-way by a void return type and also the presence of either annotation:

      @javax.jws.Oneway
      OR
      @org.osoa.sca.annotations.OneWay

      Please let me know your thoughts on this approach.

      Thanks,
      Scott
      • SystemAdmin
        SystemAdmin
        126 Posts
        ACCEPTED ANSWER

        Re: How to use custom wire format handlers with the JMS binding

        ‏2012-02-06T18:48:32Z  in response to SystemAdmin
        Sriram,

        One more note, just following up on our earlier thread where we'd discussed transactional-related behaviors with the JMS binding.

        You'd need to make a tweak in order to achieve something like the exactlyOnce behavior on the two-way operation, in implementing my suggestion of two one-way operations.

        To do this, you can continue to use exactlyOnce on the service binding. But now also add the transactedOneWay intent on the reference binding in the "response" (is it more clear to say pseudo-response?) direction. The commit of the response message then happens in the same tran as receiving the request message and component dispatch itself.

        Scott
        • SystemAdmin
          SystemAdmin
          126 Posts
          ACCEPTED ANSWER

          Re: How to use custom wire format handlers with the JMS binding

          ‏2012-02-10T08:03:32Z  in response to SystemAdmin
          Scott,

          While implementing 2 one way flow, I am hitting a snag. I keep getting this exception even though my service interface is defined as @remotable and @oneway. Here is my service interface.
          import org.osoa.sca.annotations.Remotable;
          import org.osoa.sca.annotations.OneWay;
          @Remotable
          public interface ProcessMessage {
          @OneWay
          public void onMessage(Object messageContent);
          }

          I see another thread on similar lines, however the conclusion on the thread indicated the user did not have @remotable. In my case i have both. Any idea why I am getting this error.

          2/10/12 1:58:15:265 CST 00000041 TransportServ E Exception invoking service 'ProcessMessageBeanService
          org.osoa.sca.ServiceRuntimeException: javax.naming.NameNotFoundException: Context: P473M400Node01Cell/nodes/P473M400Node01/servers/server1, name: jms/DefaultSCAConnectionFactory: First component in name DefaultSCAConnectionFactory not found. Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0 at org.apache.tuscany.sca.binding.jms.context.JMSBindingContext.getJmsResponseSession(JMSBindingContext.java:87)
          • SystemAdmin
            SystemAdmin
            126 Posts
            ACCEPTED ANSWER

            Re: How to use custom wire format handlers with the JMS binding

            ‏2012-02-10T15:04:51Z  in response to SystemAdmin
            Hi Sriram,

            Can you please paste or attach your composite file, or at least the excerpt showing the full JMS binding?

            Thanks
            • SystemAdmin
              SystemAdmin
              126 Posts
              ACCEPTED ANSWER

              Re: How to use custom wire format handlers with the JMS binding

              ‏2012-02-13T05:07:52Z  in response to SystemAdmin
              Scott,

              Here is the SCA Component.

              <?xml version="1.0" encoding="UTF-8"?>
              <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0" xmlns:was="http://www.ibm.com/xmlns/prod/websphere/sca/1.0/2007/06" autowire="false" name="JMSBindingOneWayReqResComposite" targetNamespace="http://com.sca.binding.jms.oneway.req">
              <component autowire="true" name="InvokeOneWayBusinessProcess">
              <was:implementation.osgiapp applicationSymbolicName="com.osgi.appentry" applicationVersion="1.0.0"/>
              <service name="ProcessMessageBeanService" requires="exactlyOnce">
              <binding.jms name="TextBinding" correlationScheme="RequestCorrelIDToCorrelID">
              <destination create="never" name="jms/SCA_TWOWAY_CCSP_REQUEST"/>
              <activationSpec create="never" name="jms/SCA_TWOWAY_CCSP_AS"/>
              <tuscany:wireFormat.jmsText/>
              </binding.jms>
              </service>
              <reference name="com.osgi.appentry.DispatchResponseMessage" requires="transactedOneWay">
              <binding.jms name="ResponseMessage" correlationScheme="RequestCorrelIDToCorrelID">
              <destination create="never" name="jms/SCA_TWOWAY_CCSP_RESPONSE"/>
              <connectionFactory name="jms/SCA_TWOWAY_CCSP_CF"/>
              <tuscany:wireFormat.jmsText/>
              </binding.jms>
              </reference>
              </component>
              </composite>

              I am able finally make it work successfully (one way request and one way response with OSGI Implementation. was:authentication-alias is working as well. However I might have an issue on the correlation id.

              I need to pass the correlation id which comes from the request message to response message and the client is waiting. Since I split it from two way to one way request and one way response. How do you think i can propagate correlation id from service to reference. Appreciate your help.

              Thanks
              Sriram
              • SystemAdmin
                SystemAdmin
                126 Posts
                ACCEPTED ANSWER

                Re: How to use custom wire format handlers with the JMS binding

                ‏2012-02-14T17:09:30Z  in response to SystemAdmin
                Hi Sriram,

                Sorry for not considering the issue of the correlation ID with my suggestion of splitting the request/response into two one-ways. This is clearly a major flaw in my suggestion, sorry to say.

                I suppose we couldrevisit the idea of using a request/response with a custom handler setting the replyTo, thereby allowing the runtime to set the correlationID into the response message.

                Like I'd mentioned, the problem with this approach is there's no easy programmatic access given to the custom handler to get at the response destination configured on the binding. So you'd be left introducing and parsing your own properties file or something like that containing the response destination on the binding, which isn't a nice solution.

                In the meantime, let me talk it over with my team to see if we can come up with any better ideas.

                Scott
                • SteveKinder
                  SteveKinder
                  14 Posts
                  ACCEPTED ANSWER

                  Re: How to use custom wire format handlers with the JMS binding

                  ‏2012-02-23T14:39:17Z  in response to SystemAdmin
                  Sriram,

                  Our team met to discuss how to help you to move forward. One of the reasons we wanted to scrum is that our original thought to help the next issue you've encountered might look like we were sending you back around to something we've previously tried. One of the things we noticed was that while each of our feature suggestions solved the specific issue you had, the suggestion failed to be acceptable because of other requirements of your given scenario. Our team was wondering if we could have an informal conference call to further explore your scenario. If you are interested in helping us further understand your specific requirements, please drop me a email with some proposed times that would work best for you. (kinder@us.ibm.com)
                  • SystemAdmin
                    SystemAdmin
                    126 Posts
                    ACCEPTED ANSWER

                    Re: How to use custom wire format handlers with the JMS binding

                    ‏2012-02-24T22:33:13Z  in response to SteveKinder
                    Sriram,

                    Thank you for joining the conference call with our team today.

                    As we discussed, I think we have an approach which should work for you, which is to use the JMS binding's custom handler support to null out the replyTo in the incoming request Message so that the statically-configured response destination will be used to send the response Message.

                    I think it will be a bit simpler to use a custom operation selector rather than a custom wireformat handler in this use case, especially since, as you explained to us, your interface only consists of a single operation (so the "selection" logic is simple).
                    You can then go back to using the "wireFormat.jmsText" option to grab the TextMessage payload and send it to your service impl as a String parameter value.

                    So.. first, your composite file would look something like:

                    
                    <composite....>   <component name=
                    "MyComponent" xmlns:ts=
                    "http://tuscany.apache.org/xmlns/sca/1.0" xmlns:fep=
                    "http://www.ibm.com/xmlns/prod/websphere/sca/1.0/2007/06"> <implementation.java class=
                    "my.Impl"/> <service name=
                    "MyService"> <interface.java interface=
                    "my.MyService"/> <binding.jms fep:authentication-alias=
                    "MyAuthAlias"/> <activationSpec name=
                    "jms/ActivationSpec"/> <response> <destination name=
                    "jms/ResponseQ" type=
                    "queue" create=
                    "never"/> <connectionFactory name=
                    "jms/ResponseCF" create=
                    "never"/> </response> <ts:wireFormat.jmsText/> <fep:operationSelector.jmsCustom  class=
                    "custom.opsel.SingleOperationReplyToNullifierOpSel"/> </binding.jms> </service> </component>
                    


                    The Java service interface you'd implement would simply be:

                    
                    
                    
                    public 
                    
                    interface MyService 
                    { 
                    
                    public String myMethod(String payload); 
                    }
                    


                    And here's a custom operation selector, which I made it a bit more flexible in not needing to know the single operation name, given that you'll have the list of operation names in a context passed to your selector.

                    It could look like:

                    
                    
                    
                    package custom.opsel;   
                    
                    import java.util.List; 
                    
                    import javax.jms.*;   
                    
                    import com.ibm.websphere.soa.sca.operationselector.jms.OperationSelector; 
                    
                    import com.ibm.websphere.soa.sca.operationselector.jms.OperationSelectorException; 
                    
                    import com.ibm.websphere.soa.sca.wireformat.WireFormatContext;   
                    
                    public 
                    
                    class SingleOperationReplyToNullifierOpSel 
                    
                    implements OperationSelector 
                    {   
                    
                    private WireFormatContext ctx;   @Override 
                    
                    public String getOperationName(Message msg) 
                    
                    throws OperationSelectorException 
                    { 
                    // 
                    // Null out replyTo so response gets sent to  
                    // <binding.jms> response destination 
                    // 
                    
                    try 
                    { msg.setJMSReplyTo(
                    
                    null); 
                    } 
                    
                    catch (JMSException e) 
                    { 
                    
                    throw 
                    
                    new RuntimeException(e); 
                    } 
                    
                    return computeOperationName(msg); 
                    }   
                    /* * Only useful for a single operation interface, as this gets just * a list of operation names from interface and returns the first one. * * Or, just return the single operation name of course. */ 
                    
                    private String computeOperationName(Message msg) 
                    { List<String> opNames = ctx.getOperationNames(); 
                    // Not done here, but you might want to validate  
                    // it's a single-operation interface. 
                    
                    return opNames.get(0); 
                    }   @Override 
                    
                    public WireFormatContext getWireFormatContext() 
                    { 
                    
                    return ctx; 
                    }   @Override 
                    
                    public 
                    
                    void setWireFormatContext(WireFormatContext ctx) 
                    { this.ctx = ctx; 
                    } 
                    }
                    


                    If you use Rational Application Developer with the SCA Tools feature configured your SCA projects will have the classpath needed to compile this. (If not you'll have to point to the runtime JARs.)

                    Having written that up, I'm thinking you might beat me to the act of actually testing it, so please let us know on the forum how this works out for you!

                    Thanks,
                    Scott
                    • SystemAdmin
                      SystemAdmin
                      126 Posts
                      ACCEPTED ANSWER

                      Re: How to use custom wire format handlers with the JMS binding

                      ‏2012-02-24T22:37:21Z  in response to SystemAdmin
                      Just to clarify, we are moving back to a request-response operation, so that the runtime can set the correlation id in the response message.

                      We still don't have a means for programmatically setting the replyTo to the binding-defined response destination (or accessing the binding info programatically in general). But we don't think we need to given that we hope simply nulling out the replyTo will cause the response destination to be used.