Raw Style webservices [Design question]
viniciuscarvalho Oct 3, 2007 4:28 PMHello there! I'm developing a Topdown webservice, and defining my own WSDL, and using @WebserviceProvider annotations.
The service is running, I can access it using webservice explorer or SOAPUI. When I generate the client using JBoss WS, I'm getting some errors on the response. I know it's something related to my WSDL, and SOAP response. So I was hopping someone could assist me:
WSDL
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sys="http://www.acme.com/schemas/sys" targetNamespace="http://www.acme.com/sys/definitions" xmlns:tns="http://www.acme.com/sys/definitions"> <wsdl:types> <xsd:schema> <xsd:import namespace="http://www.acme.com/schemas/sys" schemaLocation="Command.xsd" id="sys"/> </xsd:schema> </wsdl:types> <wsdl:message name="CommandRequest"> <wsdl:part name="parameters" element="sys:anyCommand"></wsdl:part> </wsdl:message> <wsdl:message name="CommandResponse"> <wsdl:part name="return" element="sys:CommandResponse"></wsdl:part> </wsdl:message> <wsdl:portType name="CommandProcessorPortType"> <wsdl:operation name="process"> <wsdl:input message="tns:CommandRequest" name="CommandRequestInput"></wsdl:input> <wsdl:output message="tns:CommandResponse" name="CommandResponseOutput"></wsdl:output> </wsdl:operation> </wsdl:portType> <wsdl:binding name="CommandProcessorBinding" type="tns:CommandProcessorPortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="process"> <soap:operation soapAction="http://www.acme.com/sys/CommandRequest"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="CommandProcessorService"> <wsdl:port name="CommandProcessorPort" binding="tns:CommandProcessorBinding"> <soap:address location="http://localhost:8080/CommandProcessorService"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
Command.xsd
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.acme.com/schemas/sys" xmlns:sys="http://www.acme.com/schemas/sys" elementFormDefault="qualified"> <xsd:element name="anyCommand"> <xsd:complexType> <xsd:sequence> <xsd:any minOccurs="1"></xsd:any> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="CommandResponse"> <xsd:complexType> <xsd:sequence> <xsd:element name="return" type="sys:ResponseCommandType"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:complexType name="ResponseCommandType"> <xsd:sequence> <xsd:element name="id" type="xsd:long"></xsd:element> <xsd:element name="message" type="xsd:string"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:schema>
My Provider
@Local @Stateless @WebServiceProvider(wsdlLocation="META-INF/wsdl/CommandProcessor.wsdl", targetNamespace="http://www.acme.com/sys/definitions", serviceName="CommandProcessorService", portName="CommandProcessorPort") @ServiceMode(value=Service.Mode.PAYLOAD) public class CommandProcessor implements Provider<Source> { Source returnMessage; public Source invoke(Source messge) { DOMSource domSource = null; try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); OutputStream out = new ByteArrayOutputStream(); StreamResult streamResult = new StreamResult(); streamResult.setOutputStream(out); transformer.transform(messge, streamResult); String xmlReq = streamResult.getOutputStream().toString(); System.out.println(xmlReq); domSource = new DOMSource(createResponseContent()); transformer.transform(domSource, streamResult); xmlReq = streamResult.getOutputStream().toString(); System.out.println(xmlReq); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return domSource; } private Document createResponseContent() throws Exception{ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.newDocument(); Element responseCommand = doc.createElementNS("http://www.acme.com/sys/definitions", "sys:CommandResponse"); Element ret = doc.createElement("return"); Element id = doc.createElement("id"); id.appendChild(doc.createTextNode("1")); Element message = doc.createElement("message"); message.appendChild(doc.createTextNode("comando recebido")); ret.appendChild(id); ret.appendChild(message); responseCommand.appendChild(ret); doc.appendChild(responseCommand); return doc; } }
Well, first, when I run ws-provide it throws a lot of warnings on the console, but it seems that all artifacts are created (Port,Service,Bindings,ObjectFactory).
Ok, running using soap ui:
Request: <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:sys="http://www.acme.com/schemas/sys"> <soapenv:Header/> <soapenv:Body> <csm:anyCommand> <asteriskCommand> <voip>true</voip> </asteriskCommand> </csm:anyCommand> </soapenv:Body> </soapenv:Envelope> Response: <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> <env:Header/> <env:Body> <sys:CommandResponse xmlns:sys="null"> <return> <id>1</id> <message>comando recebido</message> </return> </csm:CommandResponse> </env:Body> </env:Envelope>
Now, the odd thing, is that the xmlns:sys is null, when I print it on the serverside it displays that the xmlns:sys is pointing to the namespace.
So I run this test with the generated client proxy, and I get an error:
Caused by: org.jboss.ws.WSException: Cannot find child element: {http://www.acme.com/schemas/sys}CommandResponse
I really don't know if this is caused because the xmlns is being returned null, and if so, why? Or did I messed the whole doc/literal wrapped/bare style? I was thinking that I was using bare style :)
Any help would be great :)
Regards