You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by "Mark Tye (JIRA)" <ax...@ws.apache.org> on 2005/06/01 02:23:51 UTC

[jira] Created: (AXIS-2029) SOAPHeader.appendChild() throws unexpected ClassCastException

SOAPHeader.appendChild() throws unexpected ClassCastException
-------------------------------------------------------------

         Key: AXIS-2029
         URL: http://issues.apache.org/jira/browse/AXIS-2029
     Project: Axis
        Type: Bug
  Components: Basic Architecture, SAAJ  
    Versions: 1.2    
 Environment: Windows XP Pro/WebSphere 4.0
    Reporter: Mark Tye


The class org.apache.axis.message.SOAPHeader overrides the appendChild(org.w3c.dom.Node) method of org.apache.axis.message.NodeImpl in such a way that it breaks the contract of the org.3c.dom.Node.appendChild(org.w3c.dom.Node) interface.

Here's the implementation of appendChild(Node) in SOAPHeader:

390    public Node appendChild(Node newChild) throws DOMException {
391        SOAPHeaderElement headerElement = null;
392        if(newChild instanceof SOAPHeaderElement)
393            headerElement = (SOAPHeaderElement)newChild;
394        else 
395            headerElement = new SOAPHeaderElement((Element)newChild);
396        try {
397            addChildElement(headerElement);
398        } catch (SOAPException e) {
399            throw new DOMException(DOMException.INVALID_STATE_ERR,e.toString());
400        }
401        return headerElement;
402    }

This works fine if the newChild Node parameter is an instance of SOAPHeaderElement or org.w3c.dom.Element, but any other subclass of Node will cause a ClassCastException to be thrown at line 395.

It's reasonable to expect that in most cases, the Node being appended to a SOAP Header will be DOM Element representing a header entry. However, there is no prohibition in the SOAP 1.1 Note or the SOAP 1.2 Recommendation against whitespace before, after, or in between the header entries of a SOAP Header. Some parsers will render such whitespace as Text nodes, which will cause a ClassCastException in the appendChild() method.

Even if a deliberate design decision has been made not to support whitespace in the SOAPHeader class, the appendChild(Node) method should probably do something more elegant than throw a ClassCastException if the Node parameter is a Text node containing whitespace.

-- 
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


[jira] Commented: (AXIS-2029) SOAPHeader.appendChild() throws unexpected ClassCastException

Posted by "Venkat Reddy (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXIS-2029?page=comments#action_66839 ]
     
Venkat Reddy commented on AXIS-2029:
------------------------------------

I think we should accept TextNode also as child for SOAPHeader block. Does anyone know why the NodeImpl.appendChild has been overridden?

SOAP 1.2 spec:
"Each SOAP header block element information item MAY have any number of character information item children. Child character information items whose character code is amongst the white space characters as defined by XML 1.0 are considered significant".

Seems it also applies for SOAPBody !
- venkat

> SOAPHeader.appendChild() throws unexpected ClassCastException
> -------------------------------------------------------------
>
>          Key: AXIS-2029
>          URL: http://issues.apache.org/jira/browse/AXIS-2029
>      Project: Axis
>         Type: Bug
>   Components: Basic Architecture, SAAJ
>     Versions: 1.2
>  Environment: Windows XP Pro/WebSphere 4.0
>     Reporter: Mark Tye
>  Attachments: 2029.diff
>
> The class org.apache.axis.message.SOAPHeader overrides the appendChild(org.w3c.dom.Node) method of org.apache.axis.message.NodeImpl in such a way that it breaks the contract of the org.3c.dom.Node.appendChild(org.w3c.dom.Node) interface.
> Here's the implementation of appendChild(Node) in SOAPHeader:
> 390    public Node appendChild(Node newChild) throws DOMException {
> 391        SOAPHeaderElement headerElement = null;
> 392        if(newChild instanceof SOAPHeaderElement)
> 393            headerElement = (SOAPHeaderElement)newChild;
> 394        else 
> 395            headerElement = new SOAPHeaderElement((Element)newChild);
> 396        try {
> 397            addChildElement(headerElement);
> 398        } catch (SOAPException e) {
> 399            throw new DOMException(DOMException.INVALID_STATE_ERR,e.toString());
> 400        }
> 401        return headerElement;
> 402    }
> This works fine if the newChild Node parameter is an instance of SOAPHeaderElement or org.w3c.dom.Element, but any other subclass of Node will cause a ClassCastException to be thrown at line 395.
> It's reasonable to expect that in most cases, the Node being appended to a SOAP Header will be DOM Element representing a header entry. However, there is no prohibition in the SOAP 1.1 Note or the SOAP 1.2 Recommendation against whitespace before, after, or in between the header entries of a SOAP Header. Some parsers will render such whitespace as Text nodes, which will cause a ClassCastException in the appendChild() method.
> Even if a deliberate design decision has been made not to support whitespace in the SOAPHeader class, the appendChild(Node) method should probably do something more elegant than throw a ClassCastException if the Node parameter is a Text node containing whitespace.

