You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tuscany.apache.org by Scott Kurz <sc...@gmail.com> on 2008/08/18 20:18:20 UTC

Follow-up to TUSCANY-2389, nulls in arrays/collections, null vs. empty array/collection

Raymond,

So in the fix for TUSCANY-2389, as Raymond's comment along with his fix to
BaseBeanGenerator indicates:

   "Set the nillable consistent with what wsgen produces.."

we use a different bottom-up mapping for arrays on parm/ret types than than
we do for collections.

Specifically, in the generated wrapper element, the arrays get mapped to a
sequence of nillable children whereas
the other collections seem to get mapped to a sequence of non-nillable
children.

Example:

 Java:

    public String[] arrayMethod() { return null; }
    public List<String> listMethod() { return null; }

  generated XSD:

  <xs:complexType name="arrayMethodResponse">
    <xs:sequence>
      <xs:element name="return" type="xs:string" nillable="true"
minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="listMethodResponse">
    <xs:sequence>
      <xs:element name="return" type="xs:string" minOccurs="0"
maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

The net of this is we still have a very similar problem as we saw in
TUSCANY-2389 when using a collection type.

As our fix to TUSCANY-2389 shows, the key step here is the difference in
generation of the wrapper bean classes:

public class ArrayMethodResponse {
    @XmlElement(name = "return", namespace = "", nillable = true)
    private String[] _return;

public class ListMethodResponse {
    @XmlElement(name = "return", namespace = "")
    private List<String> _return;


So, having finally set the stage, let me move on to ask the question:
Where is this behavior specified?

To me it seems that the construction of the wrapper classes (the request
bean and response bean) would be specified in the JAX-WS
spec, but I don't see that it goes into this detail.

Does anyone know?

The only thing I can guess that wsgen is doing is somehow leveraging some
code which recognizes the distinction between JAXB Section 5.5.2.1, Indexed
Property (array)
and JAXB Section 5.5.2.2, List Property (collection).    These two sections
do mention how an unset indexed property should return null when read,
though an unset list property should return an empty list.

Maybe someone could explain how this applies??

If this is not well-specified, then I'd ask... do we want to map collections
as well in a similiar manner in the bottom-up cases, so as to be able to
pass nulls into them?   (Even though this is different than wsgen)

----

Extending this discussion a bit... even with arrays we are still left with
another problem:   "how to distinguish between a null array and an empty
array?"   It seems like the way to do this would be to use
@XmlElementWrapper  with nillable=true.

So we could generate:

public class ArrayMethodResponse {
    @XmlElementWrapper(name="returnArr", namespace = "", nillable = true)
    @XmlElement(name = "return", namespace = "", nillable = true)
    private String[] _return;

Now.. the extra wrapper obviously impacts performance somewhat, so it's not
just a given that we do this.    The fact that this problem is recognized in
the world of web services:
(e.g., http://www.ibm.com/developerworks/webservices/library/ws-array.html)
says that we might be OK not doing this.

On the other hand, someone doing bottom-up interface design might be exactly
the person who doesn't understand how to do WS-friendly interface design,
and you could argue that these are exactly the people who would benefit by
us supporting Java's null vs. empty distinction by default.

Any thoughts?

Thanks, Scott

Re: Follow-up to TUSCANY-2389, nulls in arrays/collections, null vs. empty array/collection

Posted by Raymond Feng <en...@gmail.com>.
I cannot find the statements in the JAX-WS/JAXB spec and was trying to be 
consistent with the wsgen behavior.

Thanks,
Raymond

From: Scott Kurz
Sent: Monday, August 18, 2008 12:08 PM
To: dev@tuscany.apache.org
Subject: Re: Follow-up to TUSCANY-2389, nulls in arrays/collections, null 
vs. empty array/collection


Raymond,

Not sure if you were just adding a note for reference or if you thought I 
was asking a different question, so let me just say that
I understand where this comes from in the code, but was asking where this 
was spec'd, and wondering if we'd be interested in doing some more here....

Would be interested to hear your thoughts.

Thanks,
Scott





On Mon, Aug 18, 2008 at 2:45 PM, Raymond Feng <en...@gmail.com> wrote:

Hi,

The wrapper generation behavior is controlled at:

org.apache.tuscany.sca.interfacedef.java.jaxws.BaseBeanGenerator.BeanProperty.BeanProperty(String, 
String, Class<?>, Type, boolean)

Where we set the nillable flag for the field. See the FIXME in the source 
code.

          // FIXME: How to test nillable?
          // this.nillable = (type instanceof GenericArrayType) || 
Collection.class.isAssignableFrom(javaClass) || javaClass.isArray();
          // TUSCANY-2389: Set the nillable consistent with what wsgen 
produces
          this.nillable = javaClass.isArray();

Thanks,
Raymond

From: Scott Kurz
Sent: Monday, August 18, 2008 11:18 AM
To: dev@tuscany.apache.org
Subject: Follow-up to TUSCANY-2389, nulls in arrays/collections, null vs. 
empty array/collection



Raymond,

So in the fix for TUSCANY-2389, as Raymond's comment along with his fix to 
BaseBeanGenerator indicates:

 "Set the nillable consistent with what wsgen produces.."

we use a different bottom-up mapping for arrays on parm/ret types than than 
we do for collections.

Specifically, in the generated wrapper element, the arrays get mapped to a 
sequence of nillable children whereas
the other collections seem to get mapped to a sequence of non-nillable 
children.

Example:

Java:

  public String[] arrayMethod() { return null; }
  public List<String> listMethod() { return null; }

 generated XSD:

 <xs:complexType name="arrayMethodResponse">
  <xs:sequence>
    <xs:element name="return" type="xs:string" nillable="true" minOccurs="0" 
maxOccurs="unbounded"/>
  </xs:sequence>
 </xs:complexType>

 <xs:complexType name="listMethodResponse">
  <xs:sequence>
    <xs:element name="return" type="xs:string" minOccurs="0" 
maxOccurs="unbounded"/>
  </xs:sequence>
 </xs:complexType>

The net of this is we still have a very similar problem as we saw in 
TUSCANY-2389 when using a collection type.

As our fix to TUSCANY-2389 shows, the key step here is the difference in 
generation of the wrapper bean classes:

public class ArrayMethodResponse {
  @XmlElement(name = "return", namespace = "", nillable = true)
  private String[] _return;

public class ListMethodResponse {
  @XmlElement(name = "return", namespace = "")
  private List<String> _return;


So, having finally set the stage, let me move on to ask the question: Where 
is this behavior specified?

To me it seems that the construction of the wrapper classes (the request 
bean and response bean) would be specified in the JAX-WS
spec, but I don't see that it goes into this detail.

Does anyone know?

The only thing I can guess that wsgen is doing is somehow leveraging some 
code which recognizes the distinction between JAXB Section 5.5.2.1, Indexed 
Property (array)
and JAXB Section 5.5.2.2, List Property (collection).    These two sections 
do mention how an unset indexed property should return null when read, 
though an unset list property should return an empty list.

Maybe someone could explain how this applies??

If this is not well-specified, then I'd ask... do we want to map collections 
as well in a similiar manner in the bottom-up cases, so as to be able to 
pass nulls into them?   (Even though this is different than wsgen)

----

Extending this discussion a bit... even with arrays we are still left with 
another problem:   "how to distinguish between a null array and an empty 
array?"   It seems like the way to do this would be to use 
@XmlElementWrapper  with nillable=true.

So we could generate:

public class ArrayMethodResponse {
  @XmlElementWrapper(name="returnArr", namespace = "", nillable = true)
  @XmlElement(name = "return", namespace = "", nillable = true)
  private String[] _return;

Now.. the extra wrapper obviously impacts performance somewhat, so it's not 
just a given that we do this.    The fact that this problem is recognized in 
the world of web services:
(e.g., http://www.ibm.com/developerworks/webservices/library/ws-array.html) 
says that we might be OK not doing this.

On the other hand, someone doing bottom-up interface design might be exactly 
the person who doesn't understand how to do WS-friendly interface design, 
and you could argue that these are exactly the people who would benefit by 
us supporting Java's null vs. empty distinction by default.

Any thoughts?

Thanks, Scott 


Re: Follow-up to TUSCANY-2389, nulls in arrays/collections, null vs. empty array/collection

Posted by Scott Kurz <sc...@gmail.com>.
Raymond,

Not sure if you were just adding a note for reference or if you thought I
was asking a different question, so let me just say that
I understand where this comes from in the code, but was asking where this
was spec'd, and wondering if we'd be interested in doing some more here....

Would be interested to hear your thoughts.

Thanks,
Scott




On Mon, Aug 18, 2008 at 2:45 PM, Raymond Feng <en...@gmail.com> wrote:

> Hi,
>
> The wrapper generation behavior is controlled at:
>
> org.apache.tuscany.sca.interfacedef.java.jaxws.BaseBeanGenerator.BeanProperty.BeanProperty(String,
> String, Class<?>, Type, boolean)
>
> Where we set the nillable flag for the field. See the FIXME in the source
> code.
>
>           // FIXME: How to test nillable?
>           // this.nillable = (type instanceof GenericArrayType) ||
> Collection.class.isAssignableFrom(javaClass) || javaClass.isArray();
>           // TUSCANY-2389: Set the nillable consistent with what wsgen
> produces
>           this.nillable = javaClass.isArray();
>
> Thanks,
> Raymond
>
> From: Scott Kurz
> Sent: Monday, August 18, 2008 11:18 AM
> To: dev@tuscany.apache.org
> Subject: Follow-up to TUSCANY-2389, nulls in arrays/collections, null vs.
> empty array/collection
>
>
>
> Raymond,
>
> So in the fix for TUSCANY-2389, as Raymond's comment along with his fix to
> BaseBeanGenerator indicates:
>
>  "Set the nillable consistent with what wsgen produces.."
>
> we use a different bottom-up mapping for arrays on parm/ret types than than
> we do for collections.
>
> Specifically, in the generated wrapper element, the arrays get mapped to a
> sequence of nillable children whereas
> the other collections seem to get mapped to a sequence of non-nillable
> children.
>
> Example:
>
> Java:
>
>   public String[] arrayMethod() { return null; }
>   public List<String> listMethod() { return null; }
>
>  generated XSD:
>
>  <xs:complexType name="arrayMethodResponse">
>   <xs:sequence>
>     <xs:element name="return" type="xs:string" nillable="true"
> minOccurs="0" maxOccurs="unbounded"/>
>   </xs:sequence>
>  </xs:complexType>
>
>  <xs:complexType name="listMethodResponse">
>   <xs:sequence>
>     <xs:element name="return" type="xs:string" minOccurs="0"
> maxOccurs="unbounded"/>
>   </xs:sequence>
>  </xs:complexType>
>
> The net of this is we still have a very similar problem as we saw in
> TUSCANY-2389 when using a collection type.
>
> As our fix to TUSCANY-2389 shows, the key step here is the difference in
> generation of the wrapper bean classes:
>
> public class ArrayMethodResponse {
>   @XmlElement(name = "return", namespace = "", nillable = true)
>   private String[] _return;
>
> public class ListMethodResponse {
>   @XmlElement(name = "return", namespace = "")
>   private List<String> _return;
>
>
> So, having finally set the stage, let me move on to ask the question: Where
> is this behavior specified?
>
> To me it seems that the construction of the wrapper classes (the request
> bean and response bean) would be specified in the JAX-WS
> spec, but I don't see that it goes into this detail.
>
> Does anyone know?
>
> The only thing I can guess that wsgen is doing is somehow leveraging some
> code which recognizes the distinction between JAXB Section 5.5.2.1,
> Indexed Property (array)
> and JAXB Section 5.5.2.2, List Property (collection).    These two
> sections do mention how an unset indexed property should return null when
> read, though an unset list property should return an empty list.
>
> Maybe someone could explain how this applies??
>
> If this is not well-specified, then I'd ask... do we want to map
> collections as well in a similiar manner in the bottom-up cases, so as to be
> able to pass nulls into them?   (Even though this is different than wsgen)
>
> ----
>
> Extending this discussion a bit... even with arrays we are still left with
> another problem:   "how to distinguish between a null array and an empty
> array?"   It seems like the way to do this would be to use
> @XmlElementWrapper  with nillable=true.
>
> So we could generate:
>
> public class ArrayMethodResponse {
>   @XmlElementWrapper(name="returnArr", namespace = "", nillable = true)
>   @XmlElement(name = "return", namespace = "", nillable = true)
>   private String[] _return;
>
> Now.. the extra wrapper obviously impacts performance somewhat, so it's not
> just a given that we do this.    The fact that this problem is recognized in
> the world of web services:
> (e.g., http://www.ibm.com/developerworks/webservices/library/ws-array.html)
> says that we might be OK not doing this.
>
> On the other hand, someone doing bottom-up interface design might be
> exactly the person who doesn't understand how to do WS-friendly interface
> design, and you could argue that these are exactly the people who would
> benefit by us supporting Java's null vs. empty distinction by default.
>
> Any thoughts?
>
> Thanks, Scott
>

Re: Follow-up to TUSCANY-2389, nulls in arrays/collections, null vs. empty array/collection

Posted by Raymond Feng <en...@gmail.com>.
Hi,

The wrapper generation behavior is controlled at:

org.apache.tuscany.sca.interfacedef.java.jaxws.BaseBeanGenerator.BeanProperty.BeanProperty(String, 
String, Class<?>, Type, boolean)

Where we set the nillable flag for the field. See the FIXME in the source 
code.

            // FIXME: How to test nillable?
            // this.nillable = (type instanceof GenericArrayType) || 
Collection.class.isAssignableFrom(javaClass) || javaClass.isArray();
            // TUSCANY-2389: Set the nillable consistent with what wsgen 
produces
            this.nillable = javaClass.isArray();

Thanks,
Raymond

From: Scott Kurz
Sent: Monday, August 18, 2008 11:18 AM
To: dev@tuscany.apache.org
Subject: Follow-up to TUSCANY-2389, nulls in arrays/collections, null vs. 
empty array/collection


Raymond,

So in the fix for TUSCANY-2389, as Raymond's comment along with his fix to 
BaseBeanGenerator indicates:

   "Set the nillable consistent with what wsgen produces.."

we use a different bottom-up mapping for arrays on parm/ret types than than 
we do for collections.

Specifically, in the generated wrapper element, the arrays get mapped to a 
sequence of nillable children whereas
the other collections seem to get mapped to a sequence of non-nillable 
children.

Example:

 Java:

    public String[] arrayMethod() { return null; }
    public List<String> listMethod() { return null; }

  generated XSD:

  <xs:complexType name="arrayMethodResponse">
    <xs:sequence>
      <xs:element name="return" type="xs:string" nillable="true" 
minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="listMethodResponse">
    <xs:sequence>
      <xs:element name="return" type="xs:string" minOccurs="0" 
maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

The net of this is we still have a very similar problem as we saw in 
TUSCANY-2389 when using a collection type.

As our fix to TUSCANY-2389 shows, the key step here is the difference in 
generation of the wrapper bean classes:

public class ArrayMethodResponse {
    @XmlElement(name = "return", namespace = "", nillable = true)
    private String[] _return;

public class ListMethodResponse {
    @XmlElement(name = "return", namespace = "")
    private List<String> _return;


So, having finally set the stage, let me move on to ask the question: 
Where is this behavior specified?

To me it seems that the construction of the wrapper classes (the request 
bean and response bean) would be specified in the JAX-WS
spec, but I don't see that it goes into this detail.

Does anyone know?

The only thing I can guess that wsgen is doing is somehow leveraging some 
code which recognizes the distinction between JAXB Section 5.5.2.1, Indexed 
Property (array)
and JAXB Section 5.5.2.2, List Property (collection).    These two sections 
do mention how an unset indexed property should return null when read, 
though an unset list property should return an empty list.

Maybe someone could explain how this applies??

If this is not well-specified, then I'd ask... do we want to map collections 
as well in a similiar manner in the bottom-up cases, so as to be able to 
pass nulls into them?   (Even though this is different than wsgen)

----

Extending this discussion a bit... even with arrays we are still left with 
another problem:   "how to distinguish between a null array and an empty 
array?"   It seems like the way to do this would be to use 
@XmlElementWrapper  with nillable=true.

So we could generate:

public class ArrayMethodResponse {
    @XmlElementWrapper(name="returnArr", namespace = "", nillable = true)
    @XmlElement(name = "return", namespace = "", nillable = true)
    private String[] _return;

Now.. the extra wrapper obviously impacts performance somewhat, so it's not 
just a given that we do this.    The fact that this problem is recognized in 
the world of web services:
(e.g., http://www.ibm.com/developerworks/webservices/library/ws-array.html) 
says that we might be OK not doing this.

On the other hand, someone doing bottom-up interface design might be exactly 
the person who doesn't understand how to do WS-friendly interface design, 
and you could argue that these are exactly the people who would benefit by 
us supporting Java's null vs. empty distinction by default.

Any thoughts?

Thanks, Scott