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:[email protected]]
Sent: Wednesday, November 09, 2011 6:37 PM
To: [email protected]
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