-- 
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


[jira] Commented: (AXIS-2029) SOAPHeader.appendChild() throws unexpected ClassCastException

Posted by "Venkat Reddy (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXIS-2029?page=comments#action_66958 ]
     
Venkat Reddy commented on AXIS-2029:
------------------------------------

Mark,
Thanks for the detailed clarification! Does the spec say that Header element can have or should process whitespace characters? Can't find anything on this.

- venkat



> SOAPHeader.appendChild() throws unexpected ClassCastException
> -------------------------------------------------------------
>
>          Key: AXIS-2029
>          URL: http://issues.apache.org/jira/browse/AXIS-2029
>      Project: Axis
>         Type: Bug
>   Components: Basic Architecture, SAAJ
>     Versions: 1.2
>  Environment: Windows XP Pro/WebSphere 4.0
>     Reporter: Mark Tye
>  Attachments: 2029.diff
>
> The class org.apache.axis.message.SOAPHeader overrides the appendChild(org.w3c.dom.Node) method of org.apache.axis.message.NodeImpl in such a way that it breaks the contract of the org.3c.dom.Node.appendChild(org.w3c.dom.Node) interface.
> Here's the implementation of appendChild(Node) in SOAPHeader:
> 390    public Node appendChild(Node newChild) throws DOMException {
> 391        SOAPHeaderElement headerElement = null;
> 392        if(newChild instanceof SOAPHeaderElement)
> 393            headerElement = (SOAPHeaderElement)newChild;
> 394        else 
> 395            headerElement = new SOAPHeaderElement((Element)newChild);
> 396        try {
> 397            addChildElement(headerElement);
> 398        } catch (SOAPException e) {
> 399            throw new DOMException(DOMException.INVALID_STATE_ERR,e.toString());
> 400        }
> 401        return headerElement;
> 402    }
> This works fine if the newChild Node parameter is an instance of SOAPHeaderElement or org.w3c.dom.Element, but any other subclass of Node will cause a ClassCastException to be thrown at line 395.
> It's reasonable to expect that in most cases, the Node being appended to a SOAP Header will be DOM Element representing a header entry. However, there is no prohibition in the SOAP 1.1 Note or the SOAP 1.2 Recommendation against whitespace before, after, or in between the header entries of a SOAP Header. Some parsers will render such whitespace as Text nodes, which will cause a ClassCastException in the appendChild() method.
> Even if a deliberate design decision has been made not to support whitespace in the SOAPHeader class, the appendChild(Node) method should probably do something more elegant than throw a ClassCastException if the Node parameter is a Text node containing whitespace.

-- 
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


[jira] Assigned: (AXIS-2029) SOAPHeader.appendChild() throws unexpected ClassCastException

Posted by "Davanum Srinivas (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXIS-2029?page=all ]

Davanum Srinivas reassigned AXIS-2029:
--------------------------------------

    Assign To: Ashutosh Shahi

