users@jax-ws.java.net

Re[2]: Problem with string arrays containing nulls

From: Egor Samarkhanov <slash_at_actimind.com>
Date: Thu, 8 Feb 2007 16:30:25 +0300

Hello !

Thanks for the hint about wrapper bean. I've created the following
wrapper:

@XmlAccessorType(value=XmlAccessType.FIELD)
public class StringArrayWrapper
{
    @XmlElement(nillable=true)
    private String[] array;

    public StringArrayWrapper( String[] array ) {
        this.array = array;
    }

    public StringArrayWrapper() {
    }

    public String[] getArray() {
        return array;
    }

    public void setArray( String[] array ) {
        this.array = array;
    }
}

changed the services's method signature to

@WebMethod()
public StringArrayWrapper testStringArray( StringArrayWrapper w )

and got the expected result. Moreover, the WCF's service method
signature is still

string[] testStringArray(string[] arg0)


Great! But then I decided to implement the same using Java Type Adapters
(to keep using String[] on Java side).
I wrote the simple adapter:

public class AdapterStringArrayToBean extends XmlAdapter<StringArrayWrapper, String[]>
{
    public String[] unmarshal( StringArrayWrapper wrapper ) throws Exception
    {
        if( wrapper == null )
          return null;
        return wrapper.getArray();
    }

    public StringArrayWrapper marshal( String[] s ) throws Exception
    {
        return new StringArrayWrapper( s );
    }
}

and then changed the service's method signature like this:

@WebMethod()
public @XmlJavaTypeAdapter(type=String[].class, value=AdapterStringArrayToBean.class) String[] testStringArray( @XmlJavaTypeAdapter(type=String[].class, value=AdapterStringArrayToBean.class) String[] s )


After the deployment I got the following method signature in WCF:

public stringArrayWrapper[] testStringArray(stringArrayWrapper[] arg0)

Well, I didn't expect array of wrappers. I thought it should be just the
wrapper. I checked the WSDL and indeed, maxOccurs="unbounded" is set for
the arg0 element (line 3):

<xs:complexType name="testStringArray">
  <xs:sequence>
    <xs:element name="arg0" type="tns:stringArrayWrapper" maxOccurs="unbounded" minOccurs="0" />
  </xs:sequence>
</xs:complexType>
<xs:complexType name="stringArrayWrapper">
  <xs:sequence>
    <xs:element name="array" type="xs:string" nillable="true" maxOccurs="unbounded" minOccurs="0" />
  </xs:sequence>
</xs:complexType>


I guess my adapter is wrong. How can I write the adapter correctly for
this case?


Thanks for your help,

Egor.


Thursday, February 8, 2007, 2:52:10 AM, you wrote:

VP> After talking to jaxb experts - there is no jaxb annotation that you can
VP> put on method parameters to achieve such behaviour. This is something
VP> that can be handled by JAXWS, where it can generate
VP> @XmlElement(nillable="true") in the wrapper bean on the property.

VP> However we would need to verify whether such change will be
VP> non-compliant w.r.t. generated code from such schema by wsimport.

VP> Please go ahead and report and issue at
VP> http://jax-ws.dev.java.net/servlets/ProjectIssues.

VP> -vivek.

