Transformation Invocation
ghostavo Sep 4, 2012 8:25 AMHello 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.
-
myLittleService.zip 26.1 KB