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 "Steve McDuff (JIRA)" <ax...@ws.apache.org> on 2006/11/03 18:03:22 UTC

[jira] Created: (AXIS-2586) Wrapped/Literal encoding and abstract parameters with arrays won't work.

Wrapped/Literal encoding and abstract parameters with arrays won't work.
------------------------------------------------------------------------

                 Key: AXIS-2586
                 URL: http://issues.apache.org/jira/browse/AXIS-2586
             Project: Apache Axis
          Issue Type: Bug
          Components: Serialization/Deserialization
    Affects Versions: 1.4
         Environment: Tomcat 5.5
Sun JRE 1.5.0.07
Windows XP SP2
            Reporter: Steve McDuff


I found a problem when passing abstract parameters with array fields to a method in Wrapped/Literal encoding:

Steps to reproduce
1 - create a base class that has an array field of itself.
2 - create a sub class that inherits from the base class
3 - create a service class to publish as a web service that uses the base class as a paramter for a public method
4 - use Java2WSDL to publish the service class using wrapped/literal encoding
5 - run the web services on a web server
6 - use WSDL2Java to create stubs for a test client
7 - use the test client to call the method on the service class with a Sub Class instance.
8 - notice that the call to the service fails with the error : org.xml.sax.SAXException: Invalid element in BaseClass - item

Here are the code samples:

class BaseClass{
    private BaseClass[] childArray;
    public BaseClass[] getChildArray(){
        return childArray;
    }
    public void setChildArray(BaseClass[] childArray){
        this.childArray = childArray;
    } 
}

class SubClass extends BaseClass{
    private BaseClass[] otherChildArray;
    public BaseClass[] getOtherChildArray(){
        return otherChildArray;
    }
    public void setOtherChildArray(BaseClass[] otherChildArray){
        this.otherChildArray = otherChildArray;
    } 
}

// Use Java2WSDL to publish this as a web service
class MyTestInterface{
    // send and return the same base class parameter
    public BaseClass sendBase(BaseClass base){
        return base;
    }
    // this method just declares sub to make sure it finds its
    // way in the WSDL
    public void declareSub(SubClass sub){};
}

// client unit test code
class MyTest extends junit.framework.TestCase{
    public void testSendBase(){
        // Insert code to resolve URL and locate the web services here
        MyTestInterface x = null;
        SubClass sendSubClass = new SubClass();
        sendSubClass.setChildArray(new BaseClass[]{new SubClass()});
        // this call will fail with the message
        // org.xml.sax.SAXException: Invalid element in BaseClass - item
        BaseClass retVal = x.sendBase(sendSubClass);
        assertEquals(sendSubClass, retVal);
    }
}

Note:
- This problem is reproducible in Document/Literal
- This problem is not reproducible in RPC/Encoded 


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


[jira] Commented: (AXIS-2586) Wrapped/Literal encoding and abstract parameters with arrays won't work.

