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

Reply via email to