VP> Vivek Pandey wrote:
>> The generated schema look ok to me. String[] is mapped to and it seems
>> correct as per JAXB schema.
>>
>> <xs:element name="return" type="xs:string" maxOccurs="unbounded"
>> minOccurs="0"/>
>>
>> Which look ok as per JAXB spec and expectedly at runtime the null
>> element is ignored. So your analysis is correct.
>> I am wondering if there is any jaxb annotation or some mechanism to
>> generate such schema. Ccing it to users_at_jaxb alias.
>>
>> -vivek.
>>
>>
>>
>>
>>
>> Egor Samarkhanov wrote:
>>> Hi!
>>>
>>> I have a problem with string arrays containing nulls (WSIT):
>>>
>>> Here is my simple service:
>>>
>>> @WebService
>>> public class MyServiceImpl
>>> {
>>> @WebMethod()
>>> public String[] testStringArray( String[] s )
>>> {
>>> return new String[] {"s","",null};
>>> }
>>> }
>>>
>>> WSIT generates the following WSDL types for it:
>>>
>>> <xs:schema xmlns:tns="http://wsitproto/"
>>> xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"
>>> targetNamespace="http://wsitproto/">
>>> <xs:element name="testStringArray" type="tns:testStringArray"/>
>>> <xs:element name="testStringArrayResponse"
>>> type="tns:testStringArrayResponse"/>
>>> <xs:complexType name="testStringArray">
>>> <xs:sequence>
>>> <xs:element name="arg0" type="xs:string"
>>> maxOccurs="unbounded" minOccurs="0"/>
>>> </xs:sequence>
>>> </xs:complexType>
>>> <xs:complexType name="testStringArrayResponse">
>>> <xs:sequence>
>>> <xs:element name="return" type="xs:string"
>>> maxOccurs="unbounded" minOccurs="0"/>
>>> </xs:sequence>
>>> </xs:complexType>
>>> </xs:schema>
>>>
>>> I created WCF client and tried to invoke the service with the new
>>> String[] {"s","",null} parameter,
>>> but my service received only two first values (only {"s",""}). The
>>> last null string is missed.
>>>
>>> I examined SOAP envelopes and they look accordingly:
>>>
>>> Inbound message:
>>>
>>> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
>>> <s:Header/>
>>> <s:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>>> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
>>> <testStringArray xmlns="http://wsitproto/">
>>> <arg0 xmlns="">s</arg0>
>>> <arg0 xmlns=""/>
>>> </testStringArray>
>>> </s:Body>
>>> </s:Envelope>
>>>
>>> Outbound message:
>>>
>>> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
>>> <S:Body>
>>> <ns2:testStringArrayResponse xmlns:ns2="http://wsitproto/">
>>> <return>s</return>
>>> <return></return>
>>> </ns2:testStringArrayResponse>
>>> </S:Body>
>>> </S:Envelope>
>>>
>>> As I understand that's because elements are not marked as
>>> nillable="true" in WSDL.
>>> I think the correct WSDL types would be as follows:
>>>
>>> <xs:schema xmlns:tns="http://wsitproto/"
>>> xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0"
>>> targetNamespace="http://wsitproto/">
>>> <xs:element name="testStringArray" type="tns:testStringArray"/>
>>> <xs:element name="testStringArrayResponse"
>>> type="tns:testStringArrayResponse"/>
>>> <xs:complexType name="testStringArray">
>>> <xs:sequence>
>>> <xs:element name="arg0" type="xs:string"
>>> maxOccurs="unbounded" minOccurs="0" nillable="true"/>
>>> </xs:sequence>
>>> </xs:complexType>
>>> <xs:complexType name="testStringArrayResponse">
>>> <xs:sequence>
>>> <xs:element name="return" type="xs:string"
>>> maxOccurs="unbounded" minOccurs="0" nillable="true"/>
>>> </xs:sequence>
>>> </xs:complexType>
>>> </xs:schema>
>>>
>>> (note the nillable attributes)
>>>
>>> And the question is how can I make WSIT generate and correctly handle
>>> nillable types in WSDL?
>>>
>>>
>>> ----
>>> Egor
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jax-ws.dev.java.net
>>> For additional commands, e-mail: users-help_at_jax-ws.dev.java.net
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jax-ws.dev.java.net
>> For additional commands, e-mail: users-help_at_jax-ws.dev.java.net
>>

VP> ---------------------------------------------------------------------
VP> To unsubscribe, e-mail: users-unsubscribe_at_jax-ws.dev.java.net
VP> For additional commands, e-mail: users-help_at_jax-ws.dev.java.net