9 Replies Latest reply on Jun 28, 2011 6:04 PM by Keith Babo

    Referencing SOAP services

    Magesh Bojan Master

      Jirka created a very good sample that is attached here:

       

      Reference to SOAP service is not properly bound

       

      I would like to explain the sample and highlight the two issues here.

       

      The sample has 2 services, ErrorService and ProxyService. Both of them are exposed as Webservices via SOAP binding. ProxyService references the Webservice exposed by ErrorService.

       

      There are two issues with the sample:

       

      1. The reference binding is not properly configured, yet the application gets deployed. The configuration is

        <reference name="RemoteService" promote="RemoteService">
            <binding.soap xmlns="urn:switchyard-component-soap:config:1.0">
                <wsdl>wsdl/ErrorService.wsdl</wsdl>
                <port>ErrorServicePort</port>
            </binding.soap>
        </reference>
        

        causes the following exception

        Caused by: org.switchyard.component.bean.BeanComponentException: Bean Component invocation failure.  Operation 'echoTwoWay' is not defined on Service 'RemoteService'.
                at org.switchyard.component.bean.ClientProxyBean$ClientProxyInvocationHandler.createExchange(ClientProxyBean.java:337)
                at org.switchyard.component.bean.ClientProxyBean$ClientProxyInvocationHandler.invoke(ClientProxyBean.java:290)
        

        Not sure if this is the right message. However changing the configuration like this, solves this issue.

        <reference name="RemoteService" promote="ProxyService/RemoteService">
            <binding.soap xmlns="urn:switchyard-component-soap:config:1.0">
                <wsdl>wsdl/ErrorService.wsdl</wsdl>
                <port>ErrorServicePort</port>
            </binding.soap>
        </reference>
        
      2. The sample assumes that injecting a @Reference to the Webservice consumer RemoteService will automagically convert the Java Object to SOAP request and transform it back to Java Object from SOAP response. This I am not sure we have implemented , I guess.

       

      So obviously the said JIRA issue above has to be split into two issues. Now I am vey keen in knowing about the point 2 above. Are we missing any default transformer configuration?

       

      PS: You will need to clean up the sample and replace the ip address with localhost. This was tested with AS7.

        • 1. Re: Referencing SOAP services
          Jiri Pechanec Apprentice

          Hi,

           

          ad 1) Blame Forge tooling. BTWI have strong feeling that sometimes component name is necessary and sometimes using it breaks things so it would be nice to now what is propoer policy. Do we support using multiple services that share the same interface?

           

          ad 2) You are not missing anything - the sample was built step-by-step and as I could not get it running I could not test the transformations. But if you look intor trnasfrom Java package then you'll find transfromers there

           

          J.

          • 2. Re: Referencing SOAP services
            Keith Babo Master

            Sounds like #1 is a bug in the forge tooling (not including the component name) and the deployer (not validating appropriately).  Both issues can be fixed as part of 298.  You need the component name when promoting a service.  That's just how the model works.  I don't think this has any practical implications in terms of deployment constraints.  You can bind a given service to multiple endpoints.  You can also have multiple services that share the same interface, but this is irrespective of the binding information.

             

            Is there still a problem with #2?  I couldn't tell based on your reply.

            • 3. Re: Referencing SOAP services
              Magesh Bojan Master

              From the JIRA

               

                  Jiri Pechanec added a comment  - 22/Jun/11 6:54 AM 

              Sorry I mis-read the forum - I understood it that I forgot to configure the transformer, now I see that the comment was intented as that the functionality in SY is missing. Sorry for the confusion

              • 4. Re: Referencing SOAP services
                Keith Babo Master

                Saw that, but it's not clear to me what functionality is missing ("the functionality in SY is missing").

                • 5. Re: Referencing SOAP services
                  Magesh Bojan Master

                  Injecting a @Reference to the Webservice consumer service RemoteService inside the ProxyServiceBean does not automagically convert the Java Object to SOAP request and transform it back to Java Object from SOAP response.

                   

                  The RemoteService expects a SOAP Element like

                   

                  <swi:echoTwoWay xmlns:swi="http://swi.org/">

                  <arg0>Olive</arg0>

                  </swi:echoTwoWay>

                   

                  Where as the actual data sent is "Olive" that results in com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character 'O' (code 79) in prolog; expected '<'

                  • 6. Re: Referencing SOAP services
                    Magesh Bojan Master

                    After discussing with Keith on IRC I noticed some more issues in the sample

                     

                    1. Transformers for String -> {http://swi.org/}echoOneWay and {http://swi.org/}echoOneWayResponse -> String has not been added

                    2. The WSDL is invalid. While the port is named as ErrorServicePort the atual type is name as ErrorService

                     

                    Fixing these two still does not work. I had to manually modify the switchyard config as

                    <component name="ProxyService">
                        <service name="ProxyService">
                            <interface.java interface="org.swi.ProxyService"/>
                        </service>
                        <reference name="RemoteService">
                            <!--<interface.java interface="org.swi.RemoteService"/>-->
                            <interface.wsdl interface="wsdl/ErrorService.wsdl#wsdl.porttype(ErrorService)"/>
                        </reference>
                        <implementation.bean xmlns="urn:switchyard-component-bean:config:1.0" class="org.swi.ProxyServiceBean"/>
                    </component>
                    

                     

                    This still does not work as the trnsformation that is looked up for it to convert from null -> {http://swi.org/}echoOneWay.

                     

                    A deeper look at ClientProxyBean.createExchange revealed that the contract is empty with no input, output or fault types defined for the invoker invocation.

                    • 7. Re: Referencing SOAP services
                      Magesh Bojan Master

                      Encountered this issue when testing the interface.wsdl

                       

                      Fix AS7 dependecies for WSDL api extensions

                      • 8. Re: Referencing SOAP services
                        Magesh Bojan Master

                        Further dicussion with Keith concluded that ClientProxyBean.createExchange should indeed set the Exchange Contract. Here is the JIRA for that

                        https://issues.jboss.org/browse/SWITCHYARD-318

                         

                        • 9. Re: Referencing SOAP services
                          Keith Babo Master

                          I've been playing with this app a bit and thought it might be useful to demonstrate an alternate implementation strategy.  See attached for a modified version of the application (errhandling2.zip) which uses our new @OperationType support to allow for the SOAP body to move through the proxy classes as XML instead of yanking out the element content in a transformer.  The nice thing about this approach is that you don't have to define a transformer as the converters automatically move the content between DOM Element and String.  Now if you really wanted to clip the XML out, then you could specify a transformer instead. 

                           

                          I had to make some changes to ClientProxyBean and BaseTransformerRegistry to get this to work.  The changes are available here:

                           

                          https://github.com/kcbabo/core/tree/SWITCHYARD-298

                          https://github.com/kcbabo/components/tree/SWITCHYARD-298

                           

                          I changed the fallback behavior in BaseTransformerRegistry, so some tests fail.  To build you'll need to ignore those tests or skip (-Dmaven.test.skip) them.

                           

                          Another thing I noticed is that there are three separate interfaces for this proxy app, all of which have identical signatures.  I'm guessing this was done because the @Service annotation only takes an interface name (which is used as the service name) and the app required discrete service names.  I have filed SWITCHYARD-322 to fix this.

                           

                          One other thing to note.  For proxy cases, it's probably a lot easier to use a Camel route to simply move between services.  Of course, it's perfectly valid to use the Bean component to implement this as well.   Once we have CDI bean integration setup for Camel component I would be interested in revisiting this example.