5 Replies Latest reply on Jul 29, 2008 12:14 PM by poutsma

    IndexOutOfBoundsException when transforming into SAAJ SOAPBo

    poutsma

      Hi,

      The following piece of code throws an IndexOutOfBoundsException in org.jboss.ws.soap.NodeImpl.getFirstChild:

      import org.w3c.dom.Document;
      import org.w3c.dom.Element;
      
      import javax.xml.parsers.DocumentBuilderFactory;
      import javax.xml.soap.MessageFactory;
      import javax.xml.soap.SOAPBody;
      import javax.xml.soap.SOAPMessage;
      import javax.xml.transform.Transformer;
      import javax.xml.transform.TransformerFactory;
      import javax.xml.transform.dom.DOMResult;
      import javax.xml.transform.dom.DOMSource;
      import javax.xml.transform.stream.StreamResult;
      
      public class SaajIssue {
      
       public static void main(String[] args) throws Exception {
       MessageFactory messageFactory = MessageFactory.newInstance();
       SOAPMessage soapMessage = messageFactory.createMessage();
       Transformer transformer = TransformerFactory.newInstance().newTransformer();
       Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
       Element root = document.createElementNS("http://test.com", "root");
       document.appendChild(root);
       Element child = document.createElementNS("http://test.com", "child");
       root.appendChild(child);
       SOAPBody body = soapMessage.getSOAPBody();
       transformer.transform(new DOMSource(document), new DOMResult(body));
       // Next line throws an IndexOutOfBoundsException
       transformer.transform(new DOMSource(body), new StreamResult(System.out));
       }
      }
      


      This is the stacktrace:

      Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
       at java.util.ArrayList.RangeCheck(ArrayList.java:546)
       at java.util.ArrayList.get(ArrayList.java:321)
       at org.jboss.ws.soap.NodeImpl.getFirstChild(NodeImpl.java:311)
       at org.jboss.ws.soap.SOAPContentElement.getFirstChild(SOAPContentElement.java:746)
       at org.apache.xml.serializer.TreeWalker.traverse(TreeWalker.java:145)
       at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:389)
       at SaajIssue.main(SaajIssue.java:36)
      


      After some investigation, it appears that the root element is imported correctly, but the child element is not. To be more precise: it is imported into the internal domNode of NodeImpl, but not the soapChildren list.

      SUN's reference implementation of SAAJ does not throw this exception, so it appears this is a bug in the JBoss SAAJ implementation. Am I correct?

      Thanks,

      Arjen Poutsma

        • 1. Re: IndexOutOfBoundsException when transforming into SAAJ SO
          sivman

          Hi Arjen,

          I am facing the same problem deploying onto the jboss, did you get any solution for this. I tried with different saaj jars, but no luck.

          Thanks
          Siva.

          • 2. Re: IndexOutOfBoundsException when transforming into SAAJ SO
            asoldano

            It could be, feel free to create an issue on the JBossWS JIRA referencing this forum thread. Thank you.

            • 3. Re: IndexOutOfBoundsException when transforming into SAAJ SO
              poutsma
              • 4. Re: IndexOutOfBoundsException when transforming into SAAJ SO
                asoldano

                OK, I've taken a look at your issue: I've added your test to the native testsuite. Our implementation of Node, NodeImpl, holds the actual w3c node along with its children and our implementation of soapChildren. The exception you were having was due to the latter being null while it should have not. That's happen because of the transformation you use to append your document content to the SOAPBody.
                I've put a check there to prevent throwing the exception, but I know that's not the solution of your issue, as you don't get the soap message you would expect.
                In particular, as far as I can see, the current implementation was written relying on the following signature for the org.w3c.dom.Node's appendChild method:

                public org.w3c.dom.Node appendChild(org.w3c.dom.Node newChild) throws DOMException

                The implementation returns a new Node (a wrapper of the supplied one), that's what is actually appended as a child. The xalan implementation that does the transformation works on the node parameter supplied to the appendChild method.
                For the sake of understanding, the following patch on the current trunk of Xalan would fix this:
                [alessio@dhcp-176-228 trunk]$ svn diff src/org/apache/xml/utils/DOMBuilder.java
                Index: src/org/apache/xml/utils/DOMBuilder.java
                ===================================================================
                --- src/org/apache/xml/utils/DOMBuilder.java (revisione 680693)
                +++ src/org/apache/xml/utils/DOMBuilder.java (copia locale)
                @@ -172,26 +172,27 @@
                 *
                 * @param newNode New node to append
                 */
                - protected void append(Node newNode) throws org.xml.sax.SAXException
                + protected Node append(Node newNode) throws org.xml.sax.SAXException
                 {
                
                 Node currentNode = m_currentNode;
                + Node result = null;
                
                 if (null != currentNode)
                 {
                 if (currentNode == m_root && m_nextSibling != null)
                - currentNode.insertBefore(newNode, m_nextSibling);
                + result = currentNode.insertBefore(newNode, m_nextSibling);
                 else
                - currentNode.appendChild(newNode);
                + result = currentNode.appendChild(newNode);
                
                 // System.out.println(newNode.getNodeName());
                 }
                 else if (null != m_docFrag)
                 {
                 if (m_nextSibling != null)
                - m_docFrag.insertBefore(newNode, m_nextSibling);
                + result = m_docFrag.insertBefore(newNode, m_nextSibling);
                 else
                - m_docFrag.appendChild(newNode);
                + result = m_docFrag.appendChild(newNode);
                 }
                 else
                 {
                @@ -226,11 +227,12 @@
                 if (ok)
                 {
                 if (m_nextSibling != null)
                - m_doc.insertBefore(newNode, m_nextSibling);
                + result = m_doc.insertBefore(newNode, m_nextSibling);
                 else
                - m_doc.appendChild(newNode);
                + result = m_doc.appendChild(newNode);
                 }
                 }
                + return result;
                 }
                
                 /**
                @@ -329,7 +331,7 @@
                 else
                 elem = m_doc.createElementNS(ns, name);
                
                - append(elem);
                + elem = (Element)append(elem);
                
                 try
                 {
                


                • 5. Re: IndexOutOfBoundsException when transforming into SAAJ SO
                  poutsma

                  Ok, thanks for the fix. I understand the issue.

                  Are you planning on sharing that DOMBuilder patch with Xalan?