Hi, I had some issues with soap messages not being serialized properly, header/body handling (binding) etc. I'm using the wsdl11-wrapping and I don't know if it has something to do with this. Anyways, at least it looks like the binding stuff is being discarded at org.apache.servicemix.http.HttpEndpoint:228, but I don't know if the part handling (soap binding) was occurring before that; although, the end-results weren't suggesting so. (All parts were serialized to the soap body, or something.) So I hacked up this little patch which does the part handling. Diffs attached. Best effort -kind of stuff, works for me. Just if anyone else is interested.. Though, I didn't quite get what HttpEndpoint#overrideDefinition was trying to do so that hack may be a little conflicting.. (see the httpendpoint-patch.)
I'd also like to know if this would somehow work without the patch as patches are a bit annoying. :) (There also appears to be some major stuff coming in the soap2-module, but it seemed a little incomplete so I didn't take a closer look.) Btw., I guess the soap-headers of the reply message are being forwarded correctly? -janne
Index: servicemix-soap/src/main/java/org/apache/servicemix/soap/marshalers/JBIMarshaler.java =================================================================== --- servicemix-soap/src/main/java/org/apache/servicemix/soap/marshalers/JBIMarshaler.java (revision 523275) +++ servicemix-soap/src/main/java/org/apache/servicemix/soap/marshalers/JBIMarshaler.java (working copy) @@ -17,6 +17,8 @@ package org.apache.servicemix.soap.marshalers; import java.net.URI; +import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -24,11 +26,26 @@ import javax.activation.DataHandler; import javax.jbi.messaging.Fault; import javax.jbi.messaging.NormalizedMessage; +import javax.wsdl.Message; +import javax.wsdl.Part; +import javax.wsdl.WSDLElement; +import javax.wsdl.extensions.soap.SOAPHeader; import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; import org.apache.servicemix.JbiConstants; +import org.apache.servicemix.jbi.util.DOMUtil; import org.apache.servicemix.soap.SoapFault; +import org.w3c.dom.Document; import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * @@ -73,7 +90,8 @@ } } - public void fromNMS(SoapMessage soapMessage, NormalizedMessage normalizedMessage) { + public void fromNMS(SoapMessage soapMessage, NormalizedMessage normalizedMessage, + Message msg, WSDLElement bindingElem) { if (normalizedMessage.getProperty(JbiConstants.SOAP_HEADERS) != null) { Map headers = (Map) normalizedMessage.getProperty(JbiConstants.SOAP_HEADERS); for (Iterator it = headers.entrySet().iterator(); it.hasNext();) { @@ -95,6 +113,55 @@ URI role = (URI) normalizedMessage.getProperty(SOAP_FAULT_ROLE); SoapFault fault = new SoapFault(code, subcode, reason, node, role, normalizedMessage.getContent()); soapMessage.setFault(fault); + } else if (bindingElem != null) { + boolean success = false; + DocumentBuilder docBuilder = null; + try { + // QName#hashCode() is implemented suitably + Collection<QName> headerElems = new HashSet<QName>(); + for (Object ext : bindingElem.getExtensibilityElements()) { + if (ext instanceof SOAPHeader) { + Part p = msg.getPart(((SOAPHeader) ext).getPart()); + if (p != null && p.getElementName() != null) + headerElems.add(p.getElementName()); + } + } + docBuilder = DOMUtil.getBuilder(); + Transformer tr = TransformerFactory.newInstance().newTransformer(); + Document jbiContent = docBuilder.newDocument(); + Document soapBody = docBuilder.newDocument(); + tr.transform(normalizedMessage.getContent(), new DOMResult(jbiContent)); + NodeList wrapperMsg = jbiContent.getElementsByTagNameNS( + "http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper", "message"); + if (wrapperMsg.getLength() == 1) { + Node part = wrapperMsg.item(0).getFirstChild(); + while (part != null && "part".equals(part.getLocalName()) + && part.getChildNodes().getLength() == 1) { + Node partContent = part.getFirstChild(); + QName elemName = new QName(partContent.getNamespaceURI(), + partContent.getLocalName()); + if (headerElems.contains(elemName)) { + DocumentFragment headerFrag = + docBuilder.newDocument().createDocumentFragment(); + tr.transform(new DOMSource(partContent), + new DOMResult(headerFrag)); + soapMessage.addHeader(elemName, headerFrag); + } else { // assume it's a valid part for body + soapBody.appendChild(soapBody.adoptNode(partContent)); + } + part = part.getNextSibling(); + } + } + soapMessage.setSource(new DOMSource(soapBody)); + success = true; + } catch (ParserConfigurationException e) { + } catch (TransformerException e) { + } finally { + if (!success) + soapMessage.setSource(normalizedMessage.getContent()); + if (docBuilder != null) + DOMUtil.releaseBuilder(docBuilder); + } } else { soapMessage.setSource(normalizedMessage.getContent()); }
Index: servicemix-http/src/main/java/org/apache/servicemix/http/processors/ProviderProcessor.java =================================================================== --- servicemix-http/src/main/java/org/apache/servicemix/http/processors/ProviderProcessor.java (revision 523281) +++ servicemix-http/src/main/java/org/apache/servicemix/http/processors/ProviderProcessor.java (working copy) @@ -33,6 +33,11 @@ import javax.jbi.messaging.MessageExchange; import javax.jbi.messaging.NormalizedMessage; import javax.servlet.http.HttpServletRequest; +import javax.wsdl.BindingOperation; +import javax.wsdl.Message; +import javax.wsdl.Port; +import javax.wsdl.Service; +import javax.wsdl.WSDLElement; import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; import org.apache.commons.httpclient.Header; @@ -126,7 +131,20 @@ PostMethod method = new PostMethod(getRelUri(locationURI)); SoapMessage soapMessage = new SoapMessage(); - soapHelper.getJBIMarshaler().fromNMS(soapMessage, nm); + Service svcDesc = endpoint.getDefinition().getService(exchange.getService()); + Message inputMsg = null; + WSDLElement inputBinding = null; + if (svcDesc != null) { + Port port = svcDesc.getPort(exchange.getEndpoint().getEndpointName()); + if (port != null) { + BindingOperation op = port.getBinding().getBindingOperation( + exchange.getOperation().getLocalPart(), null, null); + if (op != null) + inputMsg = op.getOperation().getInput().getMessage(); + inputBinding = op.getBindingInput(); + } + } + soapHelper.getJBIMarshaler().fromNMS(soapMessage, nm, inputMsg, inputBinding); Context context = soapHelper.createContext(soapMessage); soapHelper.onSend(context); SoapWriter writer = soapHelper.getSoapMarshaler().createWriter(soapMessage);
Index: servicemix-http/src/main/java/org/apache/servicemix/http/HttpEndpoint.java =================================================================== --- servicemix-http/src/main/java/org/apache/servicemix/http/HttpEndpoint.java (revision 523281) +++ servicemix-http/src/main/java/org/apache/servicemix/http/HttpEndpoint.java (working copy) @@ -209,6 +209,8 @@ } protected void overrideDefinition(Definition def) throws Exception { + this.definition = def; + if (true) return; PortType portType = getTargetPortType(def); if (portType != null) { QName[] names = (QName[]) def.getPortTypes().keySet().toArray(new QName[0]);