[JBoss JIRA] Created: (JBWS-2026) jax-ws and saaj attachments
by Mirko Ravagnan (JIRA)
jax-ws and saaj attachments
---------------------------
Key: JBWS-2026
URL: http://jira.jboss.com/jira/browse/JBWS-2026
Project: JBoss Web Services
Issue Type: Patch
Security Level: Public (Everyone can see)
Components: jbossws-native
Affects Versions: jbossws-native-2.0.3
Environment: jboss as 4.2.2 + jbossws 2.0.3
Reporter: Mirko Ravagnan
Dear jbossws developers.
I'm having an issue dealing with a webservice provided from a third party.
The problem I encountered is as follows:
1: the service returns as output some data in the response
and an optional attachment sent with saaj.
2: the attachment comes along and is stored
in a temporary directory by jboss.
3: jbossws fails to identify the attachment and does not bind it
to the response of the service.
4: jboss throws the unused attachment away.
I've tracked the issue on the class CommonSoapBinding
in class org.jboss.ws.core.
This issue is related to the inability of the mentioned class
to deal with attachment by id, but only by part name.
The fact is the service provider sends attachment
without sending the content id complete with the part name
let me explain:
The http headers sent with the response message do not contain
a header [Content-Id="MyAttachment=<blablabla...>"]
but [Content-Id="<blablabla...>"]
Hence, method "getAttachmentFromMessage" fails to find the attachment.
As a solution, I made some modification to that method in order
it to deal with the requirement to handle attachments by id.
I also modified the behaviour of the method not to throw an exception
when it does not find the attachment it expects to find, because otherwise
you might loose the chance to get fault text messages embedded in the service
response, as this exception breaks the process of rebuilding the java
representation of the soap message.
This is reflected also in method "unbindResponseMessage".
I'm attaching the modified java source
so that you can have evidence of the changes
(which have a comment "\\ m." on the right side of the line)
Many thanks for your time
Here is the modified source.
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.ws.core;
// $Id: CommonSOAPBinding.java 5322 2007-12-14 17:58:07Z richard.opalka(a)jboss.com $
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSTypeDefinition;
import org.jboss.logging.Logger;
import org.jboss.ws.Constants;
import org.jboss.ws.WSException;
import org.jboss.ws.core.binding.BindingException;
import org.jboss.ws.core.jaxrpc.ParameterWrapping;
import org.jboss.ws.core.jaxws.handler.MessageContextJAXWS;
import org.jboss.ws.core.soap.MessageContextAssociation;
import org.jboss.ws.core.soap.MessageFactoryImpl;
import org.jboss.ws.core.soap.NameImpl;
import org.jboss.ws.core.soap.SOAPBodyElementDoc;
import org.jboss.ws.core.soap.SOAPBodyElementRpc;
import org.jboss.ws.core.soap.SOAPBodyImpl;
import org.jboss.ws.core.soap.SOAPContentElement;
import org.jboss.ws.core.soap.SOAPElementImpl;
import org.jboss.ws.core.soap.SOAPFactoryImpl;
import org.jboss.ws.core.soap.SOAPFaultImpl;
import org.jboss.ws.core.soap.SOAPHeaderElementImpl;
import org.jboss.ws.core.soap.SOAPMessageImpl;
import org.jboss.ws.core.soap.Style;
import org.jboss.ws.core.soap.UnboundHeader;
import org.jboss.ws.core.soap.Use;
import org.jboss.ws.core.soap.attachment.AttachmentPartImpl;
import org.jboss.ws.core.soap.attachment.CIDGenerator;
import org.jboss.ws.core.utils.MimeUtils;
import org.jboss.ws.extensions.wsrm.RMConstant;
import org.jboss.ws.extensions.wsrm.common.RMHelper;
import org.jboss.ws.extensions.xop.XOPContext;
import org.jboss.ws.metadata.umdm.OperationMetaData;
import org.jboss.ws.metadata.umdm.ParameterMetaData;
import org.jboss.ws.metadata.umdm.TypesMetaData;
import org.jboss.wsf.common.DOMUtils;
import org.jboss.wsf.common.JavaUtils;
import org.jboss.xb.binding.NamespaceRegistry;
import org.w3c.dom.Element;
/**
* The SOAPBinding interface is an abstraction for the SOAP binding.
*
* @author Thomas.Diesler(a)jboss.com
* @since 04-Jul-2006
*/
public abstract class CommonSOAPBinding implements CommonBinding
{
// provide logging
protected Logger log = Logger.getLogger(getClass());
private boolean mtomEnabled;
protected HeaderSource headerSource;
/** A constant representing the identity of the SOAP 1.1 over HTTP binding. */
public static final String SOAP11HTTP_BINDING = "http://schemas.xmlsoap.org/wsdl/soap/http";
/** A constant representing the identity of the SOAP 1.2 over HTTP binding. */
public static final String SOAP12HTTP_BINDING = "http://www.w3.org/2003/05/soap/bindings/HTTP/";
/** A constant representing the identity of the SOAP 1.1 over HTTP binding with MTOM enabled by default. */
public static final String SOAP11HTTP_MTOM_BINDING = "http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true";
/** A constant representing the identity of the SOAP 1.2 over HTTP binding with MTOM enabled by default. */
public static final String SOAP12HTTP_MTOM_BINDING = "http://www.w3.org/2003/05/soap/bindings/HTTP/?mtom=true";
/** The SOAP encoded Array name */
private static final Name SOAP_ARRAY_NAME = new NameImpl("Array", Constants.PREFIX_SOAP11_ENC, Constants.URI_SOAP11_ENC);
public CommonSOAPBinding()
{
}
public MessageFactory getMessageFactory()
{
return new MessageFactoryImpl();
}
public SOAPFactory getSOAPFactory()
{
return new SOAPFactoryImpl();
}
public boolean isMTOMEnabled()
{
return this.mtomEnabled;
}
public void setMTOMEnabled(boolean flag)
{
this.mtomEnabled = flag;
}
/** Create the message */
protected abstract MessageAbstraction createMessage(OperationMetaData opMetaData) throws SOAPException;
/** On the client side, generate the payload from IN parameters. */
public MessageAbstraction bindRequestMessage(OperationMetaData opMetaData, EndpointInvocation epInv, Map<QName, UnboundHeader> unboundHeaders)
throws BindingException
{
if (log.isDebugEnabled())
log.debug("bindRequestMessage: " + opMetaData.getQName());
try
{
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
if (msgContext == null)
throw new WSException("MessageContext not available");
// Disable MTOM for rpc/encoded
if (opMetaData.isRPCEncoded())
XOPContext.setMTOMEnabled(false);
else XOPContext.setMTOMEnabled(isMTOMEnabled());
// Associate current message with message context
SOAPMessageImpl reqMessage = (SOAPMessageImpl)createMessage(opMetaData);
msgContext.setSOAPMessage(reqMessage);
SOAPEnvelope soapEnvelope = reqMessage.getSOAPPart().getEnvelope();
SOAPBody soapBody = soapEnvelope.getBody();
SOAPHeader soapHeader = soapEnvelope.getHeader();
// Get the namespace registry
NamespaceRegistry namespaceRegistry = msgContext.getNamespaceRegistry();
Style style = opMetaData.getStyle();
SOAPElement soapBodyElement = soapBody;
if (style == Style.RPC)
{
boolean serialize = true;
if (opMetaData.getEndpointMetaData().getConfig().getRMMetaData() != null)
{
// RM hack to JAX-RPC serialization
if (RMHelper.isRMOperation(opMetaData.getQName()))
{
serialize = false;
}
}
if (serialize)
{
QName opQName = opMetaData.getQName();
Name opName = new NameImpl(namespaceRegistry.registerQName(opQName));
if (log.isDebugEnabled())
log.debug("Create RPC body element: " + opName);
soapBodyElement = new SOAPBodyElementRpc(opName);
soapBodyElement = (SOAPBodyElement)soapBody.addChildElement(soapBodyElement);
// Add soap encodingStyle
if (opMetaData.getUse() == Use.ENCODED)
{
String envURI = soapEnvelope.getNamespaceURI();
String envPrefix = soapEnvelope.getPrefix();
soapBodyElement.setAttributeNS(envURI, envPrefix + ":encodingStyle", Constants.URI_SOAP11_ENC);
}
}
}
for (ParameterMetaData paramMetaData : opMetaData.getInputParameters())
{
QName xmlName = paramMetaData.getXmlName();
Object value = epInv.getRequestParamValue(xmlName);
if (paramMetaData.isSwA())
{
// NOTE: swa:ref is handled by the AttachmentMarshaller callback
CIDGenerator cidGenerator = reqMessage.getCidGenerator();
AttachmentPart part = createAttachmentPart(paramMetaData, value, cidGenerator);
reqMessage.addAttachmentPart(part);
// Add the attachment to the standard property
if (value instanceof DataHandler && msgContext instanceof MessageContextJAXWS)
{
DataHandler dataHandler = (DataHandler)value;
Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
attachments.put(dataHandler.getContentType(), dataHandler);
}
}
else
{
SOAPElement soapElement = paramMetaData.isInHeader() ? (SOAPElement)soapHeader : soapBodyElement;
addParameterToMessage(paramMetaData, value, soapElement);
}
}
// Add unbound headers
if (unboundHeaders != null)
{
Iterator it = unboundHeaders.values().iterator();
while (it.hasNext())
{
UnboundHeader unboundHeader = (UnboundHeader)it.next();
if (unboundHeader.getMode() != ParameterMode.OUT)
{
QName xmlName = unboundHeader.getXmlName();
Object value = unboundHeader.getHeaderValue();
xmlName = namespaceRegistry.registerQName(xmlName);
Name soapName = new NameImpl(xmlName.getLocalPart(), xmlName.getPrefix(), xmlName.getNamespaceURI());
log.debug("Add unboundHeader element: " + soapName);
SOAPContentElement contentElement = new SOAPHeaderElementImpl(soapName);
contentElement.setParamMetaData(unboundHeader.toParameterMetaData(opMetaData));
if (soapHeader == null)
soapHeader = soapEnvelope.addHeader();
soapHeader.addChildElement(contentElement);
contentElement.setObjectValue(value);
}
}
}
// Set the SOAPAction
setSOAPActionHeader(opMetaData, reqMessage);
return reqMessage;
}
catch (Exception e)
{
handleException(e);
return null;
}
}
/** Override to set the SOAPAction header */
public abstract void setSOAPActionHeader(OperationMetaData opMetaData, SOAPMessage reqMessage);
/** On the server side, extract the IN parameters from the payload and populate an Invocation object */
public EndpointInvocation unbindRequestMessage(OperationMetaData opMetaData, MessageAbstraction payload) throws BindingException
{
if (log.isDebugEnabled())
log.debug("unbindRequestMessage: " + opMetaData.getQName());
try
{
// Read the SOAPEnvelope from the reqMessage
SOAPMessageImpl reqMessage = (SOAPMessageImpl)payload;
SOAPEnvelope soapEnvelope = reqMessage.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnvelope.getHeader();
SOAPBody soapBody = soapEnvelope.getBody();
// Verify the SOAP version
verifySOAPVersion(opMetaData, soapEnvelope);
// Construct the endpoint invocation object
EndpointInvocation epInv = new EndpointInvocation(opMetaData);
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
if (msgContext == null)
throw new WSException("MessageContext not available");
// Disable MTOM for rpc/encoded
if (opMetaData.isRPCEncoded())
msgContext.put(StubExt.PROPERTY_MTOM_ENABLED, Boolean.FALSE);
// Get the namespace registry
NamespaceRegistry namespaceRegistry = msgContext.getNamespaceRegistry();
if (opMetaData.isMessageEndpoint() == false)
{
Style style = opMetaData.getStyle();
SOAPElement payloadParent = soapBody;
if (style == Style.RPC)
{
payloadParent = null;
Iterator it = soapBody.getChildElements();
while (payloadParent == null && it.hasNext())
{
Object childNode = it.next();
if (childNode instanceof SOAPElement)
{
payloadParent = (SOAPElement)childNode;
}
}
if (RMHelper.isRMOperation(opMetaData.getQName()) == false) // RM hack
{
if (payloadParent == null)
throw new SOAPException("Cannot find RPC element in");
QName elName = payloadParent.getElementQName();
elName = namespaceRegistry.registerQName(elName);
}
}
int numParameters = 0;
for (ParameterMetaData paramMetaData : opMetaData.getParameters())
{
QName xmlName = paramMetaData.getXmlName();
if (paramMetaData.getMode() == ParameterMode.OUT)
{
epInv.setRequestParamValue(xmlName, null);
}
else
{
if (paramMetaData.isSwA())
{
AttachmentPart part = getAttachmentFromMessage(paramMetaData, reqMessage);
epInv.setRequestParamValue(xmlName, part);
// Add the attachment to the standard property
if (part.getDataHandler() != null && msgContext instanceof MessageContextJAXWS)
{
DataHandler dataHandler = part.getDataHandler();
Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
attachments.put(part.getContentId(), dataHandler);
}
}
else
{
boolean isHeader = paramMetaData.isInHeader();
SOAPElement element = isHeader ? soapHeader : payloadParent;
if (!isHeader)
numParameters++;
SOAPContentElement value = getParameterFromMessage(paramMetaData, element, false);
epInv.setRequestParamValue(xmlName, value);
}
}
}
if (RMHelper.isRMOperation(opMetaData.getQName()) == false)
{
// Verify the numer of parameters matches the actual message payload
int numChildElements = 0;
Iterator itElements = payloadParent.getChildElements();
while (itElements.hasNext())
{
Node node = (Node)itElements.next();
if (node instanceof SOAPElement)
numChildElements++;
}
if (numChildElements != numParameters)
throw new WSException("Invalid number of payload elements: " + numChildElements);
}
}
// Generic message endpoint
else
{
for (ParameterMetaData paramMetaData : opMetaData.getParameters())
{
QName xmlName = paramMetaData.getXmlName();
Object value = soapBody.getChildElements().next();
epInv.setRequestParamValue(xmlName, value);
}
}
return epInv;
}
catch (Exception e)
{
handleException(e);
return null;
}
}
/** On the server side, generate the payload from OUT parameters. */
public MessageAbstraction bindResponseMessage(OperationMetaData opMetaData, EndpointInvocation epInv) throws BindingException
{
if (log.isDebugEnabled())
log.debug("bindResponseMessage: " + opMetaData.getQName());
try
{
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
if (msgContext == null)
throw new WSException("MessageContext not available");
// Disable MTOM for rpc/encoded
if (opMetaData.isRPCEncoded())
XOPContext.setMTOMEnabled(false);
else XOPContext.setMTOMEnabled(isMTOMEnabled());
// Associate current message with message context
SOAPMessageImpl resMessage = (SOAPMessageImpl)createMessage(opMetaData);
msgContext.setSOAPMessage(resMessage);
// R2714 For one-way operations, an INSTANCE MUST NOT return a HTTP response that contains a SOAP envelope.
// Specifically, the HTTP response entity-body must be empty.
boolean isWsrmMessage = msgContext.get(RMConstant.RESPONSE_CONTEXT) != null;
if (opMetaData.isOneWay() && (false == isWsrmMessage))
{
resMessage.getSOAPPart().setContent(null);
return resMessage;
}
SOAPEnvelope soapEnvelope = resMessage.getSOAPPart().getEnvelope();
SOAPHeader soapHeader = soapEnvelope.getHeader();
SOAPBody soapBody = soapEnvelope.getBody();
// Get the namespace registry
NamespaceRegistry namespaceRegistry = msgContext.getNamespaceRegistry();
Style style = opMetaData.getStyle();
SOAPElement soapBodyElement = soapBody;
if (style == Style.RPC)
{
QName opQName = opMetaData.getResponseName();
if (false == RMHelper.isRMOperation(opQName)) // RM hack
{
Name opName = new NameImpl(namespaceRegistry.registerQName(opQName));
soapBodyElement = new SOAPBodyElementRpc(opName);
soapBodyElement = (SOAPBodyElement)soapBody.addChildElement(soapBodyElement);
// Add soap encodingStyle
if (opMetaData.getUse() == Use.ENCODED)
{
String envURI = soapEnvelope.getNamespaceURI();
String envPrefix = soapEnvelope.getPrefix();
soapBodyElement.setAttributeNS(envURI, envPrefix + ":encodingStyle", Constants.URI_SOAP11_ENC);
}
}
}
// Add the return to the message
ParameterMetaData retMetaData = opMetaData.getReturnParameter();
if (retMetaData != null)
{
Object value = epInv.getReturnValue();
// TODO calls to ParameterWrapping should be elsewhere
if (opMetaData.isDocumentWrapped())
value = ParameterWrapping.wrapResponseParameters(retMetaData, value, epInv.getOutParameters());
if (retMetaData.isSwA())
{
CIDGenerator cidGenerator = resMessage.getCidGenerator();
AttachmentPart part = createAttachmentPart(retMetaData, value, cidGenerator);
resMessage.addAttachmentPart(part);
epInv.setReturnValue(part);
// Add the attachment to the standard property
if (part.getDataHandler() != null && msgContext instanceof MessageContextJAXWS)
{
DataHandler dataHandler = part.getDataHandler();
Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
attachments.put(part.getContentId(), dataHandler);
}
}
else
{
SOAPContentElement soapElement = addParameterToMessage(retMetaData, value, soapBodyElement);
epInv.setReturnValue(soapElement);
soapElement.setObjectValue(value);
}
}
// Add the out parameters to the message
for (ParameterMetaData paramMetaData : opMetaData.getOutputParameters())
{
QName xmlName = paramMetaData.getXmlName();
Object value = epInv.getResponseParamValue(xmlName);
if (paramMetaData.isSwA())
{
CIDGenerator cidGenerator = resMessage.getCidGenerator();
AttachmentPart part = createAttachmentPart(paramMetaData, value, cidGenerator);
resMessage.addAttachmentPart(part);
// Add the attachment to the standard property
if (value instanceof DataHandler && msgContext instanceof MessageContextJAXWS)
{
DataHandler dataHandler = (DataHandler)value;
Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
attachments.put(dataHandler.getContentType(), dataHandler);
}
}
else
{
if (paramMetaData.isInHeader())
{
addParameterToMessage(paramMetaData, value, soapHeader);
}
else
{
addParameterToMessage(paramMetaData, value, soapBodyElement);
}
}
}
return resMessage;
}
catch (Exception e)
{
handleException(e);
return null;
}
}
/** On the client side, extract the OUT parameters from the payload and return them to the client. */
public void unbindResponseMessage(OperationMetaData opMetaData, MessageAbstraction payload, EndpointInvocation epInv, Map<QName, UnboundHeader> unboundHeaders)
throws BindingException
{
if (log.isDebugEnabled())
log.debug("unbindResponseMessage: " + opMetaData.getQName());
try
{
// R2714 For one-way operations, an INSTANCE MUST NOT return a HTTP response that contains a SOAP envelope.
// Specifically, the HTTP response entity-body must be empty.
if (opMetaData.isOneWay() == true)
{
return;
}
// WS-Addressing might redirect the response, which results in an empty envelope
SOAPMessageImpl resMessage = (SOAPMessageImpl)payload;
SOAPEnvelope soapEnvelope = resMessage.getSOAPPart().getEnvelope();
if (soapEnvelope == null)
{
return;
}
// Verify the SOAP version
verifySOAPVersion(opMetaData, soapEnvelope);
// Get the SOAP message context that is associated with the current thread
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
if (msgContext == null)
throw new WSException("MessageContext not available");
// Disable MTOM for rpc/encoded
if (opMetaData.isRPCEncoded())
msgContext.put(StubExt.PROPERTY_MTOM_ENABLED, Boolean.FALSE);
SOAPHeader soapHeader = soapEnvelope.getHeader();
SOAPBodyImpl soapBody = (SOAPBodyImpl)soapEnvelope.getBody();
SOAPBodyElement soapBodyElement = soapBody.getBodyElement();
// Translate the SOAPFault to an exception and throw it
if (soapBodyElement instanceof SOAPFaultImpl)
throwFaultException((SOAPFaultImpl)soapBodyElement);
// Extract unbound OUT headers
if (unboundHeaders != null && soapHeader != null)
{
Map<QName, UnboundHeader> outHeaders = new HashMap<QName, UnboundHeader>();
Iterator itHeaderElements = soapHeader.getChildElements();
while (itHeaderElements.hasNext())
{
SOAPContentElement soapHeaderElement = (SOAPHeaderElementImpl)itHeaderElements.next();
Name elName = soapHeaderElement.getElementName();
QName xmlName = new QName(elName.getURI(), elName.getLocalName());
UnboundHeader unboundHeader = (UnboundHeader)unboundHeaders.get(xmlName);
if (unboundHeader != null)
{
soapHeaderElement.setParamMetaData(unboundHeader.toParameterMetaData(opMetaData));
// Do the unmarshalling
Object value = soapHeaderElement.getObjectValue();
unboundHeader.setHeaderValue(value);
outHeaders.put(xmlName, unboundHeader);
}
}
unboundHeaders.clear();
unboundHeaders.putAll(outHeaders);
}
Style style = opMetaData.getStyle();
SOAPElement soapElement = soapBody;
if (style == Style.RPC)
{
if (soapBodyElement == null)
throw new WSException("Cannot unbind response message with empty soap body");
soapElement = soapBodyElement;
}
ParameterMetaData retMetaData = opMetaData.getReturnParameter();
if (retMetaData != null)
{
if (retMetaData.isSwA())
{
AttachmentPart part = getAttachmentFromMessage(retMetaData, resMessage);
epInv.setReturnValue(part);
// Add the attachment to the standard property
if (part.getDataHandler() != null && msgContext instanceof MessageContextJAXWS)
{
DataHandler dataHandler = part.getDataHandler();
Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
attachments.put(part.getContentId(), dataHandler);
}
}
else
{
SOAPContentElement value = getParameterFromMessage(retMetaData, soapElement, false);
epInv.setReturnValue(value);
}
}
for (ParameterMetaData paramMetaData : opMetaData.getOutputParameters())
{
QName xmlName = paramMetaData.getXmlName();
if (paramMetaData.isSwA())
{
AttachmentPart part = getAttachmentFromMessage(paramMetaData, resMessage);
epInv.setResponseParamValue(xmlName, part);
if (part != null) { // m.
// Add the attachment to the standard property
if (part.getDataHandler() != null && msgContext instanceof MessageContextJAXWS)
{
DataHandler dataHandler = part.getDataHandler();
Map<String, DataHandler> attachments = (Map<String, DataHandler>)msgContext.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
attachments.put(part.getContentId(), dataHandler);
}
} // m.
}
else
{
SOAPElement element = paramMetaData.isInHeader() ? soapHeader : soapElement;
SOAPContentElement value = getParameterFromMessage(paramMetaData, element, false);
epInv.setResponseParamValue(xmlName, value);
}
}
}
catch (Exception e)
{
handleException(e);
}
}
public MessageAbstraction bindFaultMessage(Exception ex)
{
SOAPMessageImpl faultMessage = (SOAPMessageImpl)createFaultMessageFromException(ex);
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
if (msgContext != null)
{
msgContext.setSOAPMessage(faultMessage);
}
else
{
log.warn("Cannot set fault message in message context");
}
return faultMessage;
}
protected abstract SOAPMessage createFaultMessageFromException(Exception ex);
private void verifySOAPVersion(OperationMetaData opMetaData, SOAPEnvelope soapEnvelope)
{
String envNS = soapEnvelope.getNamespaceURI();
String bindingId = opMetaData.getEndpointMetaData().getBindingId();
if (CommonSOAPBinding.SOAP11HTTP_BINDING.equals(bindingId) && Constants.NS_SOAP11_ENV.equals(envNS) == false)
log.warn("Expected SOAP-1.1 envelope, but got: " + envNS);
if (CommonSOAPBinding.SOAP12HTTP_BINDING.equals(bindingId) && Constants.NS_SOAP12_ENV.equals(envNS) == false)
log.warn("Expected SOAP-1.2 envelope, but got: " + envNS);
}
private AttachmentPart createAttachmentPart(ParameterMetaData paramMetaData, Object value, CIDGenerator cidGenerator) throws SOAPException, BindingException
{
String partName = paramMetaData.getXmlName().getLocalPart();
Set mimeTypes = paramMetaData.getMimeTypes();
AttachmentPart part = new AttachmentPartImpl();
if (value instanceof DataHandler)
{
DataHandler handler = (DataHandler)value;
String mimeType = MimeUtils.getBaseMimeType(handler.getContentType());
// JAX-WS 2.0, 2.6.3.1 MIME Content
// Conformance (MIME type mismatch): On receipt of a message where the MIME type of a part does not
// match that described in the WSDL an implementation SHOULD throw a WebServiceException.
if (mimeTypes != null && !MimeUtils.isMemberOf(mimeType, mimeTypes))
log.warn("Mime type " + mimeType + " not allowed for parameter " + partName + " allowed types are " + mimeTypes);
part.setDataHandler((DataHandler)value);
}
else
{
String mimeType = null;
if (mimeTypes != null && mimeTypes.size() > 0)
{
mimeType = (String)mimeTypes.iterator().next();
}
else
{
mimeType = MimeUtils.resolveMimeType(value);
}
if (mimeType == null)
throw new BindingException("Could not determine mime type for attachment parameter: " + partName);
part.setContent(value, mimeType);
}
if (paramMetaData.isSwA())
{
String swaCID = '<' + partName + "=" + cidGenerator.generateFromCount() + '>';
part.setContentId(swaCID);
}
if (paramMetaData.isXOP())
{
String xopCID = '<' + cidGenerator.generateFromName(partName) + '>';
part.setContentId(xopCID);
}
return part;
}
private AttachmentPart getAttachmentFromMessage(ParameterMetaData paramMetaData, SOAPMessage message) throws SOAPException, BindingException
{
QName xmlName = paramMetaData.getXmlName();
AttachmentPart part = ((SOAPMessageImpl)message).getAttachmentByPartName(xmlName.getLocalPart());
if (part == null) { // m.
Iterator<SOAPElement> it = message.getSOAPBody().getChildElements(xmlName); // m.
if (it.hasNext()) { // m.
SOAPElement e = it.next(); // m.
part = ((SOAPMessageImpl)message).getAttachment(e); // m.
}
}
// m. if (part == null)
// m. throw new BindingException("Could not locate attachment for parameter: " + paramMetaData.getXmlName());
return part;
}
/** Marshall the given parameter and add it to the SOAPMessage */
private SOAPContentElement addParameterToMessage(ParameterMetaData paramMetaData, Object value, SOAPElement soapElement) throws SOAPException, BindingException
{
QName xmlName = paramMetaData.getXmlName();
Class javaType = paramMetaData.getJavaType();
if (value != null && paramMetaData.isXOP() == false)
{
Class valueType = value.getClass();
if (JavaUtils.isAssignableFrom(javaType, valueType) == false)
throw new BindingException("javaType " + javaType.getName() + " is not assignable from: " + valueType.getName());
}
// Make sure we have a prefix on qualified names
if (xmlName.getNamespaceURI().length() > 0)
{
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
NamespaceRegistry namespaceRegistry = msgContext.getNamespaceRegistry();
xmlName = namespaceRegistry.registerQName(xmlName);
}
Name soapName = new NameImpl(xmlName.getLocalPart(), xmlName.getPrefix(), xmlName.getNamespaceURI());
SOAPContentElement contentElement;
if (soapElement instanceof SOAPHeader)
{
contentElement = new SOAPHeaderElementImpl(soapName);
soapElement.addChildElement(contentElement);
}
else
{
Style style = paramMetaData.getOperationMetaData().getStyle();
if (style == Style.DOCUMENT)
{
contentElement = new SOAPBodyElementDoc(soapName);
soapElement.addChildElement(contentElement);
}
else
{
contentElement = new SOAPContentElement(soapName);
soapElement.addChildElement(contentElement);
}
}
contentElement.setParamMetaData(paramMetaData);
if (paramMetaData.isSOAPArrayParam())
{
log.trace("Add parameter as SOAP encoded Array");
contentElement.addNamespaceDeclaration(Constants.PREFIX_SOAP11_ENC, Constants.URI_SOAP11_ENC);
}
// When a potential xop parameter is detected and MTOM is enabled
// we flag the SOAP message as a XOP package
if (paramMetaData.isXOP() && XOPContext.isMTOMEnabled())
{
log.trace("Add parameter as XOP");
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
SOAPMessageImpl soapMessage = (SOAPMessageImpl)msgContext.getSOAPMessage();
soapMessage.setXOPMessage(true);
}
else if (paramMetaData.isSwaRef())
{
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
SOAPMessageImpl soapMessage = (SOAPMessageImpl)msgContext.getSOAPMessage();
soapMessage.setSWARefMessage(true);
}
contentElement.setObjectValue(value);
return contentElement;
}
/** Unmarshall a message element and add it to the parameter list */
private SOAPContentElement getParameterFromMessage(ParameterMetaData paramMetaData, SOAPElement soapElement, boolean optional) throws BindingException
{
Name xmlName = new NameImpl(paramMetaData.getXmlName());
SOAPContentElement soapContentElement = null;
Iterator childElements = soapElement.getChildElements();
while (childElements.hasNext())
{
Object childNode = childElements.next();
if (childNode instanceof SOAPElement)
{
SOAPElementImpl childElement = (SOAPElementImpl)childNode;
// If this message was manipulated by a handler the child may not be a content element
if (!(childElement instanceof SOAPContentElement))
childElement = (SOAPContentElement)soapElement.replaceChild(new SOAPContentElement(childElement), childElement);
// The parameters are expected to be lazy
SOAPContentElement aux = (SOAPContentElement)childElement;
Name elName = aux.getElementName();
if (xmlName.equals(elName))
{
soapContentElement = aux;
soapContentElement.setParamMetaData(paramMetaData);
break;
}
if (SOAP_ARRAY_NAME.equals(elName))
{
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
msgContext.put(CommonMessageContext.ALLOW_EXPAND_TO_DOM, Boolean.TRUE);
try
{
QName compXMLName = paramMetaData.getXmlName();
Element compElement = DOMUtils.getFirstChildElement(aux);
// NPE when the soap encoded array size is 0 on the return path
// http://jira.jboss.org/jira/browse/JBWS-1285
if (compElement == null || compElement.getNodeName().equals(compXMLName.getLocalPart()))
{
soapContentElement = aux;
soapContentElement.setParamMetaData(paramMetaData);
break;
}
}
finally
{
msgContext.remove(CommonMessageContext.ALLOW_EXPAND_TO_DOM);
}
}
}
}
// If matching by name fails, try to match by xmlType
// This maybe necessary when wsa:Action dispatches to the operation
if (soapContentElement == null)
{
childElements = soapElement.getChildElements();
OperationMetaData opMetaData = paramMetaData.getOperationMetaData();
TypesMetaData typesMetaData = opMetaData.getEndpointMetaData().getServiceMetaData().getTypesMetaData();
if (childElements.hasNext() && opMetaData.getStyle() == Style.DOCUMENT)
{
SOAPElementImpl childElement = (SOAPElementImpl)childElements.next();
// The parameters are expected to be lazy
SOAPContentElement aux = (SOAPContentElement)childElement;
Name elName = aux.getElementName();
QName elType = null;
XSElementDeclaration xsdElement = typesMetaData.getSchemaModel().getElementDeclaration(elName.getLocalName(), elName.getURI());
if (xsdElement != null && xsdElement.getTypeDefinition() != null)
{
XSTypeDefinition xsdType = xsdElement.getTypeDefinition();
elType = new QName(xsdType.getNamespace(), xsdType.getName());
}
if (paramMetaData.getXmlType().equals(elType))
{
soapContentElement = aux;
soapContentElement.setParamMetaData(paramMetaData);
}
}
}
if (soapContentElement == null && optional == false)
throw new WSException("Cannot find child element: " + xmlName);
// When a potential XOP parameter is detected and
// the incomming request is actuall XOP encoded we flag
// the SOAP message a XOP packaged.
if (paramMetaData.isXOP() && XOPContext.isXOPEncodedRequest())
{
SOAPMessageImpl soapMessage = (SOAPMessageImpl)MessageContextAssociation.peekMessageContext().getSOAPMessage();
soapMessage.setXOPMessage(true);
}
else if (paramMetaData.isSwaRef())
{
SOAPMessageImpl soapMessage = (SOAPMessageImpl)MessageContextAssociation.peekMessageContext().getSOAPMessage();
soapMessage.setSWARefMessage(true);
}
return soapContentElement;
}
abstract protected void throwFaultException(SOAPFaultImpl fault) throws Exception;
abstract protected void verifyUnderstoodHeader(SOAPHeaderElement element) throws Exception;
public void checkMustUnderstand(OperationMetaData opMetaData) throws Exception
{
CommonMessageContext msgContext = MessageContextAssociation.peekMessageContext();
if (msgContext == null)
throw new WSException("MessageContext not available");
SOAPMessageImpl soapMessage = (SOAPMessageImpl)msgContext.getSOAPMessage();
SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope();
if (soapEnvelope == null || soapEnvelope.getHeader() == null)
return;
Iterator it = soapEnvelope.getHeader().examineAllHeaderElements();
while (it.hasNext())
{
SOAPHeaderElement soapHeaderElement = (SOAPHeaderElement)it.next();
Name name = soapHeaderElement.getElementName();
QName xmlName = new QName(name.getURI(), name.getLocalName());
ParameterMetaData paramMetaData = (opMetaData != null ? opMetaData.getParameter(xmlName) : null);
boolean isBoundHeader = (paramMetaData != null && paramMetaData.isInHeader());
if (!isBoundHeader && soapHeaderElement.getMustUnderstand())
verifyUnderstoodHeader(soapHeaderElement);
}
}
public void setHeaderSource(HeaderSource source)
{
headerSource = source;
}
private void handleException(Exception ex) throws BindingException
{
if (ex instanceof RuntimeException)
throw (RuntimeException)ex;
if (ex instanceof BindingException)
throw (BindingException)ex;
throw new BindingException(ex);
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 6 months
[JBoss JIRA] Created: (JBWS-2023) MTOM - javax.xml.ws.soap.SOAPFaultException: org.xml.sax.SAXParseException: Content is not allowed in trailing section.
by David Boeren (JIRA)
MTOM - javax.xml.ws.soap.SOAPFaultException: org.xml.sax.SAXParseException: Content is not allowed in trailing section.
-----------------------------------------------------------------------------------------------------------------------
Key: JBWS-2023
URL: http://jira.jboss.com/jira/browse/JBWS-2023
Project: JBoss Web Services
Issue Type: Bug
Security Level: Public (Everyone can see)
Components: jbossws-native
Affects Versions: jbossws-2.0.1.SP1
Environment: Using JBoss EAP 4.3
Reporter: David Boeren
Attachments: DeviceConfigClient.java, server.log, ServiceDeviceConfig.java
When MTOM is enabled on the client side, I am getting the following exceptiong when I invoke the web service method.
If I comment out the following lines in the client code, the server receives the xml correctly and the web service is working as expected.
/** get the binding and enable mtom
SOAPBinding binding = (SOAPBinding)((BindingProvider)stub).getBinding ();
binding.setMTOMEnabled (true);
*/
2008-02-29 16:31:04,699 ERROR [STDERR] [Fatal Error] :2:1: Content is not allowed in trailing section.
2008-02-29 16:31:04,704 DEBUG [org.jboss.ws.metadata.umdm.EndpointMetaData] Configure SOAPBinding
2008-02-29 16:31:04,708 ERROR [org.jboss.ws.core.jaxws.SOAPFaultHelperJAXWS] SOAP request exception
org.jboss.ws.core.CommonSOAPFaultException: org.xml.sax.SAXParseException: Content is not allowed in trailing section.
at org.jboss.ws.core.soap.EnvelopeBuilderDOM.build(EnvelopeBuilderDOM.java:93)
at org.jboss.ws.core.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:262)
at org.jboss.ws.core.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:185)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.processRequest(RequestHandlerImpl.java:389)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleRequest(RequestHandlerImpl.java:272)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.doPost(RequestHandlerImpl.java:189)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:122)
at org.jboss.wsf.stack.jbws.EndpointServlet.service(EndpointServlet.java:84)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:580)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:595)
Our test XML is:
<?xml version="1.0" encoding="UTF-8"?>
<DB>
</DB>
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 6 months