JDK-8186441 : Change of behavior in the getMessage () method of the SOAPMessageContextImpl class
  • Type: Bug
  • Component: xml
  • Sub-Component: jax-ws
  • Affected Version: 8u141
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2017-08-11
  • Updated: 2018-05-14
  • Resolved: 2017-11-30
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 10 JDK 8
10 b35Fixed 8u152Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) Client VM (build 25.144-b01, mixed mode, sharing)


ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Versi��n 6.1.7601]

A DESCRIPTION OF THE PROBLEM :

Using the default implementation of jaxws and xml api distributed with the jre Java(TM) SE Runtime Environment (build 1.8.0_141-b15)

In a web service client jaxws which has a handler that implements SOAPHandler<SOAPMessageContext>, used to sing the payload inside the SOAP Message, since 1.8.0_141-b15 version, the message obtained with the getMessage() method of the com.sun.xml.internal.ws.handler.SOAPMessageContextImp class,  to be signed moves  the namespaces of the root tag of the payload to the Soap Body tag, and then signs a String xml different from the original sent by user. 

Besides, when deleting the namespace from the root tag of the payload of the Soap Message, causes the server does not know which operation is responsible for processing that message for not bearing the namespace.

The same problem occurs with the response, when is used the SOAPMessageContextImpl .getMessage() to obtain the SOAPMEssage, then it moves the namespaces and check the signature. It always fails because we are not checking the original message which answers the server.

Activating java debugging we can see clearly:

---[HTTP response - https://host/ServiceContext/ServiceEME - 200]---
Connection: Keep-Alive
Content-Type: application/soap+xml; charset=utf-8
Date: Wed, 09 Aug 2017 17:09:51 GMT
Keep-Alive: timeout=5, max=100
Referrer-policy: no-referrer
Server: MSX-2
Set-Cookie: _WL_AUTHCOOKIE_JSESSIONID=5iLt2F1sTk9G08vAd2qc; path=/; secure; ; Secure; HttpOnly
Strict-Transport-Security: max-age=63072000;
Transfer-Encoding: chunked
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
<?xml version='1.0' encoding='UTF-8'?><SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Body>
<ResponseMessage xmlns="http://iec.ch/TC57/2011/schema/message"><Header><Verb>reply</Verb><Noun>AckHoras</Noun><Timestamp>2017-08-09T17:09:02.359Z</Timestamp><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI=""><Tran


In the client response Handler when the message is obtained by this method is different from the original message sent by the server.

@Override
    public boolean handleMessage(final SOAPMessageContext messageContext) {

        SOAPMessage message = messageContext.context.getMessage()
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        message.writeTo(baos);
        String soapToSing= baos.toString(StandardCharsets.UTF_8.name());

}


The soapToSing has the next content:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Header/
><SOAP-ENV:Body xmlns="http://iec.ch/TC57/2011/schema/message"><ResponseMessage><Header xmlns="http://iec.ch/TC57/2011/schema/message"><Verb>reply</Verb><Noun>AckHoras</Noun><Timestamp>2017-08-09T17:0

The namesapace of the RequestMessage has no namespace and it has been transferred to the Body tag.


REGRESSION.  Last worked in version 8u131

ADDITIONAL REGRESSION INFORMATION: 
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The string extracted from the SoapMessageContext should be:


<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Body>
<ResponseMessage xmlns="http://iec.ch/TC57/2011/schema/message"><Header><Verb>reply</Verb><Noun>AckHoras</Noun><Timestamp>2017-08-09T17:09:02.359Z</Timestamp><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><Reference URI=""><Tran..........

ACTUAL -
The string extracted from the SoapMessageContext is:


<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Header/
><SOAP-ENV:Body xmlns="http://iec.ch/TC57/2011/schema/message"><ResponseMessage><Header xmlns="http://iec.ch/TC57/2011/schema/message"><Verb>reply</Verb><Noun>AckHoras</Noun><Timestamp>2017-08-09T17:0

The Body has the namespace of the RequestMessage tag, and the RequestMessage needs the namespace to be processed by the webservice in the server.


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
A webservice client uses the default implemenattion of jaxws ot the jre distribution.

Client code where the handler is attached ...

@SuppressWarnings("rawtypes")
    protected final ResponseMessage sendMessage(final RequestMessage message) throws HandlerException {

        ResponseMessage retValue = null;

        try {
            ServiceEME service = new ServiceEME(getClass().getClassLoader().getResource(WSDL_FILE), SERVICE_NAME);
            PortTFEDIType port = service.getServiceEMEPort();
            BindingProvider bindingProvider = (BindingProvider) port;
            bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPoint.toString());

            /* sets a handler in order to sign and verify signature. The handler is useful also for debug. */
            messageMetaData = new MessageMetaData();
            Binding binding = bindingProvider.getBinding();
            List<Handler> handlerList = binding.getHandlerChain();
            handlerList.add(new SendHandler(signRequest, verifyResponse, messageMetaData, certificate, privateKey));
            binding.setHandlerChain(handlerList);

            retValue = port.request(message);

            /* Throws exception if the retrieved message has an invalid signature. */
            MessageMetaData metadata = getMessageMetaData();
            if (metadata.getException() != null) {
                throw (HandlerException) metadata.getException();
            }

        } catch (MsgFaultMsg ex) {


-- Code of the Handler SendHandler.java used in request and response of a webservice call.
public final class SendHandler implements SOAPHandler<SOAPMessageContext> {


    public SendHandler() {
    }

    /**
     * Gets this handler headers.
     * @return An empty set.
     */
    @Override
    public Set<QName> getHeaders() {

        return Collections.emptySet();
    }

    /**
     * Called at the end of a message interchange.
     * @param mc Message context.
     */
    @Override
    public void close(final MessageContext mc) {

        /* This method should not be implemented. */
    }


    @Override
    public boolean handleFault(final SOAPMessageContext messageContext) {

       return true;
    }


    @Override
    public boolean handleMessage(final SOAPMessageContext messageContext) {


        SOAPMessage message = messageContext.context.getMessage()
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        message.writeTo(baos);
        String soapToSing= baos.toString(StandardCharsets.UTF_8.name());

/**THE SOAPTOSING is different from the original*/

............
        return true;
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Force the classpath of the client to use an older implementation for jax-ws, 
We  have used next implementation:
    <dependency>
      <groupId>com.sun.xml.ws</groupId>
      <artifactId>jaxws-rt</artifactId>
    <version>2.2.6</version>



Comments
Seems like JDK-8159058 changed the behavior of SOAPMessageContextImpl class. Since this class is internal one, the additional investigation might be needed to understand if it works/or not according to SOAP documentation. JDK-8159058 is a serious bug therefore it can't be reverted. Additional work might be needed to improve JDK-8159058 fix delivered to standalone JAXWS-RI project if this one will be confirmed as a bug.
14-11-2017