I'm new to webservices and Axis and I'm trying to solve a problem which seems 
like it would be a fairly common one. I have some EJBs that I am wanting to 
expose to clients via webservices rather than using RMI for various reasons.  
I'm trying to use Axis but am running into some trouble.  The problem is that 
several of the EJBs return large arrays of complex objects (10,000+).  Even if 
serializers/deserializers are written for the complex objects, the amount of 
XML required to describe each one (and that is identical for each element) 
makes the size of the SOAP message too large (ex. ~600 KB byte array using RMI 
becomes ~4 MB with SOAP, and ~1 sec vs. ~5 min processing time).  

My question is:  
What is the best way to handle large arrays of complex objects using Axis?

Here's a snippet from the SOAP envelope for one of the elements of my arrays:

<multiRef id="id10" soapenc:root="0" 
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"; 
xsi:type="ns7:MemberDTO" xmlns:ns7="http://model.client.odcs.solutions.sas.com"; 
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/";> 
<data 
xsi:type="xsd:string">Code_10;/;.;/;.;/;-240,11766,1,true,false,.,0,1</data> 
</multiRef>

The only things that differ in the XML for this object and the other 9,999+ are 
the id value and the <data> value.  The rest of the text is repeated 9,999+ 
times and is the main reason the message size is so large.

I decided to try serializing and deserializing my object arrays as single 
objects to avoid the redundant text.   For example, I registered type mappings 
for both the MemberDTO object and the MemberDTO array in my client-config.wsdd 
and server-config.wsdd files as follows:

 <typeMapping qname="ns:MemberDTO" 
xmlns:ns="http://model.client.odcs.solutions.sas.com"; 
languageSpecificType="java:com.sas.solutions.odcs.client.model.MemberDTO" 
serializer="com.sas.solutions.odcs.client.services.axis.encoding.CommonSerializerFactory"
 
deserializer="com.sas.solutions.odcs.client.services.axis.encoding.CommonDeserializerFactory"/>

 <typeMapping qname="ns:MemberDTO;" 
xmlns:ns="http://model.client.odcs.solutions.sas.com"; 
languageSpecificType="java:com.sas.solutions.odcs.client.model.MemberDTO[]" 
serializer="com.sas.solutions.odcs.client.services.axis.encoding.CommonSerializerFactory"
 
deserializer="com.sas.solutions.odcs.client.services.axis.encoding.CommonDeserializerFactory"/>

I found, however, that using custom serializers/deserializers for arrays as 
objects runs into problems when using them for method parameters.  If a method 
is overloaded such that at least 2 of the methods have the same number of 
parameters it's possible that Axis can't match the correct operation 
description with the SOAP XML.  When Axis is wanting to deserialize some XML 
for a method the list of possible operation descriptions based on the service's 
wsdl are retrieved (matched by method name and number of parameters).  If there 
are more than one operations that match, the code tries to deserialize the XML 
using each operation until one works.  The problem happens when the operation 
that uses a custom serializer comes second or later in the list of operation 
descriptions.  The code tries to find a deserializer for the parameters based 
on javaType from the operation description and the xmlType from the XML.   If 
the javaType is a normal array (ex. String[]) and the xmlType is a
custom type (ex. MemberDTO;) no mapping is found for that pair.  Since the 
javaType is an array Axis defaults to ArrayDeserializer.  This would be fine, 
except for the fact that ArrayDeserializer has the following code where 
RuntimeExceptions are caught and ignored prohibiting the operation matching 
code to detect the error:

    public void valueComplete() throws SAXException
    { 
        if (componentsReady()) {
           try {
                if (arrayClass != null) {
                    value = JavaUtils.convert(value, arrayClass);
                } 
           } catch (RuntimeException e) {
               // We must ignore exceptions from convert for Arrays with null - 
why?
           }
        }     
        
        super.valueComplete();
    }

When JavaUtils.convert() is called with a value for "MemberDTO;" and an array 
class of "String[]" an ArrayStoreException results.  Since this exception is 
caught and not handled, the code matching the operation descriptions never sees 
the problem and thinks that the operation matches.  The code does not check the 
remaining operations and the real operation is never matched.  Later when the 
XML is actually deserialized the ArrayStoreException occurs again and the 
service fails to deserialize the object.  To get around this problem I simply 
change the method names so that they are not overloaded.  Would this problem be 
considered a bug (seems like you never really want to catch RuntimeException 
and ignore right)?  Or is what I'm doing wrong and no one should 
serialize/deserialize arrays as single objects?  I've tried this using 1.2.1 
and 1.4 and they both exhibit the same problem.  

It really goes back to my original question which is what is the best way to 
handle large arrays to avoid the redundant XML for each array element?  It 
seems like this would be a common problem for real-world applications.

Any help or direction would be greatly appreciated.

-Ryan



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to