> SOAPHeader.appendChild() throws unexpected ClassCastException
> -------------------------------------------------------------
>
>          Key: AXIS-2029
>          URL: http://issues.apache.org/jira/browse/AXIS-2029
>      Project: Axis
>         Type: Bug
>   Components: Basic Architecture, SAAJ
>     Versions: 1.2
>  Environment: Windows XP Pro/WebSphere 4.0
>     Reporter: Mark Tye
>     Assignee: Ashutosh Shahi
>  Attachments: 2029.diff
>
> The class org.apache.axis.message.SOAPHeader overrides the appendChild(org.w3c.dom.Node) method of org.apache.axis.message.NodeImpl in such a way that it breaks the contract of the org.3c.dom.Node.appendChild(org.w3c.dom.Node) interface.
> Here's the implementation of appendChild(Node) in SOAPHeader:
> 390    public Node appendChild(Node newChild) throws DOMException {
> 391        SOAPHeaderElement headerElement = null;
> 392        if(newChild instanceof SOAPHeaderElement)
> 393            headerElement = (SOAPHeaderElement)newChild;
> 394        else 
> 395            headerElement = new SOAPHeaderElement((Element)newChild);
> 396        try {
> 397            addChildElement(headerElement);
> 398        } catch (SOAPException e) {
> 399            throw new DOMException(DOMException.INVALID_STATE_ERR,e.toString());
> 400        }
> 401        return headerElement;
> 402    }
> This works fine if the newChild Node parameter is an instance of SOAPHeaderElement or org.w3c.dom.Element, but any other subclass of Node will cause a ClassCastException to be thrown at line 395.
> It's reasonable to expect that in most cases, the Node being appended to a SOAP Header will be DOM Element representing a header entry. However, there is no prohibition in the SOAP 1.1 Note or the SOAP 1.2 Recommendation against whitespace before, after, or in between the header entries of a SOAP Header. Some parsers will render such whitespace as Text nodes, which will cause a ClassCastException in the appendChild() method.
> Even if a deliberate design decision has been made not to support whitespace in the SOAPHeader class, the appendChild(Node) method should probably do something more elegant than throw a ClassCastException if the Node parameter is a Text node containing whitespace.

-- 
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


[jira] Commented: (AXIS-2029) SOAPHeader.appendChild() throws unexpected ClassCastException

Posted by "Mark Tye (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXIS-2029?page=comments#action_66946 ]
     
Mark Tye commented on AXIS-2029:
--------------------------------

The diff is a step in the right direction: it's certainly better to throw a DOMException with a meaningful error message than a totally unhelpful ClassCastException. However, it would probably make more sense to throw a SOAPException, since it's only within the context of SOAP that Header elements are prohibited from having text nodes as their immediate children. From a purely DOM perspective, it's perfectly legal to add a text node to the Header element.

However, I'm not sure that throwing an exception is always the right thing to do here. While the SOAP specs (and the javadoc comments of the javax.xml.soap.SOAPHeader interface) forbid the addition of Text node children to a SOAP Header element, that doesn't really address the whitespace issue I mentioned in my original comment.

For example, if you're using the SAAJ API to build the response envelope in a message-style service invocation (e.g. public void method(SOAPEnvelope req, SOAPEnvelope resp)) and you're using a parsed DOM tree or SAX events as input, you might be tempted, as I was, to use the SOAPElement.addTextNode(String) method to handle the character data the parser feeds you. That works just fine if the SOAPElement you're adding text to is an instance of SOAPHeaderElement, SOAPBodyElement, or even SOAPBody - and it *used* to work for instances of SOAPHeader under Axis 1.2 beta - but now it results in a ClassCastException. You get this exception even if the String you're trying to add contains only whitespace - which is perfectly legal in the context of a SOAP Header.

I suggest that the SOAPHeader.appendChild(Node) method should check to see if the node being appended is an instance of Text (or maybe CharacterData?). If it is, and the node contains only whitespace, no exception should be thrown. (Presumably, the whitespace can be safely ignored). 

An alternative might be to implement the addTextNode(String) method in SOAPHeader, overriding the generic implementation in MessageElement, and throw an exception if the parameter string contains non-whitespace characters. This would push the point of failure closer to source of the problem, which is generally a good design principle.

If you take the latter approach, you probably want to do the same thing for the Axis SOAPBody and SOAPEnvelope implementations, too.

(Regarding Venkat's comment about the SOAP 1.2 spec, I should point out that a SOAP header *block* element information item is not the same thing as the SOAP Header element information item itself - although that's anything but obvious at first glance. The sentence that Venkat references in section 5.2.1 allows the *children* of the SOAP Header to have character information, like so:

<SOAP-ENV:Header>
  <tns:element1>
    this text is permitted
  </tns:element1>
</SOAP-ENV:Header>

Whereas section 5.2 specifies that the immediate children of the SOAP Header *must* be elements, which would seem to disallow text such as this:

<SOAP-ENV:Header>
  this text is not permitted
</SOAP-ENV:Header>

The SOAP 1.1 spec says more or less the same thing, but without the fussy nomenclature.)