Posted by "Steve McDuff (JIRA)" <ax...@ws.apache.org>.
    [ http://issues.apache.org/jira/browse/AXIS-2586?page=comments#action_12447199 ] 
            
Steve McDuff commented on AXIS-2586:
------------------------------------

Possible solution identified: 

In the class : org.apache.axis.encoding.ser.BeanDeserializer.  
Problem: getDeserializer wasn't getting the right deserializer for array types when the xmlType is set.
Solution: apply the default XML Type when we are getting an array deserializer

I modified the following method (see method comments to know where changes were applied).

    protected Deserializer getDeserializer(QName xmlType, 
                                           Class javaType, 
                                           String href,
                                           DeserializationContext context) {
        if (javaType.isArray()) {
            context.setDestinationClass(javaType);
        } 
        // See if we have a cached deserializer
        if (cacheStringDSer != null) {
            if (String.class.equals(javaType) &&
                href == null &&
                (cacheXMLType == null && xmlType == null ||
                 cacheXMLType != null && cacheXMLType.equals(xmlType))) {
                cacheStringDSer.reset();
                return cacheStringDSer;
            }
        }
        
        Deserializer dSer = null;

        // MODIFICATION DONE HERE : Added the "&& ! javatype.isArray()" part in the line below
        if (xmlType != null && href == null && ! javatype.isArray() ) {
            // Use the xmlType to get the deserializer.
            dSer = context.getDeserializerForType(xmlType);
        } else {
            // If the xmlType is not set, get a default xmlType
            TypeMapping tm = context.getTypeMapping();
            QName defaultXMLType = tm.getTypeQName(javaType);
            // If there is not href, then get the deserializer
            // using the javaType and default XMLType,
            // If there is an href, the create the generic
            // DeserializerImpl and set its default type (the
            // default type is used if the href'd element does 
            // not have an xsi:type.
            if (href == null) {
                dSer = context.getDeserializer(javaType, defaultXMLType);
            } else {
                dSer = new DeserializerImpl();
                context.setDestinationClass(javaType);
                dSer.setDefaultType(defaultXMLType);
            }
        }
        if (javaType.equals(String.class) &&
            dSer instanceof SimpleDeserializer) {
            cacheStringDSer = (SimpleDeserializer) dSer;
            cacheXMLType = xmlType;
        }
        return dSer;
    }




Note: The source problem seems to be that the client sends its arrays identified with types when special conditions are met.

Here are 2 SOAP messages sent. One uses a BaseClass as a root parameter, the other uses a SubClass.

SOAP using baseclass:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<sendParent xmlns="http://text.com">
<x>
<childs>
<item xmlns:ns1="http://text.com" xsi:type="ns1:ChildInherit">
<ns1:childs>
<ns1:item xsi:type="ns1:ChildInherit">
<ns1:childs xsi:nil="true"/>
</ns1:item>
</ns1:childs>
</item>
</childs>
</x>
</sendParent>
</soapenv:Body>
</soapenv:Envelope>

SOAP using subclass:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<sendParent xmlns="http://text.com">
<x xmlns:ns1="http://text.com" xsi:type="ns1:ParentInherit">
<ns1:childs xsi:type="ns1:Child">
<ns1:item xsi:type="ns1:ChildInherit">
<ns1:childs xsi:type="ns1:Child">
<ns1:item xsi:type="ns1:ChildInherit">
<ns1:childs xsi:nil="true" xsi:type="ns1:Child"/>
</ns1:item>
</ns1:childs>
</ns1:item>
</ns1:childs>
</x>
</sendParent>
</soapenv:Body>
</soapenv:Envelope>


Notice that by using a subclass, all the arrays in the XML get tagged with "xsi:type". It is even applied to arrays that are deeper down the object hierarchy.

Conclusion:
- The fix I applied above is not the problem source, but it works as a failsafe for the server side.
- The client serializer should be fixed not to tag "xsi:type" on arrays.


> Wrapped/Literal encoding and abstract parameters with arrays won't work.
> ------------------------------------------------------------------------
>
>                 Key: AXIS-2586
>                 URL: http://issues.apache.org/jira/browse/AXIS-2586
>             Project: Apache Axis
>          Issue Type: Bug
>          Components: Serialization/Deserialization
>    Affects Versions: 1.4
>         Environment: Tomcat 5.5
> Sun JRE 1.5.0.07
> Windows XP SP2
>            Reporter: Steve McDuff
>
> I found a problem when passing abstract parameters with array fields to a method in Wrapped/Literal encoding:
> Steps to reproduce
> 1 - create a base class that has an array field of itself.
> 2 - create a sub class that inherits from the base class
> 3 - create a service class to publish as a web service that uses the base class as a paramter for a public method
> 4 - use Java2WSDL to publish the service class using wrapped/literal encoding
> 5 - run the web services on a web server
> 6 - use WSDL2Java to create stubs for a test client
> 7 - use the test client to call the method on the service class with a Sub Class instance.
> 8 - notice that the call to the service fails with the error : org.xml.sax.SAXException: Invalid element in BaseClass - item
> Here are the code samples:
> class BaseClass{
>     private BaseClass[] childArray;
>     public BaseClass[] getChildArray(){
>         return childArray;
>     }
>     public void setChildArray(BaseClass[] childArray){
>         this.childArray = childArray;
>     } 
> }
> class SubClass extends BaseClass{
>     private BaseClass[] otherChildArray;
>     public BaseClass[] getOtherChildArray(){
>         return otherChildArray;
>     }
>     public void setOtherChildArray(BaseClass[] otherChildArray){
>         this.otherChildArray = otherChildArray;
>     } 
> }
> // Use Java2WSDL to publish this as a web service
> class MyTestInterface{
>     // send and return the same base class parameter
>     public BaseClass sendBase(BaseClass base){
>         return base;
>     }
>     // this method just declares sub to make sure it finds its
>     // way in the WSDL
>     public void declareSub(SubClass sub){};
> }
> // client unit test code
> class MyTest extends junit.framework.TestCase{
>     public void testSendBase(){
>         // Insert code to resolve URL and locate the web services here
>         MyTestInterface x = null;
>         SubClass sendSubClass = new SubClass();
>         sendSubClass.setChildArray(new BaseClass[]{new SubClass()});
>         // this call will fail with the message
>         // org.xml.sax.SAXException: Invalid element in BaseClass - item
>         BaseClass retVal = x.sendBase(sendSubClass);
>         assertEquals(sendSubClass, retVal);
>     }
> }
> Note:
> - This problem is reproducible in Document/Literal
> - This problem is not reproducible in RPC/Encoded 

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