You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Jesse Pangburn <Je...@us.lawson.com> on 2011/11/10 03:36:44 UTC

partial response problem with SOAP 1.1 use of WS-Addressing and SOAPAction

Hi,
I invoked a SOAP 1.1 web service using CXF 2.4.2 DispatchImpl and that service immediately returned the following soap header:
	<soap:Header>
		<wsa:MessageID>uuid:A12B3727-0B3D-11E1-983D-DFB5348FF699</wsa:MessageID>
		<wsa:Action>response</wsa:Action>
	</soap:Header>

My client hung for 60 seconds until a timeout was reached, at which point the response was available in the StaxSource.  Tracing the problem into the code revealed that it was waiting because the message response it had received so far was deemed a "partial response" due to the following code which always is called when WS-Addressing is enabled in MAPCodec.java:
    private void markPartialResponse(SoapMessage message, AddressingProperties maps) {
        if (ContextUtils.isRequestor(message) && null != maps
            && (null == maps.getRelatesTo() 
                || (null != maps.getRelatesTo()
                    && Names.WSA_UNSPECIFIED_RELATIONSHIP.equals(maps.getRelatesTo().getValue())))) {
            message.put(Message.PARTIAL_RESPONSE_MESSAGE, Boolean.TRUE);
        } 
    }

