6 Replies Latest reply on Jun 6, 2013 7:23 AM by kcbabo

    Transformation Invocation

    ghostavo

      Hello again,

       

      I've bound a service with SOAP and I'm trying to get the transformation working but I can't seem to be able to get it to be invoked.

       

      Here's the WSDL:

      <?xml version="1.0" encoding="UTF-8"?>
      <wsdl:definitions name="HelloService" targetNamespace="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
        <wsdl:types>
      <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT">
        <xsd:element name="sayHello" type="tns:sayHello"/>
        <xsd:complexType name="sayHello">
          <xsd:sequence>
            <xsd:element minOccurs="0" name="string" type="xsd:string"/>
          </xsd:sequence>
        </xsd:complexType>
        <xsd:element name="sayHelloResponse" type="tns:sayHelloResponse"/>
        <xsd:complexType name="sayHelloResponse">
          <xsd:sequence>
            <xsd:element minOccurs="0" name="string" type="xsd:string"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:schema>
        </wsdl:types>
        <wsdl:message name="sayHelloResponse">
          <wsdl:part name="parameters" element="tns:sayHelloResponse">
          </wsdl:part>
        </wsdl:message>
        <wsdl:message name="sayHello">
          <wsdl:part name="parameters" element="tns:sayHello">
          </wsdl:part>
        </wsdl:message>
        <wsdl:portType name="HelloServicePortType">
          <wsdl:operation name="sayHello">
            <wsdl:input name="sayHello" message="tns:sayHello">
          </wsdl:input>
            <wsdl:output name="sayHelloResponse" message="tns:sayHelloResponse">
          </wsdl:output>
          </wsdl:operation>
        </wsdl:portType>
        <wsdl:binding name="HelloServiceSoapBinding" type="tns:HelloServicePortType">
          <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
          <wsdl:operation name="sayHello">
            <soap:operation soapAction="sayHello" style="document"/>
            <wsdl:input name="sayHello">
              <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="sayHelloResponse">
              <soap:body use="literal"/>
            </wsdl:output>
          </wsdl:operation>
        </wsdl:binding>
        <wsdl:service name="HelloService">
          <wsdl:port name="HelloServicePort" binding="tns:HelloServiceSoapBinding">
            <soap:address location="http://localhost:18001/HelloService"/>
          </wsdl:port>
        </wsdl:service>
      </wsdl:definitions>
      
      

       

      Here's the switchyard.xml

      <?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:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:soap="urn:switchyard-component-soap:config:1.0" xmlns:xform="urn:switchyard-config:transform:1.0" name="myLittleService" targetNamespace="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT">
        <sca:composite name="myLittleService" targetNamespace="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT">
          <sca:component name="HelloServiceBean">
            <bean:implementation.bean class="com.example.switchyard.myLittleService.HelloServiceBean"/>
            <sca:service name="HelloService">
              <sca:interface.java interface="com.example.switchyard.myLittleService.HelloService"/>
            </sca:service>
          </sca:component>
          <sca:service name="HelloService" promote="HelloServiceBean/HelloService">
            <sca:interface.java interface="com.example.switchyard.myLittleService.HelloService"/>
            <soap:binding.soap>
              <soap:wsdl>META-INF/HelloService.wsdl</soap:wsdl>
              <soap:wsdlPort>HelloServicePort</soap:wsdlPort>
              <soap:socketAddr>:18001</soap:socketAddr>
              <soap:contextPath>myLittleService</soap:contextPath>
            </soap:binding.soap>
          </sca:service>
        </sca:composite>
        <transforms>
          <transform.java xmlns="urn:switchyard-config:transform:1.0" from="{urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT}sayHello"
       to="java:java.lang.String"
                                     class="com.example.switchyard.myLittleService.HelloServiceTransformer"/>
          <transform.java xmlns="urn:switchyard-config:transform:1.0" from="java:java.lang.String"
                                     to="{urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT}sayHelloResponse"
                                     class="com.example.switchyard.myLittleService.HelloServiceTransformer"/>
        </transforms>
      </switchyard>
      
      

       

      Here's the HelloService interface:

      package com.example.switchyard.myLittleService;
      
      public interface HelloService {
       public String sayHello(String name);
      }
      

       

      Here's the bean implementing it:

      package com.example.switchyard.myLittleService;
      
      import org.switchyard.component.bean.Service;
      
      @Service(HelloService.class)
      public class HelloServiceBean implements HelloService {
      
       @Override
       public String sayHello(String name) {
       System.out.println("Hi, " + name + "!");
       return "Hi, " + name + "!";
       }
      }
      

       

      And here's the class with the implemented transformer methods:

      package com.example.switchyard.myLittleService;
      
      import java.io.StringReader;
      
      import javax.xml.transform.TransformerFactory;
      import javax.xml.transform.dom.DOMResult;
      import javax.xml.transform.stream.StreamSource;
      
      import org.switchyard.annotations.Transformer;
      
      import org.w3c.dom.Document;
      import org.w3c.dom.Element;
      import org.w3c.dom.NodeList;
      
      public class HelloServiceTransformer {
      
       @Transformer(from = "{urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT}sayHello")
       public String transform(Element from) {
       System.out.println("Transform to String!");
       return new String(getElementValue(from, "urn:string"));
       }
      
       private String getElementValue(Element parent, String elementName) {
       String value = null;
       NodeList nodes = parent.getElementsByTagName(elementName);
      
       if(nodes.getLength() > 0) {
       value = nodes.item(0).getChildNodes().item(0).getNodeValue();
       }
      
       return value;
       }
      
       @Transformer(to = "{urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT}sayHelloResponse")
       public Element transform(String name) {
       System.out.println("Transform to Element!");
       StringBuffer ackXml = new StringBuffer()
       .append("<hello:sayHelloResponse xmlns:hello=\"urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT\">")
       .append("<return>" + name + "</return>")
       .append("</hello:sayHelloResponse>");
      
       return toElement(ackXml.toString());
       }
      
       private Element toElement(String string) {
       DOMResult dom = new DOMResult();
      
       try {
       TransformerFactory.newInstance().newTransformer().transform(new StreamSource(new StringReader(string)), dom);
       } catch(Exception e) {
       e.printStackTrace();
       }
      
       return ((Document)dom.getNode()).getDocumentElement();
       }
      }
      

       

      When I send a soap request (via soapUI):

       

      <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT">
         <soapenv:Header/>
         <soapenv:Body>
            <urn:sayHello>
               <urn:string>Some name</urn:string>
            </urn:sayHello>
         </soapenv:Body>
      </soapenv:Envelope>
      

       

      the anwer I get is:

      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
         <SOAP-ENV:Header/>
         <SOAP-ENV:Body>
            <SOAP-ENV:Fault>
               <faultcode>SOAP-ENV:Server</faultcode>
               <faultstring>org.switchyard.exception.SwitchYardException: Error parsing DOM source.</faultstring>
            </SOAP-ENV:Fault>
         </SOAP-ENV:Body>
      </SOAP-ENV:Envelope>
      

       

      I assume the faultstring is important, but I'm not exactly sure what is going on. I'd expect that this would mean that the transformation methods are not implemented correctly but the server prints:

      13:08:42,939 INFO  [stdout] (http--127.0.0.1-8080-3) Hi, <?xml version="1.0" encoding="UTF-8"?><urn:sayHello xmlns:urn="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT">
      13:08:42,940 INFO  [stdout] (http--127.0.0.1-8080-3)          <urn:string>Some name</urn:string>
      13:08:42,975 INFO  [stdout] (http--127.0.0.1-8080-3)       </urn:sayHello>!
      13:08:42,984 ERROR [stderr] (http--127.0.0.1-8080-3) [Fatal Error] :1:1: Content is not allowed in prolog.
      

       

      and since the transformation methods are not printing, I assume they are not being invoked. Am I missing anything?

       

      attached are the source files.

        • 1. Re: Transformation Invocation
          kcbabo

          From the info you posted, it looks like the request processing is successfull.  We see the "Hi <msg> !" in the server log, so the input transformation is executing and the bean itself is being invoked.  The issue, I believe, is on the return path.  Specifically, what you are returning from the bean implementation itself:

           

          return "Hi, " + name + "!";

           

          Once this executes, the response message is populated with this content and the reply transformer is executed.  The content in question has an <?xml> declaration, so that gets put inside another XML document, which likely will blow up.  That might be the issue, but I would have expected to see the "Transform to Element!" message in your server log before the error.  So there might be something else going on here as well.

          • 2. Re: Transformation Invocation
            ghostavo

            I'm not seeing either transformer method being invoked, either before or after the bean being invoked.

             

            There is no "Transform to Element!" or "Transform to String!" either before or after the "Hi, <msg>!" so I assume they are not being called.

            • 3. Re: Transformation Invocation
              mageshbk

              With the DEBUG log turned on it says:

              DEBUG [org.switchyard.component.soap.InboundHandler] (http--127.0.0.1-8080-1) Received SOAP message targeted at Webservice operation 'sayHello' on port 'HelloServicePort'.
              DEBUG [org.switchyard.internal.ExchangeImpl] (http--127.0.0.1-8080-1) Created IN_OUT Exchange instance (29115870) for Service '{urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT}HelloService', operation 'sayHello'.  Response Handler: org.switchyard.SynchronousInOutHandler@18f2e35
              DEBUG [org.switchyard.internal.transform.BaseTransformerRegistry] (http--127.0.0.1-8080-1) Selecting transformer: from 'java:javax.xml.transform.dom.DOMSource' to 'java:org.w3c.dom.Node'. Type: org.switchyard.transform.ootb.xml.BasicDOMTransformer
              DEBUG [org.switchyard.internal.ExchangeImpl] (http--127.0.0.1-8080-1) Sending IN Message (29682871) on IN_OUT Exchange (29115870) for Service '{urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT}HelloService', operation 'sayHello'.  Exchange state: OK
              DEBUG [org.switchyard.internal.validate.BaseValidatorRegistry] (http--127.0.0.1-8080-1) No compatible validator registered: name 'java:java.lang.String'
              DEBUG [org.switchyard.internal.transform.BaseTransformerRegistry] (http--127.0.0.1-8080-1) No compatible transformer registered: from 'java:java.lang.String' to 'java:java.lang.String'
              DEBUG [org.switchyard.internal.validate.BaseValidatorRegistry] (http--127.0.0.1-8080-1) No compatible validator registered: name 'java:java.lang.String'
              DEBUG [org.switchyard.internal.transform.BaseTransformerRegistry] (http--127.0.0.1-8080-1) Selecting transformer: from 'java:javax.xml.transform.dom.DOMSource' to 'java:java.lang.String'. Type: org.switchyard.transform.ootb.xml.BasicDOMTransformer
              DEBUG [org.switchyard.component.bean.ServiceProxyHandler] (http--127.0.0.1-8080-1) CDI Bean Service ExchangeHandler proxy class received IN_OUT Exchange (29115870) for Bean Service '{urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT}HelloService'.  Invoking bean method 'sayHello'.
              INFO  [stdout] (http--127.0.0.1-8080-1) Hi, <?xml version="1.0" encoding="UTF-8"?><urn:sayHello xmlns:urn="urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT">
              INFO  [stdout] (http--127.0.0.1-8080-1)          <!--Optional:-->
              INFO  [stdout] (http--127.0.0.1-8080-1)          <urn:string>Name</urn:string>
              INFO  [stdout] (http--127.0.0.1-8080-1)       </urn:sayHello>!
              DEBUG [org.switchyard.internal.ExchangeImpl] (http--127.0.0.1-8080-1) Sending OUT Message (24499159) on IN_OUT Exchange (29115870) for Service '{urn:com.example.switchyard:myLittleService:0.0.1-SNAPSHOT}HelloService', operation 'sayHello'.  Exchange state: OK
              DEBUG [org.switchyard.internal.validate.BaseValidatorRegistry] (http--127.0.0.1-8080-1) No compatible validator registered: name 'java:java.lang.String'
              DEBUG [org.switchyard.internal.transform.BaseTransformerRegistry] (http--127.0.0.1-8080-1) No compatible transformer registered: from 'java:java.lang.String' to 'java:java.lang.String'
              DEBUG [org.switchyard.internal.validate.BaseValidatorRegistry] (http--127.0.0.1-8080-1) No compatible validator registered: name 'java:java.lang.String'
              DEBUG [org.switchyard.internal.transform.BaseTransformerRegistry] (http--127.0.0.1-8080-1) Selecting transformer: from 'java:java.lang.String' to 'java:org.w3c.dom.Node'. Type: org.switchyard.transform.ootb.xml.BasicDOMTransformer
              ERROR [stderr] (http--127.0.0.1-8080-1) [Fatal Error] :1:1: Content is not allowed in prolog.
              

               

              I remeber the puzzled days that I went through when testing OS application. Now thie thread will sort that out.

              1 of 1 people found this helpful
              • 4. Re: Transformation Invocation
                kcbabo

                The composite-level service is using a Java interface, the same one used by the bean service.  If the interface is the same, then no tranformation occurs (rightly so).  You want this instead:

                 

                <sca:service name="HelloService" promote="HelloServiceBean/HelloService">
                      <sca:interface.wsdl interface="META-INF/HelloService.wsdl#wsdl.porttype(HelloServicePortType)"/>
                   <soap:binding.soap>
                     <soap:wsdl>META-INF/HelloService.wsdl</soap:wsdl>
                     <soap:wsdlPort>HelloServicePort</soap:wsdlPort>
                     <soap:socketAddr>:18001</soap:socketAddr>
                     <soap:contextPath>myLittleService</soap:contextPath>
                   </soap:binding.soap>
                </sca:service>
                
                • 5. Re: Transformation Invocation
                  nmoghadam

                  I was having the same problem and I am not using any transformer.

                   

                  As you suggested I changed my service to :

                   

                  <sca:service name="ExampleServicePortType" promote="ExampleServiceImpl/ExampleService">

                        <sca:interface.wsdl interface="wsdl/ExampleService.wsdl#wsdl.porttype(ExampleServicePortType)"/>

                        <soap:binding.soap>

                          <soap:contextMapper/>

                          <soap:wsdl>wsdl/ExampleService.wsdl</soap:wsdl>

                          <soap:wsdlPort>ExampleServicePort</soap:wsdlPort>

                          <soap:contextPath>switchyard-example</soap:contextPath>

                        </soap:binding.soap>

                      </sca:service>

                   

                  I get the following error:

                   

                  Caused by: org.switchyard.exception.SwitchYardException: Transformations not applied.  Required payload type of 'java:java.lang.String'.  Actual payload type is '{http://www.example.org/ExampleService/}sayHello'.  You must define and register a Transformer to transform between these types.

                            at org.switchyard.component.soap.InboundHandler.invoke(InboundHandler.java:229) [switchyard-component-soap-0.8.0.Final.jar:0.8.0.Final]

                            at org.switchyard.component.soap.endpoint.BaseWebService.invoke(BaseWebService.java:115) [switchyard-component-soap-0.8.0.Final.jar:0.8.0.Final]

                            at org.switchyard.component.soap.endpoint.BaseWebService.invoke(BaseWebService.java:45) [switchyard-component-soap-0.8.0.Final.jar:0.8.0.Final]

                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_31]

                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_31]

                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_31]

                            at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_31]

                            at org.jboss.ws.common.invocation.AbstractInvocationHandlerJSE.invoke(AbstractInvocationHandlerJSE.java:111)

                            at org.jboss.wsf.stack.cxf.JBossWSInvoker._invokeInternal(JBossWSInvoker.java:181) [jbossws-cxf-server-4.0.2.GA.jar:4.0.2.GA]

                  • 6. Re: Transformation Invocation
                    kcbabo

                    What does the Java interface for ExampleService look like (the one implemented by ExampleServiceImpl)?