Axis
  1. Axis
  2. AXIS-2421

incorrect Bean deserialisation - deserialised object's constructor invoked with incorrect argument values - axis seems to confuse types

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 1.3
    • Fix Version/s: None
    • Labels:
      None
    • Environment:
      Client on Windows XP Pro, Server (Tomcat and Axis) on RedHat Linux

      Description

      Problem:

      • transmitting a simple object via SOAP
      • object has 4 attributes, two "long" values, one "int" value and one Java String value
      • problem is with deserialisation of longs
      • object's constructor is invoked with the first long's value for both long parameters
      • 2nd long's value is never used
      • problem seems to be in org.apache.axis.encoding.ConstructorTarget.java line 88
      • args[c] = values.get causes the first value of a type to be returned, regardless of whether or not ir was returned already
      • fix implemented by replacing above line with:
        args[c] = values.remove;
      • not sure of the wider implications of this fix, however.

      /*

      • Some client code to test this
        */

      package soaptest;

      import org.apache.axis.client.Call;
      import org.apache.axis.client.Service;
      import javax.xml.namespace.QName;

      public class ProfileClient {
      public static void main(String[] args) {
      try {
      String endpoint = "http://localhost:8087/axis/services/ProfileService";

      Service service = new Service();
      Call call = (Call) service.createCall();

      call.setTargetEndpointAddress(new java.net.URL(endpoint));
      call.setOperationName(new QName("http://soapinterop.org", "addSubscriber"));

      call.registerTypeMapping(java.lang.Class.forName("soaptest.Subscriber"), new QName("Subscriber"), new org.apache.axis.encoding.ser.BeanSerializerFactory(java.lang.Class.forName("soaptest.Subscriber"), new QName("Subscriber")), new org.apache.axis.encoding.ser.BeanDeserializerFactory(java.lang.Class.forName("soaptest.Subscriber"), new QName("Subscriber")));

      Subscriber sub = new Subscriber (555555, 358408, 1, "jussi@sonera.fi");
      System.out.println("About to invoke..." + sub.toString());
      call.invoke(new Object[]

      {sub}

      );
      }
      catch (java.rmi.RemoteException ex)

      { System.err.println("Problem with remote connection: " + ex.toString()); }

      catch (Exception ex)

      { System.err.println("Problem executing client: " + ex.toString()); }

      }
      }

      /*

      • This class should be on client and server
      • /

      package soaptest;

      public class Subscriber implements java.io.Serializable {
      public Subscriber(long imsi, long msisdn, int operator, String URI)

      { myIMSI = imsi; myMSISDN = msisdn; myOperator = operator; myURI = URI; }

      public long getIMSI()

      { System.out.println("Subscriber.getIMSI(): returning " + myIMSI); return myIMSI; }

      public long getMSISDN()

      { System.out.println("Subscriber.getMSISDN(): returning " + myMSISDN); return myMSISDN; }

      public int getOperator()

      { System.out.println("Subscriber.getOperator(): returning " + myOperator); return myOperator; }

      public String getURI()

      { System.out.println("Subscriber.getURI(): returning " + myURI); return myURI; }

      public void setIMSI(long imsi)

      { myIMSI = imsi; }

      public void setMSISDN(long msisdn)

      { myMSISDN = msisdn; }

      public void setOperator(int operator)

      { myOperator = operator; }

      public void setURI(String uri)

      { myURI = uri; }

      public String toString()

      { return "IMSI: " + myIMSI + ", MSISDN: " + myMSISDN + ", operator: " + myOperator + ", URI: " + myURI; }

      private long myIMSI;
      private long myMSISDN;
      private int myOperator;
      private String myURI;
      }
      /*

      • this should be deployed as a web service
        */

      package soaptest;

      import java.util.*;

      public class ProfileAccess {
      public ProfileAccess()

      { System.err.println("Starting"); }

      public void addSubscriber(Subscriber sub)

      { System.err.println("The subscriber being added is " + sub.toString()); }

      }

        Activity

        Hide
        Nate Franzen added a comment -

        The problem is clearly there in axis 1.4 as well,

        There's a block of code axis/encoding/ConstructorTarget.java

        // Get arg for the type of the class
        for (int c = 0; c < classes.length; c++) {
        boolean found = false;
        int i = 0;
        while (!found && i < values.size()) {
        // got right class arg
        --> if (values.get.getClass().getName().toLowerCase().indexOf(classes[c].getName().toLowerCase()) != -1)

        { found = true; args[c] = values.get(i); }

        i++;

        where it just optimistically picks the first argument of matching type. If the constructor takes two strings as parameters, then it is called with (string1, string1). Nothing fails, it just corrupts the deserialized object. Oops.

        Show
        Nate Franzen added a comment - The problem is clearly there in axis 1.4 as well, There's a block of code axis/encoding/ConstructorTarget.java // Get arg for the type of the class for (int c = 0; c < classes.length; c++) { boolean found = false; int i = 0; while (!found && i < values.size()) { // got right class arg --> if (values.get .getClass().getName().toLowerCase().indexOf(classes [c] .getName().toLowerCase()) != -1) { found = true; args[c] = values.get(i); } i++; where it just optimistically picks the first argument of matching type. If the constructor takes two strings as parameters, then it is called with (string1, string1). Nothing fails, it just corrupts the deserialized object. Oops.
        Hide
        Agnes Ro added a comment -

        Hi. Is there a patch for this? This is a big issue for us atm..

        Agnes.

        Show
        Agnes Ro added a comment - Hi. Is there a patch for this? This is a big issue for us atm.. Agnes.
        Hide
        Agnes Ro added a comment -

        One more thing, is this issue in 1.2 as well?

        Agnes.

        Show
        Agnes Ro added a comment - One more thing, is this issue in 1.2 as well? Agnes.
        Hide
        Rob Allen added a comment -

        This is how we worked around this issue...

        // got right class arg
        if (values.get.getClass().getName().toLowerCase().indexOf(classes[c].getName().toLowerCase()) != -1)

        { found = true; args[c] = values.get(i); values.remove(i); // ADD THIS LINE }

        I should mention that I don't know whether this is a guaranteed fix as I'm not sure whether the first argument in the "values" list will always map to the first value of the args[] array. The order was correct in each case I saw while running in the debugger.

        Show
        Rob Allen added a comment - This is how we worked around this issue... // got right class arg if (values.get .getClass().getName().toLowerCase().indexOf(classes [c] .getName().toLowerCase()) != -1) { found = true; args[c] = values.get(i); values.remove(i); // ADD THIS LINE } I should mention that I don't know whether this is a guaranteed fix as I'm not sure whether the first argument in the "values" list will always map to the first value of the args[] array. The order was correct in each case I saw while running in the debugger.

          People

          • Assignee:
            Unassigned
            Reporter:
            gareth smith
          • Votes:
            2 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:

              Development