The problem, I think, is this condition "null == maps.getRelatesTo()".  This essentially means that a WS-Addressing RelatesTo header is required to indicate that a message response is complete- even on a synchronous request/response.  I think the source of this problem is that the original WS-Addressing submission to W3C said that "This element MUST be present if the message is a reply" in the description for the RelatesTo header (see http://www.w3.org/Submission/ws-addressing/#_Toc77464323).  This language was struck from the final WS-Addressing 1.0 (see http://www.w3.org/TR/ws-addr-core/#msgaddrpropsinfoset) and means that RelatesTo is not required.

While I think it was sloppy on the part of the service writer to not include the RelatesTo header, it is OPTIONAL according to the spec.  So, especially in the case of a synchronous request, I think this code is incorrect.  A CXF Dispatch client should not hang until timeout is reached because an optional header is not included in the response.

Unfortunately, I'm not really sure what the correct solution is here since I don't understand the case for ever having a partial response message in a synchronous request/response.  Should later code note that the request/response is synchronous and ignore this partial response flag?  I assume the intention of this code is for asynchronous request/response so that the immediate response on the request's socket connection is not treated as the asynchronous response message.

Any clues?
Thanks,
Jesse



RE: partial response problem with SOAP 1.1 use of WS-Addressing and SOAPAction

Posted by Jesse Pangburn <Je...@us.lawson.com>.
Issue is created as https://issues.apache.org/jira/browse/CXF-3916

I've run the following build command on 2.4.2 with this patched and it didn't give any errors:
mvn -Pfastinstall,everything install

Not sure if that build command runs the tests you're referring to or not.

Thanks,
Jesse

-----Original Message-----
From: Daniel Kulp [mailto:dkulp@apache.org] 
Sent: Tuesday, November 15, 2011 1:10 PM
To: users@cxf.apache.org
Cc: Jesse Pangburn
Subject: Re: partial response problem with SOAP 1.1 use of WS-Addressing and SOAPAction

On Thursday, November 10, 2011 4:39:22 PM Jesse Pangburn wrote:
> Hi Dan,
> So I've read over this more and now see that the partial response stuff is
> definitely for asynchronous processing, so the check with the WS-Addressing
> relatesTo header makes sense.  The problem (I think) appears in your
> checkin revision 705446 for ClientImpl.java in this section: synchronized
> (message.getExchange()) {
>         if (!isPartialResponse(message) && callback == null) {
>             message.getExchange().put(FINISHED, Boolean.TRUE);
>             message.getExchange().setInMessage(message);
>             message.getExchange().notifyAll();
>         }
>     }
> 
> You added the "&& callback == null" test, but I think what is needed is "||
> callback == null".  The idea here (again, as I'm reading it) is regarding
> these two cases: - it's an asynchronous response which is not a partial
> response
> - there is no callback, meaning it's a synchronous response
> 
> In either of these cases you want to tell the exchange that it's finished
> and the message you just got is the inbound message.  I think this worked
> for a long time without anyone running into this because in the synchronous
> case (callback == null), the only way you get a partialResponse==true is
> when WS-Addressing is engaged AND the server that you're connecting to
> doesn't return the optional (but almost always used) relatesTo header. 
> Probably in the vast majority of cases either WS-Addressing isn't used or
> the relatesTo header is present in a response.
> 
> If you agree, I can create a defect and describe this.  Since the change is
> just && to ||, obviously it won't help to send you a patch file :-)

That SOUNDS likely from the description, but I'd definitely need to run all 
the tests and such again to make sure.   Can you file a JIRA with all this so 
I don't forget about it and to make sure it's tracked?

Thanks!

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog
Talend - http://www.talend.com



Re: partial response problem with SOAP 1.1 use of WS-Addressing and SOAPAction

Posted by Daniel Kulp <dk...@apache.org>.
On Thursday, November 10, 2011 4:39:22 PM Jesse Pangburn wrote:
> Hi Dan,
> So I've read over this more and now see that the partial response stuff is
> definitely for asynchronous processing, so the check with the WS-Addressing
> relatesTo header makes sense.  The problem (I think) appears in your
> checkin revision 705446 for ClientImpl.java in this section: synchronized
> (message.getExchange()) {
>         if (!isPartialResponse(message) && callback == null) {
>             message.getExchange().put(FINISHED, Boolean.TRUE);
>             message.getExchange().setInMessage(message);
>             message.getExchange().notifyAll();
>         }
>     }
> 
> You added the "&& callback == null" test, but I think what is needed is "||
> callback == null".  The idea here (again, as I'm reading it) is regarding
> these two cases: - it's an asynchronous response which is not a partial
> response
> - there is no callback, meaning it's a synchronous response
> 
> In either of these cases you want to tell the exchange that it's finished
> and the message you just got is the inbound message.  I think this worked
> for a long time without anyone running into this because in the synchronous
> case (callback == null), the only way you get a partialResponse==true is
> when WS-Addressing is engaged AND the server that you're connecting to
> doesn't return the optional (but almost always used) relatesTo header. 
> Probably in the vast majority of cases either WS-Addressing isn't used or
> the relatesTo header is present in a response.
> 
> If you agree, I can create a defect and describe this.  Since the change is
> just && to ||, obviously it won't help to send you a patch file :-)

That SOUNDS likely from the description, but I'd definitely need to run all 
the tests and such again to make sure.   Can you file a JIRA with all this so 
I don't forget about it and to make sure it's tracked?

Thanks!

-- 
Daniel Kulp
dkulp@apache.org
http://dankulp.com/blog
Talend - http://www.talend.com

RE: partial response problem with SOAP 1.1 use of WS-Addressing and SOAPAction

Posted by Jesse Pangburn <Je...@us.lawson.com>.
Hi Dan,
So I've read over this more and now see that the partial response stuff is definitely for asynchronous processing, so the check with the WS-Addressing relatesTo header makes sense.  The problem (I think) appears in your checkin revision 705446 for ClientImpl.java in this section:
    synchronized (message.getExchange()) {
        if (!isPartialResponse(message) && callback == null) {
            message.getExchange().put(FINISHED, Boolean.TRUE);
            message.getExchange().setInMessage(message);
            message.getExchange().notifyAll();                   
        }
    }

You added the "&& callback == null" test, but I think what is needed is "|| callback == null".  The idea here (again, as I'm reading it) is regarding these two cases:
- it's an asynchronous response which is not a partial response
- there is no callback, meaning it's a synchronous response

In either of these cases you want to tell the exchange that it's finished and the message you just got is the inbound message.  I think this worked for a long time without anyone running into this because in the synchronous case (callback == null), the only way you get a partialResponse==true is when WS-Addressing is engaged AND the server that you're connecting to doesn't return the optional (but almost always used) relatesTo header.  Probably in the vast majority of cases either WS-Addressing isn't used or the relatesTo header is present in a response.

If you agree, I can create a defect and describe this.  Since the change is just && to ||, obviously it won't help to send you a patch file :-)

Thanks,
Jesse

-----Original Message-----
From: Jesse Pangburn [mailto:Jesse.Pangburn@us.lawson.com] 
Sent: Wednesday, November 09, 2011 6:37 PM
To: users@cxf.apache.org
Subject: partial response problem with SOAP 1.1 use of WS-Addressing and SOAPAction

Hi,
I invoked a SOAP 1.1 web service using CXF 2.4.2 DispatchImpl and that service immediately returned the following soap header:
	<soap:Header>
		<wsa:MessageID>uuid:A12B3727-0B3D-11E1-983D-DFB5348FF699</wsa:MessageID>
		<wsa:Action>response</wsa:Action>
	</soap:Header>

My client hung for 60 seconds until a timeout was reached, at which point the response was available in the StaxSource.  Tracing the problem into the code revealed that it was waiting because the message response it had received so far was deemed a "partial response" due to the following code which always is called when WS-Addressing is enabled in MAPCodec.java:
    private void markPartialResponse(SoapMessage message, AddressingProperties maps) {
        if (ContextUtils.isRequestor(message) && null != maps
            && (null == maps.getRelatesTo() 
                || (null != maps.getRelatesTo()
                    && Names.WSA_UNSPECIFIED_RELATIONSHIP.equals(maps.getRelatesTo().getValue())))) {
            message.put(Message.PARTIAL_RESPONSE_MESSAGE, Boolean.TRUE);
        } 
    }

The problem, I think, is this condition "null == maps.getRelatesTo()".  This essentially means that a WS-Addressing RelatesTo header is required to indicate that a message response is complete- even on a synchronous request/response.  I think the source of this problem is that the original WS-Addressing submission to W3C said that "This element MUST be present if the message is a reply" in the description for the RelatesTo header (see http://www.w3.org/Submission/ws-addressing/#_Toc77464323).  This language was struck from the final WS-Addressing 1.0 (see http://www.w3.org/TR/ws-addr-core/#msgaddrpropsinfoset) and means that RelatesTo is not required.

While I think it was sloppy on the part of the service writer to not include the RelatesTo header, it is OPTIONAL according to the spec.  So, especially in the case of a synchronous request, I think this code is incorrect.  A CXF Dispatch client should not hang until timeout is reached because an optional header is not included in the response.

Unfortunately, I'm not really sure what the correct solution is here since I don't understand the case for ever having a partial response message in a synchronous request/response.  Should later code note that the request/response is synchronous and ignore this partial response flag?  I assume the intention of this code is for asynchronous request/response so that the immediate response on the request's socket connection is not treated as the asynchronous response message.

Any clues?
Thanks,
Jesse