[ http://issues.apache.org/jira/browse/AXIS2-919?page=comments#action_12422805 ] Derek Foster commented on AXIS2-919: ------------------------------------
The title of this one should be "bug in OMElement.serialize()", not "but in..." Looks like my finger slipped. > Unable to print out entire SOAP message: but 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 > > 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]