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 sc...@apache.org on 2002/03/06 20:35:50 UTC

cvs commit: xml-axis/java/test/wsdl/roundtrip BondInvestment.java RoundtripTestServiceTestCase.java RoundtripTestSoapBindingImpl.java

scheu       02/03/06 11:35:50

  Modified:    java/src/org/apache/axis/encoding
                        DeserializationContextImpl.java Deserializer.java
                        DeserializerImpl.java SerializationContext.java
               java/src/org/apache/axis/encoding/ser ArrayDeserializer.java
                        BeanDeserializer.java BeanSerializer.java
                        MapDeserializer.java
               java/test/wsdl/interop3/groupE List.java
               java/test/wsdl/roundtrip BondInvestment.java
                        RoundtripTestServiceTestCase.java
                        RoundtripTestSoapBindingImpl.java
  Log:
  The type data received off the wire should be used to load a Deserializer.
  However both the BeanDeserializer and ArrayDeserializer were using
  the java class type of the property/array element to construct a Deserializer.
  This works fine if the java class and xml instance data have the same type,
  but does not work at all if the xml instance data is a derived type.
  
  For example consider a Bean with a property Foo that is an Object.
  The old code would attempt to find a Deserializer for Object when a Foo
  is received off the wire...and fail.  The new code will now use the xml type information
  to determine the Deserializer.
  
  So I changed the code in the ArrayDeserializer and BeanDeserializer to
  use the xml instance type information to get the Deserializer for contained items.
  This change revealed another problem.  If the contained item has an href, there is no
  type information; thus a generic DeserializerImpl object is used....The href/id
  processing breaks when the DeserializerImpl has value targets.
  
  Here are some of the additional changes that I made:
  
    1) Changed the code so that value targets are moved (instead of copied) when
       deserializer fixups are applied.  This is necessary to ensure that only one
       set(..) is invoked per value, and that it is invoked on the correct value.
       This is also a small performance improvement.
  
    2) For the case of array elements, if an array element definition does not have
       a type attribute, its type can be assumed from the array's arrayType setting.
       Consider the situation where the array has an arrayType of "Foo[]", and the
       first element of the array is an href and does not have a type attribute.
       The array deserializer will construct a generic DeserializerImpl for
       the contained array element.  The new setDefaultType(..) method of the
       DeserializerImpl object will be used to indicate that the "Foo" deserializer
       should be used if the definition of the array element
       does not have a type attribute.
  
    3) Changed the roundtrip test to test this new code.
  
    4) Changed BeanSerializer.writeSchema to use a sequence group instead of
       all group. (Per note from Dave Dunkin)
  
  (This problem was reported by Thomas Sandholm on axis-user)
  
  Revision  Changes    Path
  1.14      +7 -3      xml-axis/java/src/org/apache/axis/encoding/DeserializationContextImpl.java
  
  Index: DeserializationContextImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/DeserializationContextImpl.java,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- DeserializationContextImpl.java	27 Feb 2002 15:50:11 -0000	1.13
  +++ DeserializationContextImpl.java	6 Mar 2002 19:35:49 -0000	1.14
  @@ -532,10 +532,14 @@
   
           // There could already be a deserializer in the fixup list
           // for this href.  If so, the easiest way to get all of the
  -        // targets updated is to copy the previous deserializers 
  +        // targets updated is to move the previous deserializers 
           // targets to dser.
  -        if (prev != null && prev != dser)
  -            dser.copyValueTargets(prev);
  +        if (prev != null && prev != dser) {
  +            dser.moveValueTargets(prev);
  +            if (dser.getDefaultType() == null) {
  +                dser.setDefaultType(prev.getDefaultType());
  +            }
  +        }
       }
       
       /**
  
  
  
  1.29      +19 -2     xml-axis/java/src/org/apache/axis/encoding/Deserializer.java
  
  Index: Deserializer.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/Deserializer.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- Deserializer.java	26 Jan 2002 02:40:33 -0000	1.28
  +++ Deserializer.java	6 Mar 2002 19:35:49 -0000	1.29
  @@ -134,6 +134,18 @@
        */
       public void setValue(Object value, Object hint) throws SAXException;
   
  +   /**
  +     * In some circumstances an element may not have 
  +     * a type attribute, but a default type qname is known from
  +     * information in the container.  For example,
  +     * an element of an array may not have a type= attribute, 
  +     * so the default qname is the component type of the array.
  +     * This method is used to communicate the default type information 
  +     * to the deserializer.
  +     */
  +    public void setDefaultType(QName qName);
  +    public QName getDefaultType();
  +
       /**
        * For deserializers of non-primitives, the value may not be
        * known until later (due to multi-referencing).  In such
  @@ -152,8 +164,13 @@
        */
       public Vector getValueTargets();
   
  +    /**
  +     * Remove the Value Targets of the Deserializer.
  +     */
  +    public void removeValueTargets() ;
  +
      /**
  -     * Add someone else's targets to our own (see DeserializationContext)
  +     * Move someone else's targets to our own (see DeserializationContext)
        *
        * The DeserializationContext only allows one Deserializer to  
        * wait for a unknown multi-ref'ed value.  So to ensure
  @@ -161,7 +178,7 @@
        * to copy the Target objects to the waiting Deserializer.
        * @param other is the Deserializer to copy targets from.
        */
  -    public void copyValueTargets(Deserializer other);
  +    public void moveValueTargets(Deserializer other);
   
       /**
        * Some deserializers (ArrayDeserializer) require
  
  
  
  1.5       +54 -11    xml-axis/java/src/org/apache/axis/encoding/DeserializerImpl.java
  
  Index: DeserializerImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/DeserializerImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- DeserializerImpl.java	22 Feb 2002 23:39:44 -0000	1.4
  +++ DeserializerImpl.java	6 Mar 2002 19:35:49 -0000	1.5
  @@ -96,6 +96,9 @@
   
       protected Vector targets = null;
   
  +    protected QName defaultType = null;
  +
  +
       /** 
        * JAX-RPC compliant method which returns mechanism type.
        */
  @@ -142,6 +145,22 @@
       }
   
       /**
  +     * In some circumstances an element may not have 
  +     * a type attribute, but a default type qname is known from
  +     * information in the container.  For example,
  +     * an element of an array may not have a type= attribute, 
  +     * so the default qname is the component type of the array.
  +     * This method is used to communicate the default type information 
  +     * to the deserializer.
  +     */
  +    public void setDefaultType(QName qName) {
  +        defaultType = qName;
  +    }
  +    public QName getDefaultType() {
  +        return defaultType;
  +    }
  +
  +    /**
        * For deserializers of non-primitives, the value may not be
        * known until later (due to multi-referencing).  In such
        * cases the deserializer registers Target object(s).  When
  @@ -168,7 +187,17 @@
       }
       
       /**
  -     * Add someone else's targets to our own (see DeserializationContext)
  +     * Remove the Value Targets of the Deserializer.
  +     */
  +    public void removeValueTargets() {
  +        if (targets != null) {
  +            targets.clear();
  +            targets = null;
  +        }
  +    }
  +
  +    /**
  +     * Move someone else's targets to our own (see DeserializationContext)
        *
        * The DeserializationContext only allows one Deserializer to  
        * wait for a unknown multi-ref'ed value.  So to ensure
  @@ -176,7 +205,7 @@
        * to copy the Target objects to the waiting Deserializer.
        * @param other is the Deserializer to copy targets from.
        */
  -    public void copyValueTargets(Deserializer other)
  +    public void moveValueTargets(Deserializer other)
       {
           if ((other == null) || (other.getValueTargets() == null))
               return;
  @@ -188,6 +217,7 @@
           while (e.hasMoreElements()) {
               targets.addElement(e.nextElement());
           }
  +        other.removeValueTargets();
       }
       
       /**
  @@ -231,8 +261,7 @@
                       }
                   }
                   // Don't need targets any more, so clear them
  -                targets.clear();
  -                targets = null;
  +                removeValueTargets();
               }
           }
       }
  @@ -303,13 +332,14 @@
           // point will cause an infinite loop during deserialization if the 
           // current element contains child elements that cause an href back to this id.)
           // Also note that that endElement() method is responsible for the final
  -        // assoication of this id with the completed value.
  +        // association of this id with the completed value.
           id = attributes.getValue("id");
           if (id != null) {
               context.addObjectById(id, value);
               if (log.isDebugEnabled()) {
                   log.debug(JavaUtils.getMessage("deserInitPutValueDebug00", "" + value, id));
  -            }     
  +            }
  +            context.registerFixup("#" + id, this);
           }
   
           String href = attributes.getValue("href");
  @@ -372,6 +402,14 @@
               QName type = context.getTypeFromAttributes(namespace,
                                                          localName,
                                                          attributes);
  +            // If no type is specified, use the defaultType if available.
  +            // xsd:string is used if no type is provided.
  +            if (type == null) {
  +                type = defaultType;
  +                if (type == null) {
  +                    type = Constants.XSD_STRING;
  +                }
  +            }
               
               if (log.isDebugEnabled()) {
                   log.debug(JavaUtils.getMessage("gotType00", "Deser", "" + type));
  @@ -383,11 +421,15 @@
               if (type != null) {
                   Deserializer dser = context.getDeserializerForType(type);
                   if (dser != null) {
  -                    dser.copyValueTargets(this);
  +                    // Move the value targets to the new deserializer
  +                    dser.moveValueTargets(this);
                       context.replaceElementHandler((org.apache.axis.message.SOAPHandler) dser);
                       // And don't forget to give it the start event...
                       dser.startElement(namespace, localName, qName,
                                         attributes, context);
  +                } else {
  +                    throw new SAXException(
  +                                           JavaUtils.getMessage("noDeser00", "" + type));
                   }
               } else {
                   startIdx = context.getCurrentRecordPos();
  @@ -442,9 +484,9 @@
           // Time to call valueComplete to copy the value to 
           // the targets.  First a call is made to componentsReady
           // to ensure that all components are ready.
  -
  -        if (componentsReady())
  +        if (componentsReady()) {
               valueComplete();
  +        }
   
           // If this element has an id, then associate the value with the id.
           // Subsequent hrefs to the id will obtain the value directly.
  @@ -487,8 +529,9 @@
               SAXOutputter so = null;
               so = new SAXOutputter(serContext);
               context.getCurElement().publishContents(so);
  -            
  -            value = writer.getBuffer().toString();
  +            if (!isNil) {
  +                value = writer.getBuffer().toString();
  +            }
           }
       }
       
  
  
  
  1.74      +2 -2      xml-axis/java/src/org/apache/axis/encoding/SerializationContext.java
  
  Index: SerializationContext.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/SerializationContext.java,v
  retrieving revision 1.73
  retrieving revision 1.74
  diff -u -r1.73 -r1.74
  --- SerializationContext.java	1 Feb 2002 04:12:28 -0000	1.73
  +++ SerializationContext.java	6 Mar 2002 19:35:49 -0000	1.74
  @@ -83,8 +83,8 @@
        * @param attributes are additional attributes
        * @param value is the object to serialize
        * @param javaType is the "real" type of the value.  For primitives, the value is the
  -     * associated java.lang class.  So the javaType is needed to know that the value 
  -     * is really a wrapped primitive.
  +     * associated java.lang class.  So the javaType is needed to know that the value
  +     * is really a wrapped primitive.     
        */
       public void serialize(QName qName, Attributes attributes, Object value, Class javaType) 
           throws IOException;
  
  
  
  1.8       +16 -15    xml-axis/java/src/org/apache/axis/encoding/ser/ArrayDeserializer.java
  
  Index: ArrayDeserializer.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/ArrayDeserializer.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ArrayDeserializer.java	22 Feb 2002 23:39:44 -0000	1.7
  +++ ArrayDeserializer.java	6 Mar 2002 19:35:49 -0000	1.8
  @@ -406,29 +406,30 @@
                                                          localName,
                                                          attributes);
   
  -        // If xsi:type is not set, use the default.
  -        if (itemType == null) {
  -            itemType = defaultItemType;
  -        }
  -
  -        // If xsi:type is still not set, try using the arrayClass info
  -        if (itemType == null &&
  -            arrayClass != null &&
  -            arrayClass.isArray()) {
  -            itemType = context.getTypeMapping().
  -                getTypeQName(arrayClass.getComponentType());
  -        }
  -
           // Get the deserializer for the type.  If no deserializer is 
  -        // found, the deserializer is set to DeserializerImpl() which
  -        // will properly issue any errors.
  +        // found, the deserializer is set to DeserializerImpl().
  +        // It is possible that the element has an href, thus we
  +        // won't know the type until the definitition is encountered.
           Deserializer dSer = null;
           if (itemType != null) {
               dSer = context.getDeserializerForType(itemType);
           }
           if (dSer == null) {
               dSer = new DeserializerImpl();  
  +            // Determine a default type for the deserializer
  +            if (itemType == null) {
  +                QName defaultType = defaultItemType;
  +                // If defaultType is not known, try using the arrayClass info
  +                if (defaultType == null &&
  +                    arrayClass != null &&
  +                    arrayClass.isArray()) {
  +                    defaultType = context.getTypeMapping().
  +                        getTypeQName(arrayClass.getComponentType());
  +                }
  +                dSer.setDefaultType(defaultType);
  +            }
           }
  +
   
           // Register the callback value target, and
           // keep track of this index so we know when it has been set.
  
  
  
  1.7       +16 -10    xml-axis/java/src/org/apache/axis/encoding/ser/BeanDeserializer.java
  
  Index: BeanDeserializer.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BeanDeserializer.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- BeanDeserializer.java	22 Feb 2002 23:39:44 -0000	1.6
  +++ BeanDeserializer.java	6 Mar 2002 19:35:49 -0000	1.7
  @@ -159,19 +159,25 @@
                   pd[i].getName().equals(localNameLo) ||
                   pd[i].getName().equals(mangledName)) {
   
  -                // determine the QName for this child element
  -                TypeMapping tm = context.getTypeMapping();
  -                Class type = pd[i].getType();
  -                QName qn = tm.getTypeQName(type);
  -                if (qn == null)
  -                    throw new SAXException(
  -                            JavaUtils.getMessage("unregistered00", "" + type));
  +                // Determine the QName for this child element.
  +                // Look at the type attribute specified.  If this fails,
  +                // use the javaType of the property to get the type qname.
  +                QName qn = context.getTypeFromAttributes(namespace, localName, attributes);
   
                   // get the deserializer
                   Deserializer dSer = context.getDeserializerForType(qn);
  -                if (dSer == null)
  -                    throw new SAXException(
  -                            JavaUtils.getMessage("noDeser00", "" + type));
  +
  +                // If no deserializer, use the base DeserializerImpl.
  +                // There may not be enough information yet to choose the
  +                // specific deserializer.
  +                if (dSer == null) {
  +                    dSer = new DeserializerImpl();
  +                    // determine a default type for this child element
  +                    TypeMapping tm = context.getTypeMapping();
  +                    Class type = pd[i].getType();
  +                    dSer.setDefaultType(tm.getTypeQName(type));
  +                }
  +                
   
                   if (pd[i].getWriteMethod().getParameterTypes().length == 1) {
                       // Success!  Register the target and deserializer.
  
  
  
  1.13      +8 -2      xml-axis/java/src/org/apache/axis/encoding/ser/BeanSerializer.java
  
  Index: BeanSerializer.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BeanSerializer.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- BeanSerializer.java	27 Feb 2002 13:41:27 -0000	1.12
  +++ BeanSerializer.java	6 Mar 2002 19:35:49 -0000	1.13
  @@ -324,8 +324,14 @@
               e = complexType;
           }
   
  -        // Add fields under all element
  -        Element all = types.createElement("all");
  +        // Add fields under sequence element.
  +        // Note: In most situations it would be okay 
  +        // to put the fields under an all element.
  +        // However it is illegal schema to put an
  +        // element with minOccurs=0 or maxOccurs>1 underneath
  +        // an all element.  This is the reason why a sequence
  +        // element is used.
  +        Element all = types.createElement("sequence");
           e.appendChild(all);
   
           // Build a ClassRep that represents the bean class.  This
  
  
  
  1.4       +1 -2      xml-axis/java/src/org/apache/axis/encoding/ser/MapDeserializer.java
  
  Index: MapDeserializer.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/MapDeserializer.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- MapDeserializer.java	22 Feb 2002 23:39:44 -0000	1.3
  +++ MapDeserializer.java	6 Mar 2002 19:35:49 -0000	1.4
  @@ -220,8 +220,7 @@
                                                               attributes);
               Deserializer dser = context.getDeserializerForType(typeQName);
   
  -            // If no deserializer, create DeserializerBase and let it worry
  -            // about errors
  +            // If no deserializer, use the base DeserializerImpl.
               if (dser == null)
                   dser = new DeserializerImpl();
   
  
  
  
  1.2       +1 -1      xml-axis/java/test/wsdl/interop3/groupE/List.java
  
  Index: List.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/interop3/groupE/List.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- List.java	20 Feb 2002 13:46:08 -0000	1.1
  +++ List.java	6 Mar 2002 19:35:50 -0000	1.2
  @@ -153,6 +153,6 @@
        */
       public String toString() {
           return "{" + varInt + ", \"" + varString + "\", " + 
  -            child.toString() + "}";
  +            (child == null ? null :child.toString()) + "}";
       }
   }
  
  
  
  1.4       +2 -0      xml-axis/java/test/wsdl/roundtrip/BondInvestment.java
  
  Index: BondInvestment.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/roundtrip/BondInvestment.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- BondInvestment.java	1 Mar 2002 18:38:31 -0000	1.3
  +++ BondInvestment.java	6 Mar 2002 19:35:50 -0000	1.4
  @@ -93,6 +93,8 @@
       public Byte[] wrapperByteArray;
       public Short[] wrapperShortArray;
       private CallOptions[] options;
  +    public Object options2;
  +    public Object options3;
   
       public BondInvestment() {
   
  
  
  
  1.5       +4 -0      xml-axis/java/test/wsdl/roundtrip/RoundtripTestServiceTestCase.java
  
  Index: RoundtripTestServiceTestCase.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/roundtrip/RoundtripTestServiceTestCase.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- RoundtripTestServiceTestCase.java	23 Feb 2002 00:48:28 -0000	1.4
  +++ RoundtripTestServiceTestCase.java	6 Mar 2002 19:35:50 -0000	1.5
  @@ -215,6 +215,8 @@
               BondInvestment sendValue = new BondInvestment();
   
               sendValue.setOptions(callOptions);
  +            sendValue.setOptions2(callOptions);
  +            sendValue.setOptions3(callOptions[0]);
               sendValue.setWrapperShortArray(wrapperShortArray);
               sendValue.setWrapperByteArray(wrapperByteArray);
               sendValue.setWrapperDouble(new Double(2323.232D));
  @@ -433,6 +435,8 @@
               BondInvestment sendValue = new BondInvestment();
               
               sendValue.setOptions(callOptions);
  +            sendValue.setOptions2(callOptions);
  +            sendValue.setOptions3(callOptions[0]);
               sendValue.setWrapperShortArray(wrapperShortArray);
               sendValue.setWrapperByteArray(wrapperByteArray);
               sendValue.setWrapperDouble(new Double(2323.232D));
  
  
  
  1.5       +8 -0      xml-axis/java/test/wsdl/roundtrip/RoundtripTestSoapBindingImpl.java
  
  Index: RoundtripTestSoapBindingImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/roundtrip/RoundtripTestSoapBindingImpl.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- RoundtripTestSoapBindingImpl.java	23 Feb 2002 00:48:28 -0000	1.4
  +++ RoundtripTestSoapBindingImpl.java	6 Mar 2002 19:35:50 -0000	1.5
  @@ -130,6 +130,8 @@
           BondInvestment sendValue = new BondInvestment();
           
           sendValue.setOptions(callOptions);
  +        sendValue.setOptions2(callOptions);
  +        sendValue.setOptions3(callOptions[0]);
           sendValue.setWrapperShortArray(wrapperShortArray);
           sendValue.setWrapperByteArray(wrapperByteArray);
           sendValue.setWrapperDouble(new Double(33.232D));
  @@ -160,6 +162,8 @@
   
           if ((in0.getOptions()[0].getCallDate().equals(new Date(1013441507388L))) &&
               (in0.getOptions()[1].getCallDate().equals(new Date(1013441507390L))) &&
  +            (((CallOptions[])in0.getOptions2())[0].getCallDate().equals(new Date(1013441507388L))) &&
  +            (((CallOptions[])in0.getOptions2())[1].getCallDate().equals(new Date(1013441507390L))) &&
               (in0.getWrapperShortArray()[0].equals(new Short((short) 23))) &&
               (in0.getWrapperShortArray()[1].equals(new Short((short) 56))) &&
               (in0.getWrapperByteArray()[0].equals(new Byte((byte) 2))) &&
  @@ -204,6 +208,8 @@
           BondInvestment sendValue = new BondInvestment();
           
           sendValue.setOptions(callOptions);
  +        sendValue.setOptions2(callOptions);
  +        sendValue.setOptions3(callOptions[0]);
           sendValue.setWrapperShortArray(wrapperShortArray);
           sendValue.setWrapperByteArray(wrapperByteArray);
           sendValue.setWrapperDouble(new Double(33.232D));
  @@ -233,6 +239,8 @@
   
           if (!((in0.getOptions()[0].getCallDate().equals(new Date(1013441507388L))) &&
                 (in0.getOptions()[1].getCallDate().equals(new Date(1013441507390L))) &&
  +              (((CallOptions[])in0.getOptions2())[0].getCallDate().equals(new Date(1013441507388L))) &&
  +              (((CallOptions[])in0.getOptions2())[1].getCallDate().equals(new Date(1013441507390L))) &&
                 (in0.getWrapperShortArray()[0].equals(new Short((short) 23))) &&
                 (in0.getWrapperShortArray()[1].equals(new Short((short) 56))) &&
                 (in0.getWrapperByteArray()[0].equals(new Byte((byte) 2))) &&