The MessageBinding solution incorrectly advances the cursor of XMLStreamReader
message during the client/server XFire transport.
--------------------------------------------------------------------------------------------------------------------------------
Key: XFIRE-866
URL: http://jira.codehaus.org/browse/XFIRE-866
Project: XFire
Issue Type: Bug
Components: Core
Affects Versions: 1.2.3
Reporter: Scott Seixas
Assigned To: Dan Diephouse
I am developing a solution using XFire that uses MessageBinding to transport
the entire XML input from the XFire client to my defined service as an
XMLStreamReader object. However, during the transport of this XMLStreamReader
object the parser's cursor is incorrectly advanced.
To clarify the issue further, consider the below implementation:
//ServiceImpl
public XMLStreamReader echo( XMLStreamReader reader )
{
return reader;
}
//Client Program
AnnotationServiceFactory factory = new AnnotationServiceFactory(new
Jsr181WebAnnotations(), xfire.getTransportManager(), new
MessageBindingProvider());
factory.setStyle("message");
Service test = factory.create(TestService.class);
URL u = new URL("http://localhost/test.xml");
InputStream in = u.openStream();
XMLStreamReader parser = STAXUtils.createXMLStreamReader( in , null, null );
XFireProxyFactory serviceFactory = new XFireProxyFactory();
TestService service = (TestService) serviceFactory.create( test,
"http://localhost/services/TestService");
XMLStreamReader output = service.echo( parser );
In this example if the test.xml input document originally looked like
<A><B><C><D></D></C></B></A>
Then the XML output would look like
<C><D></D></C>
(i.e. the cursor is currently pointing to <C>)
This occurs because the XMLStreamReader message advances its cursor one element
during the SOAPBodyHandler on the XFire server side prior to calling the
service and again on the XFire client side prior to returning back to the
client program.
The desired behavior is that the XMLStreamReader input/output should not have
its cursor advance past the root element of the original document during the
transport of this stream. Thus, the output XMLStreamReader object should have
its cursor on the root element <A> and not on <C>.
The errant logic is in the loop on the bottom of the readMessage method in the
org.codehaus.xfire.service.binding.MessageBinding class. The code in this loop
is implemented as seen below:
//Errant Logic
for ( Iterator itr = msg.getMessageParts().iterator(); itr.hasNext(); )
{
MessagePartInfo p = (MessagePartInfo) itr.next();
params.add( service.getBindingProvider().readParameter(p,
message.getXMLStreamReader(), context) );
nextEvent(message.getXMLStreamReader());
}
When p is a XMLStreamReader type then the readParameter method simply returns
the XMLStreamReader object of the message. Thus, the params list contains a
reference to the message's XMLStreamReader object. However, the next line of
code advances the cursor of the message's XMLStreamReader which advances the
object reference in the params list.
This advances seems to be unnecessary because there is only one message part to
iterate through.
I have fixed this locally (see below) by modifying the logic to advance the
cursor of the message only if there exist a next message part. If the loop is
currently handling the last message part, then there is no reason to advance
the cursor. Of course, since the MessageBinding approach is meant to treat the
entire SOAP Body XML as a single input/output, you could also remove the loop
and the nextEvent call all together and implement the logic under the
assumption that the MessageBinding only has a single message body part.
//My fix
for (Iterator itr = msg.getMessageParts().iterator(); itr.hasNext(); )
{
MessagePartInfo p = (MessagePartInfo) itr.next();
params.add( service.getBindingProvider().readParameter(p,
message.getXMLStreamReader(), context) );
if( itr.hasNext() ) nextEvent(message.getXMLStreamReader());
}
//Potential fix
Iterator itr = msg.getMessageParts().iterator;
MessagePartInfo p = (MessagePartInfo) itr.next();
params.add( service.getBindingProvider().readParameter(p,
message.getXMLStreamReader(), context) );
if( itr.hasNext() ) throw new Exception( "Too many parameters for
MessageBinding");
The work to implement this fix is trivial, but the end result is quite powerful
as it preserves the context of the XMLStreamReader object during transport when
it is the input/output parameter of a MessageBinding implementation.
Regards,
Scott Seixas
Software Engineer
CA - Clarity Division, BSO (formerly Niku)
650.298.5923
[EMAIL PROTECTED]
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe from this list please visit:
http://xircles.codehaus.org/manage_email