axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Eran Chinthaka (JIRA)" <j...@apache.org>
Subject [jira] Commented: (AXIS2-919) Unable to print out entire SOAP message: bug in OMElement.serialize()
Date Tue, 05 Sep 2006 06:22:22 GMT
    [ http://issues.apache.org/jira/browse/AXIS2-919?page=comments#action_12432571 ] 
            
Eran Chinthaka commented on AXIS2-919:
--------------------------------------

Hi Derek,

This is the reply for http://issues.apache.org/jira/browse/AXIS2-919#action_12429161.

Well, I agree with your points in the design pov. But we have a problem in that when we are
using Collection classes instead of Iterators with Axiom.
The reason for selecting Iterators is to get the maximum out of deferred building capability
of Axiom. For example, when you get an iterator when you call getChildren() from an OMElement,
most of the time none of the child elements are being built. Those are built one by one as
and when you progress along the iterator.
But if we provided the Collection interface, we will lose the advantage of deferred  building
if the user calls the size() method. We basically wanted to promote users to get maximum out
of the deferred building.

I still can remember the hot arguments we had about selecting which interface to use. But
we decided to use iterator, after all. 

BTW, can we please move this discussion to commons-dev as its the place to discuss Axiom issues
and close this one? Derek, its your call :)

> Unable to print out entire SOAP message: bug in OMElement.serialize()
> ---------------------------------------------------------------------
>
>                 Key: AXIS2-919
>                 URL: http://issues.apache.org/jira/browse/AXIS2-919
>             Project: Apache Axis 2.0 (Axis2)
>          Issue Type: Bug
>          Components: core, om
>    Affects Versions: 1.0
>            Reporter: Derek Foster
>         Assigned To: Eran Chinthaka
>            Priority: Blocker
>
> I was attempting, inside an XMLBeans-generated service method, to print out the entire
SOAP message to a log file. Towards that end, I tried to execute the following code:
> final StringWriter writer = new StringWriter();
> messageContext.getEnvelope().serialize(writer);
> System.out.println(writer.toString());
> However, I was surprised to get the following exception resulting from this:
> org.apache.axiom.om.OMException
> 	at org.apache.axiom.om.impl.llom.OMElementImpl.getNextOMSibling(OMElementImpl.java:266)
> 	at org.apache.axiom.om.impl.traverse.OMChildrenIterator.next(OMChildrenIterator.java:111)
> 	at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:771)
> 	at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:177)
> 	at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:756)
> 	at org.apache.axiom.om.impl.llom.OMNodeImpl.serialize(OMNodeImpl.java:310)
> 	at org.apache.axiom.om.impl.llom.OMNodeImpl.serialize(OMNodeImpl.java:352)
>        ...
> The cause of the problem appears to be the fact that the SOAP envelope is a top-level
XML object. Thus, the item immediately following it is a DOCUMENT_END. The OMElementImpl.internalSerialize(XMLStreamWriter,
boolean cache) method contains the following code:
>             Iterator children = this.getChildren();
>             while (children.hasNext()) {
>                 ((OMNodeEx) children.next()).internalSerialize(writer);
> which seems plausible. However, the iterator that is returned is of type OMChildrenIterator.
Its hasNext method looks like this:
>     /**
>      * Returns <tt>true</tt> if the iteration has more elements. (In other
>      * words, returns <tt>true</tt> if <tt>next</tt> would return
an element
>      * rather than throwing an exception.)
>      *
>      * @return Returns <tt>true</tt> if the iterator has more elements.
>      */
>     public boolean hasNext() {
>         return (currentChild != null);
>     }
> but its next() method looks like this:
>     /**
>      * Returns the next element in the iteration.
>      *
>      * @return Returns the next element in the iteration.
>      * @throws java.util.NoSuchElementException
>      *          iteration has no more elements.
>      */
>     public Object next() {
>         nextCalled = true;
>         removeCalled = false;
>         if (hasNext()) {
>             lastChild = currentChild;
>             currentChild = currentChild.getNextOMSibling();
>             return lastChild;
>         }
>         return null;
>     }
> which is a problem, because currentChild.getNextOMSibling() looks like this:
>     /**
>      * Gets the next sibling. This can be an OMAttribute or OMText or
>      * OMELement for others.
>      *
>      * @throws OMException
>      */
>     public OMNode getNextOMSibling() throws OMException {
>         while (!done) {
>             int token = builder.next();
>             if (token == XMLStreamConstants.END_DOCUMENT) {
>                 throw new OMException();
>             }
>         }
>         return super.getNextOMSibling();
>     }
> which will under some circumstances throw an OMException, which is not in the contract
of the iterator's next() method to throw.
> Thus, iterator.hasNext() is returning true, implying that there is a next element, but
when next() is actually called, the iterator discovers that it has reached the end of the
document, and that therefore there really is no next element. It therefore throws an OMException.
> Firstly, if the next() method is going to be implemented this way, then hasNext() should
perform enough lookahead on the document to detect that the next item in the input stream
is indeed a END_DOCUMENT, and should therefore return false, since under these circumstances
there truly isn't a next element (and calling next() would therefore always throw an OMException).
That way, when the end of the document is hit, the serialize method will simply stop and return
its results rather than trying to advance past the end of the document as it does now.
> Secondly, this OMException really should have some meaningful error text in it, such
as "Can't call 'next()' on an iterator which is positioned at element 'foo' which is the last
element in the document" or even better, "Can't call next() when hasNext() returns false"
(see below). I can't think of any cases in typical library code where it is desirable to throw
exceptions that don't have any message text. This is really unpleasant for anybody that is
trying to debug a problem. I would encourage someone to do a search through the source code
for "throw new OMException()" and add an explanatory error message wherever one is found.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe, e-mail: axis-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-dev-help@ws.apache.org


Mime
View raw message