> SOAPHeader.appendChild() throws unexpected ClassCastException
> -------------------------------------------------------------
>
>          Key: AXIS-2029
>          URL: http://issues.apache.org/jira/browse/AXIS-2029
>      Project: Axis
>         Type: Bug
>   Components: Basic Architecture, SAAJ
>     Versions: 1.2
>  Environment: Windows XP Pro/WebSphere 4.0
>     Reporter: Mark Tye
>  Attachments: 2029.diff
>
> The class org.apache.axis.message.SOAPHeader overrides the appendChild(org.w3c.dom.Node) method of org.apache.axis.message.NodeImpl in such a way that it breaks the contract of the org.3c.dom.Node.appendChild(org.w3c.dom.Node) interface.
> Here's the implementation of appendChild(Node) in SOAPHeader:
> 390    public Node appendChild(Node newChild) throws DOMException {
> 391        SOAPHeaderElement headerElement = null;
> 392        if(newChild instanceof SOAPHeaderElement)
> 393            headerElement = (SOAPHeaderElement)newChild;
> 394        else 
> 395            headerElement = new SOAPHeaderElement((Element)newChild);
> 396        try {
> 397            addChildElement(headerElement);
> 398        } catch (SOAPException e) {
> 399            throw new DOMException(DOMException.INVALID_STATE_ERR,e.toString());
> 400        }
> 401        return headerElement;
> 402    }
> This works fine if the newChild Node parameter is an instance of SOAPHeaderElement or org.w3c.dom.Element, but any other subclass of Node will cause a ClassCastException to be thrown at line 395.
> It's reasonable to expect that in most cases, the Node being appended to a SOAP Header will be DOM Element representing a header entry. However, there is no prohibition in the SOAP 1.1 Note or the SOAP 1.2 Recommendation against whitespace before, after, or in between the header entries of a SOAP Header. Some parsers will render such whitespace as Text nodes, which will cause a ClassCastException in the appendChild() method.
> Even if a deliberate design decision has been made not to support whitespace in the SOAPHeader class, the appendChild(Node) method should probably do something more elegant than throw a ClassCastException if the Node parameter is a Text node containing whitespace.

-- 
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


[jira] Commented: (AXIS-2029) SOAPHeader.appendChild() throws unexpected ClassCastException

