Glen addressed a similar issue on axis-user today. The deserialization engine always deserializes arrays into ArrayList objects.
Rich Scheuerle XML & Web Services Development 512-838-5115 (IBM TL 678-5115) "David L. Cole" <DLCole@cmsenergy To: [EMAIL PROTECTED] .com> cc: [EMAIL PROTECTED] Subject: Deserialization issue 02/08/2002 11:27 AM Please respond to axis-dev Hi all, Has anybody noticed an anonymoly occurring as follows: I have the following 2 test classes (simplified here for brevity) public class DataWrapper { private HashMap storage; //Primary object storage private long startTime; //Used to store an arbitrary start time private long endTime; //Used to store an arbitrary end time } public class User { private long userID; private String userName; private String password; } I also have a stateless session bean which contains the following method: public DataWrapper timedGetAllUsers() { long startTime = System.currentTimeMillis(); User[] users = getAllUsers(); DataWrapper wrapper = new DataWrapper(new HashMap(users.length)); wrapper.setStartTime(startTime); if(users != null) { HashMap map = new HashMap(); map.put("users",users); wrapper.setStorage(map); } wrapper.setEndTime(System.currentTimeMillis()); return wrapper; } NOTE: Notice that in the above method we add a User[] with the key "users" to a HashMap and then set the storage attribute to the new HashMap inside the DataWrapper class. On my client app (a Swing client) I execute the method using Axis in the following manner: private DataWrapper getAllUsersUsingAxisSoap() { DataWrapper retVal = null; org.apache.axis.client.Service service = null ; org.apache.axis.client.Call call = null ; try { service = new org.apache.axis.client.Service(); call = (org.apache.axis.client.Call) service.createCall(); } catch(Exception t) { t.printStackTrace(); } try { Class cls = com.itemxchange.users.data.User.class; Class wrapperClass = com.itemxchange.util.data.DataWrapper.class; java.net.URL endpointURL = new java.net.URL ("http://localhost:7001/axis/servlet/AxisServlet"); call.setTargetEndpointAddress( endpointURL ); call.setProperty(org.apache.axis.transport.http.HTTPTransport.URL, endpointURL.toString()); if (call.getProperty(org.apache.axis.transport.http.HTTPTransport.URL) == null) { throw new org.apache.axis.NoEndPointException(); } call.removeAllParameters(); call.setReturnType(new org.apache.axis.encoding.XMLType(new javax.xml.rpc.namespace.QName ("http://schemas.xmlsoap.org/soap/encoding/", "DataWrapper"))); // set the namespace and serializer/deserializer for the user object and DataWrapper classes org.apache.axis.encoding.BeanSerializer beanSerial = new org.apache.axis.encoding.BeanSerializer(cls); org.apache.axis.encoding.BeanSerializer wrapperBeanSerial = new org.apache.axis.encoding.BeanSerializer(wrapperClass); javax.xml.rpc.namespace.QName qn = new javax.xml.rpc.namespace.QName("urn:UserManagerEJB", "user"); javax.xml.rpc.namespace.QName wrapperQN = new javax.xml.rpc.namespace.QName("urn:UserManagerEJB", "DataWrapper"); call.addDeserializerFactory(wrapperQN, wrapperClass, wrapperBeanSerial.getFactory()); call.addDeserializerFactory(qn, cls, beanSerial.getFactory()); call.setProperty(org.apache.axis.transport.http.HTTPTransport.ACTION, ""); call.setProperty(call.NAMESPACE, "UserManager"); call.setOperationName( "timedGetAllUsers"); Object resp = null; try { resp = call.invoke(new Object[] {}); } catch(Exception e) { log("Caught exception during call.invoke()"); e.printStackTrace(); } if (resp instanceof java.rmi.RemoteException) { ((java.rmi.RemoteException)resp).printStackTrace(); throw (java.rmi.RemoteException)resp; } else { try { retVal = (DataWrapper)org.apache.axis.utils.JavaUtils.convert(resp,DataWrapper.class); } catch(Exception e) { log("Caught exception during convert."); e.printStackTrace(); } } } catch(Exception e) { e.printStackTrace(); } return retVal; } And here is the DD: <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <service name="UserManager" provider="java:RPC"> <parameter name="className" value="com.itemxchange.users.ejb.UserManagerEJB"/> <parameter name="methodName" value="*"/> <beanMapping qname="ns:user" xmlns:ns="urn:UserManagerEJB" languageSpecificType ="java:com.itemxchange.users.data.User"/> <beanMapping qname="ns:DataWrapper" xmlns:ns="urn:UserManagerEJB" languageSpecificType ="java:com.itemxchange.util.data.DataWrapper"/> </service> </deployment> The problem which occurs is after the call returns successfully, the DataWrapper object's storage HashMap should have an array of Users (User[]) stored inside for the key "users". Instead of a User[], the value for "users" has come back as an ArrayList. Here is the method used to extract the User[] from the DataWrapper object: private User[] getUserArrayFromWrapper(DataWrapper wrapper) { User[] usersArray = null; HashMap map = wrapper.getStorage(); //Pull out the Users[] as an Object by the key 'users' Object usersArrayObject = null; if(map != null) { usersArrayObject = map.get("users"); if(usersArrayObject != null) { log("getUserArrayFromWrapper: usersArrayObject class: "+ usersArrayObject.getClass().getName()); } else { log("getUserArrayFromWrapper: usersArrayObject is NULL!"); log("getUserArrayFromWrapper: contents of Storage Map: " + map); } } else { log("getUserArrayFromWrapper: Storage Map is NULL!"); } //If the protocol was Apache-Axis, the usersArrayObject will be returned //internally as an ArrayList, else it will be simply a User[] as expected //If the protocol is Apache-Soap2.0 or Weblogic SOAP or RMI, the usersArrayObject //will be the User[] as expected. if(usersArrayObject instanceof ArrayList) { usersArray = (User[])((ArrayList)usersArrayObject).toArray(new User[0]); } else { usersArray = (User[])usersArrayObject; } return usersArray; } I am guessing that this is simply an oversight. Upon getting the object out of the HashMap, I am having to cast it to an ArrayList and subsequently call the toArray() method on the ArrayList to get the expected User[]. Any comments and/or suggestions? Thanks, David Cole