Posted by "Mark Tye (JIRA)" <ax...@ws.apache.org>.
    [ http://issues.apache.org/jira/browse/AXIS-2029?page=comments#action_12312975 ] 

Mark Tye commented on AXIS-2029:
--------------------------------

Venkat, to the best of my knowledge, the 1.1 version of the SOAP spec makes no mention of whitespace or how it should be processed. In the absence of any SOAP-specific rules regarding whitespace, I would assume that rules from the XML 1.0 specification would apply. Here's section 2.10 (White Space Handling) of the spec:

<xml-spec version="1.0">
In editing XML documents, it is often convenient to use "white space" (spaces, tabs, and blank lines) to set apart the markup for greater readability. Such white space is typically not intended for inclusion in the delivered version of the document. On the other hand, "significant" white space that should be preserved in the delivered version is common, for example in poetry and source code.

An XML processor MUST always pass all characters in a document that are not markup through to the application. A validating XML processor MUST also inform the application which of these characters constitute white space appearing in element content.
</xml-spec>

The SOAP 1.2 specification is considerably more explicit about the handling of whitespace. I think the rule that's most relevant to this situation is found in the 4th paragraph of section 5 (SOAP Message Construct):

<soap-spec version="1.2">
Element information items defined by this specification that only have element information items defined as allowable members of their [children] property can also have zero or more character information item children whose character code is amongst the white space characters as defined by XML 1.0 [XML 1.0]. Unless otherwise indicated, such character information items are considered insignificant.
</soap-spec>

Since the SOAP Header is defined in Section 5.2 as an element information item that only has element information items as its children, this would seem to indicate that it's indeed permissible for the Header element to contain whitespace. The main difference between this rule and the one you quoted in your previous comment is that in this case, the white space is *not* considered significant.

For both versions of the SOAP spec, the implication seems to be that it's OK to have whitespace in the SOAP Header, but such whitespace is insignificant, and should therefore be ignored. I think this supports my contention that the SOAPHeader.appendChild(Node) method shouldn't throw an Exception if the parameter is a Text node that contains only whitespace, but should be allowed (or maybe required?) to throw an exception if the Text node parameter contains any non-whitespace characters.


> SOAPHeader.appendChild() throws unexpected ClassCastException
> -------------------------------------------------------------
>
>          Key: AXIS-2029
>          URL: http://issues.apache.org/jira/browse/AXIS-2029
>      Project: Axis
>         Type: Bug
>   Components: Basic Architecture, SAAJ
>     Versions: 1.2
>  Environment: Windows XP Pro/WebSphere 4.0
>     Reporter: Mark Tye
>  Attachments: 2029.diff
>
> The class org.apache.axis.message.SOAPHeader overrides the appendChild(org.w3c.dom.Node) method of org.apache.axis.message.NodeImpl in such a way that it breaks the contract of the org.3c.dom.Node.appendChild(org.w3c.dom.Node) interface.
> Here's the implementation of appendChild(Node) in SOAPHeader:
> 390    public Node appendChild(Node newChild) throws DOMException {
> 391        SOAPHeaderElement headerElement = null;
> 392        if(newChild instanceof SOAPHeaderElement)
> 393            headerElement = (SOAPHeaderElement)newChild;
> 394        else 
> 395            headerElement = new SOAPHeaderElement((Element)newChild);
> 396        try {
> 397            addChildElement(headerElement);
> 398        } catch (SOAPException e) {
> 399            throw new DOMException(DOMException.INVALID_STATE_ERR,e.toString());
> 400        }
> 401        return headerElement;
> 402    }
> This works fine if the newChild Node parameter is an instance of SOAPHeaderElement or org.w3c.dom.Element, but any other subclass of Node will cause a ClassCastException to be thrown at line 395.
> It's reasonable to expect that in most cases, the Node being appended to a SOAP Header will be DOM Element representing a header entry. However, there is no prohibition in the SOAP 1.1 Note or the SOAP 1.2 Recommendation against whitespace before, after, or in between the header entries of a SOAP Header. Some parsers will render such whitespace as Text nodes, which will cause a ClassCastException in the appendChild() method.
> Even if a deliberate design decision has been made not to support whitespace in the SOAPHeader class, the appendChild(Node) method should probably do something more elegant than throw a ClassCastException if the Node parameter is a Text node containing whitespace.

-- 
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


[jira] Updated: (AXIS-2029) SOAPHeader.appendChild() throws unexpected ClassCastException

Posted by "Ashutosh Shahi (JIRA)" <ax...@ws.apache.org>.
     [ http://issues.apache.org/jira/browse/AXIS-2029?page=all ]

Ashutosh Shahi updated AXIS-2029:
---------------------------------

    Attachment: 2029.diff

A possible workaround to avoid the classcast exception. We can check to see if the type of Node is Element before casting, else throw DOMException. All-tests runs fine.
Ashutosh

> SOAPHeader.appendChild() throws unexpected ClassCastException
> -------------------------------------------------------------
>
>          Key: AXIS-2029
>          URL: http://issues.apache.org/jira/browse/AXIS-2029
>      Project: Axis
>         Type: Bug
>   Components: Basic Architecture, SAAJ
>     Versions: 1.2
>  Environment: Windows XP Pro/WebSphere 4.0
>     Reporter: Mark Tye
>  Attachments: 2029.diff
>
> The class org.apache.axis.message.SOAPHeader overrides the appendChild(org.w3c.dom.Node) method of org.apache.axis.message.NodeImpl in such a way that it breaks the contract of the org.3c.dom.Node.appendChild(org.w3c.dom.Node) interface.
> Here's the implementation of appendChild(Node) in SOAPHeader:
> 390    public Node appendChild(Node newChild) throws DOMException {
> 391        SOAPHeaderElement headerElement = null;
> 392        if(newChild instanceof SOAPHeaderElement)
> 393            headerElement = (SOAPHeaderElement)newChild;
> 394        else 
> 395            headerElement = new SOAPHeaderElement((Element)newChild);
> 396        try {
> 397            addChildElement(headerElement);
> 398        } catch (SOAPException e) {
> 399            throw new DOMException(DOMException.INVALID_STATE_ERR,e.toString());
> 400        }
> 401        return headerElement;
> 402    }
> This works fine if the newChild Node parameter is an instance of SOAPHeaderElement or org.w3c.dom.Element, but any other subclass of Node will cause a ClassCastException to be thrown at line 395.
> It's reasonable to expect that in most cases, the Node being appended to a SOAP Header will be DOM Element representing a header entry. However, there is no prohibition in the SOAP 1.1 Note or the SOAP 1.2 Recommendation against whitespace before, after, or in between the header entries of a SOAP Header. Some parsers will render such whitespace as Text nodes, which will cause a ClassCastException in the appendChild() method.
> Even if a deliberate design decision has been made not to support whitespace in the SOAPHeader class, the appendChild(Node) method should probably do something more elegant than throw a ClassCastException if the Node parameter is a Text node containing whitespace.

-- 
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