axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bo Xie (JIRA)" <j...@apache.org>
Subject [jira] Commented: (AXIS2-1938) [axis2] WSDL2JAVA with XMLBean binding does not create instance of the derived type or ignore xsi:type in the xml
Date Sat, 27 Jan 2007 18:46:49 GMT

    [ https://issues.apache.org/jira/browse/AXIS2-1938?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12468050
] 

Bo Xie commented on AXIS2-1938:
-------------------------------

Looks like this is related with xsd resource loading on the service side. This kinda explain
why the same code worked on client side(with the xsi:type generated) but not on the service
side. Update with more info on the email thread.

Thanks,
-Bo

Hi,

   My previous issue is caused by org.apache.xmlbeans.impl

    .schema.SchemaTypeLoaderImpl's findTypeRef () not be able to load the following resource
in service: 


schemaorg_apache_xmlbeans/type/http_3A_2F_2Fquickstart_2Esamples_2Fxsd/EU_2DAddress.xsb

This resource is actually in my .aar file under dir\XBean-packaged.jar(generated from WSDL2JAVA)

Do anyone know how to make it work?

Thanks a lot!

-Bo



On 1/21/07, Bo Xie <mrboxie@gmail.com > wrote:

    Hi all,

        Sorry to ask this again, does anyone know what could cause the following call to return
null, is it some kind of setup/configure issue in the service? How to workaround it? It is
in org.apache.xmlbeans.impl.schema.SchemaTypeLoaderImpl's findTypeRef (). This causes the
derived type cannot be created properly with the xsi:type attribute.

        SchemaTypeSystem ts = typeSystemForComponent("schema" + METADATA_PACKAGE_LOAD + "/type/",
name);


    Thanks,
    -Bo



    On 1/19/07, Bo Xie <mrboxie@gmail.com > wrote:

        Hi,

          Looks like the problem is with the _typeCache in org.apache.xmlbeans.impl.schema.SchemaTypeLoaderImpl's
findTypeRef () not being populated correctly for derived type when deployed as a service.
This in turn was caused by typeSystemForComponent() in findTypeRef() returning null. As comparison,
the _typeCache is populated correctly if I run it locally in a test program's main() and in
this case the typeSystemForComponent() is not null.

          Below is the findTypeRef method which suppose to return the derived type if Qname
passed in is a derived type. In my case, the QName is { http://quickstart.samples/xsd}EU-Address
.

          When in service, the _typeCache is populated with CACHED_NOT_FOUND for QName {http://quickstart.samples/xsd}EU-Address
. So findTypeRef  will return null. This will result in the changeType() call to not return
the derived type. (See call stack at the bottom.)

          In the local test program, the _typeCache was initially empty and was populated
with the correct value at the end of findTypeRef call.

          The only way that CACHED_NOT_FOUND can be set for any QName type is when the following
line in findTypeRef () return null.
        SchemaTypeSystem ts = typeSystemForComponent("schema" + METADATA_PACKAGE_LOAD + "/type/",
name);

          I have no idea why this typeSystemForComponent() could return null in service. Can
someone help clarify the myth here? When I trace into the first incoming message, it indeed
shows that the typeSystemForComponent return null!

          Below are the findTypeRef method and the call stack.

        Thanks,
        -Bo

        public SchemaType.Ref findTypeRef(QName name)
            {
                /**
                 * The maps are synchronized, we use two accesses to the cache (one read
                 * and one write), but the code inbetween is not synchronized. The
                 * assumption is that the underlying datastructures (the search path and
                 * the classloader) do not change, so two threads running the code in
                 * parallel will come up with the same result.
                 */
                Object cached = _typeCache.get(name);
                if (cached == CACHED_NOT_FOUND)
                    return null; ==>exit here in bad one
                   
                SchemaType.Ref result = (SchemaType.Ref) cached;
                if (result == null)
                {
                    for (int i = 0; i < _searchPath.length; i++)
                        if (null != (result = _searchPath[i].findTypeRef(name)))
                            break;
                    if (result == null)
                    {
                        SchemaTypeSystem ts = typeSystemForComponent("schema" + METADATA_PACKAGE_LOAD
+ "/type/", name);
                        if (ts != null)
                        {
                            result = ts.findTypeRef(name);
                            assert(result != null) : "Type system registered type " + QNameHelper.pretty(name)
+ " but does not return it";
                        }
                    }
                    _typeCache.put(name, result == null ? CACHED_NOT_FOUND : result);
                }
                return result; ==>exit here in good case when the typeCache.put is call
with good value.
            }


        Stack:
        SchemaTypeLoaderImpl.findTypeRef(QName) line: 369   
        SchemaTypeLoaderImpl(SchemaTypeLoaderBase).findType(QName) line: 119   
        SchemaTypeImpl.getElementType(QName, QName, SchemaTypeLoader) line: 910   
        GetAddressesResponseDocumentImpl$GetAddressesResponseImpl(XmlObjectBase).get_element_type(QName,
QName) line: 925   
        Cur.setType(SchemaType, boolean) line: 2546   
        Xobj$ElementXobj(Xobj).change_type(SchemaType) line: 1876   
        AddressImpl(XmlObjectBase).changeType(SchemaType) line: 504   
        StockQuoteServiceSkeleton.populateAddress(GetAddressesResponseDocument) line: 281
  
        StockQuoteServiceSkeleton.getAddresses(GetAddressesDocument) line: 226   
        StockQuoteServiceMessageReceiverInOut.invokeBusinessLogic(MessageContext, MessageContext)
line: 73   
        StockQuoteServiceMessageReceiverInOut(AbstractInOutSyncMessageReceiver).receive(MessageContext)
line: 39   
        AxisEngine.receive(MessageContext) line: 493   


        On 1/18/07, Bo Xie < mrboxie@gmail.com> wrote:

            Hi,

               Regarding the instanceOf issue, I debugged and saw the following issue.

               1. In the WSDL2JAVA generated GetAddressesDocumentImpl.getAddressArray, I would
expect the array element should be of type USAddressImpl if instance is a US address. This
is not the case. For example, all elements in targetList filled by find_all_element_users()
are instances of AddressImpl not USAddressImpl when the XML element is as follows:

            <xml-fragment xsi:type="xsd:US-Address" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
" xmlns:xsd=" http://quickstart.samples/xsd" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/
">
              <city xmlns=" http://quickstart.samples/xsd">Cupertino</city>
              <name xmlns="http://quickstart.samples/xsd ">XYZ</name>
              <state xmlns=" http://quickstart.samples/xsd">CA</state>
              <zip xmlns="http://quickstart.samples/xsd ">95014</zip>
            </xml-fragment>

            This kind of explained why the instanceof is not working properly in service code.
Any idea why it is done this way? Is it a bug?

            public samples.quickstart.service.xmlbeans.xsd.Address[] getAddressesArray()
                    {
                        synchronized (monitor())
                        {
                            check_orphaned();
                            java.util.List targetList = new java.util.ArrayList();
                            get_store().find_all_element_users(ADDRESSES$2, targetList);
                            samples.quickstart.service.xmlbeans.xsd.Address[] result = new
samples.quickstart.service.xmlbeans.xsd.Address [targetList.size()];
                            targetList.toArray(result);
                            return result;
                        }
                    }

            Thanks,
            -Bo


> [axis2] WSDL2JAVA with XMLBean binding does not create instance of the derived type or
ignore xsi:type in the xml
> -----------------------------------------------------------------------------------------------------------------
>
>                 Key: AXIS2-1938
>                 URL: https://issues.apache.org/jira/browse/AXIS2-1938
>             Project: Axis 2.0 (Axis2)
>          Issue Type: Bug
>          Components: databinding
>    Affects Versions: 1.1
>         Environment: Windows XP, tomcat 5.5, Axis2 1.1
>            Reporter: Bo Xie
>         Attachments: StockQuoteServiceSkeleton.java, XMLBeanBinding.zip
>
>
> There are basically two issues.
> 1. The java objects created does not use the xsi:type in the XML. In my case, the xsi:type
is for derived type, but the object created is still of base type.
> 2. The XML string generated from the client side has the xsi:type for Address object,
so the service see it but did not generate the derived type according to the xsi:type(this
is the issue reported above). But the server side generated XML string does not have the xsi:type
for the objects, so the object XML string does not have xsi:type when the message received
on the client side. Why the xsi:type is missing in this case? In both cases, I used types
derived from the Address type. The client and service code are based on the XMLBean quickstart
sample.
> Attached are 
> 1. the WSDL file. 
> 2.The build file that you can check if the WSDL2JAVA is proper for my case.
> 3. The client code
> 4. The server code.
> Below are the email exchange with Ajith Ranabahu.
> Subject: [axis2] WSDL2JAVA with XMLBean binding does not create instance of the derived
type
> ------------------------
> From: Bo Xie <mrboxie@gmail.com>
> To: axis-user@ws.apache.org
> Date: Tue, Jan 2, 2007 at 7:45 PM
> Hi there,
>   I am new to axis2 with XMLBean data binding, please help me with the following issue.
>   I modified the quickstart sample XMLBean program to try a WSDL with the following types.
The type US-Address is a derived from type Address. I would like to create a service operation
updateAddresses to change addresses of a company based on a symbol. The addresses is an array
that can take either Address or USAddress instances.
>           <xs:complexType name="Address">
>                 <xs:sequence>
>                     <xs:element name="name" type="xs:string" minOccurs="0"/>
>                     <xs:element name="street" type="xs:string"/>
>                     <xs:element name="city" type="xs:string"/>
>                 </xs:sequence>
>             </xs:complexType>
>          
>        
>             <xs:complexType name="US-Address">
>                 <xs:complexContent>
>                     <xs:extension base="ipo:Address">
>                         <xs:sequence>
>                             <xs:element name="state" type="ipo:US-State"/>
>                             <xs:element name="zip" type="xs:positiveInteger"/>
>                         </xs:sequence>
>                     </xs:extension>
>                 </xs:complexContent>
>             </xs:complexType>
>          <xs:element name="updateAddresses">
>                 <xs:complexType>
>                     <xs:sequence>
>                         <xs:element name="symbol" type="xs:string" nillable="true"/>
>                         <xs:element name="addresses" type="ipo:Address" maxOccurs="unbounded"/>
>                     </xs:sequence>
>                 </xs:complexType>
>       I used WSDL2JAVA with XMLBean data binding to generate the skeleton and stub code.
All looks great and the SOAP exchange looks fine too.
>       In the client code, I created one instance if USAddress and one instance of Address
and put them into the addresses list. In the SOAP request message, the instances are as  shown
as follows below. Note, xsi-type for the instance indicate the correct types which is nice.
>     <soapenv:Body>
>     <updateAddresses xmlns="http://quickstart.samples/xsd">
>       
>         <symbol>XYZ</symbol>      
>         <addresses xmlns:xsi="http;//www.w3.org/2001/XMLSchema-instance" xmlns:xsd="
> http://quickstart.samples/xsd" xsi:type="xsd:US-Address">
>         <name>company name</name>
>         <city>Sunnyvale</city>
>         <state>CA</state>
>         <zip>94087</zip>
>        </addresses>
>        <addresses xmlns:xsi="http;//www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://quickstart.samples/xsd
> " xsi:type="xsd:Address">
>         <name>company name</name>
>         <city>Hong Kong</city>
>        </addresses>
>     </updateAddresses>
>   </soapenv:Body>
>    The problem is when the XML object mapped into java object on the service side, all
the XML address object passed to the skeleton are all of Address type. I would expect one
instance be Address type, another be USAddress type. Since xsi-type in the SOAP message has
the right type, why the XMLBean object is not created as the derived type? Is there any option
in WSDL2JAVA to make this work?
>    From the XMLBean Address java object, how can I access the xsi-type attribute that
was available in the XML string?
>    If I am not heading the right direction, can anyone suggest some alternatives?
> Thanks for your time!
> -Bo
>  
> --------
> From: Ajith Ranabahu <ajith.ranabahu@gmail.com>
> Reply-To: axis-user@ws.apache.org
> To: axis-user@ws.apache.org
> Date: Wed, Jan 3, 2007 at 5:16 AM
> Hi,
> The reason here is that you have set the type of the addresses element
> to be 'Address' rather than USAddress (the code generator would put
> the reference for the Address rather than the USAddress). However
> since the xsi:type attribute is present the deserializer should create
> the right object and you can just use a type cast to get to the right
> object.
> HTH
> Ajith
> [Quoted text hidden]
> --
> Ajith Ranabahu
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: axis-user-unsubscribe@ws.apache.org
> For additional commands, e-mail: axis-user-help@ws.apache.org
> --------
> From: Bo Xie <boxie@cisco.com>
> Reply-To: axis-user@ws.apache.org
> To: axis-user@ws.apache.org
> Date: Wed, Jan 3, 2007 at 7:55 AM
> Thanks Ajith for the quick response.
> I have tried to use the instanceof to test if the instance is USAddress,
> but the test returns false. Without that, the type cast is not safe as
> the Address list can have items of either Address or USAddress. My
> question here is should the java instance created from XML be of type
> USAddress even though the signature is Address. Is there anyway to make
> this happen?
> Thanks,
> -Bo
> [Quoted text hidden]
> [Quoted text hidden]
> --------
> From: Ajith Ranabahu <ajith.ranabahu@gmail.com>
> Reply-To: axis-user@ws.apache.org
> To: axis-user@ws.apache.org
> Date: Wed, Jan 3, 2007 at 8:20 AM
> Hi,
> Since the xsi:type attribute is present and points to the USAddress,
> the generated object should be of  type USAddress. Perhaps the problem
> is the way you check the instanceof. I mean XMLBeans should have
> generated a getAddresses method to updateAddress ? (It's a little bit
> weird how XMLBeans treats these schemas but I'm guessing)
> If you can use a debugger and go through the object hierarchy at
> runtime you should be able to figure this out
> Ajith
> [Quoted text hidden]
> --
> Ajith Ranabahu
> [Quoted text hidden]
> --------
> From: Bo Xie <mrboxie@gmail.com>
> To: axis-user@ws.apache.org
> Date: Wed, Jan 3, 2007 at 10:19 AM
> Thanks Ajith. Could you be more specific on how to figure out the right type of the instance?
Here is the code snippet and the output on the service side.
> The getAddressArray indeed returns Address[] which is good. But the instanceof always
returns Address even for USAddress instance. The interesting thing is the toString output
of the addr variable. It includes the correct xsi-type for each instance. So how can I do
the correct instanceof to figure the right type to cast in this case?
> Thanks,
> -Bo
> ----Code snippet----
> public  void updateAddresses(samples.quickstart.service.xmlbeans.xsd.UpdateAddressesDocument
param3)
>     {
>         //Todo fill this with the necessary business logic
>         String symbol = param3.getUpdateAddresses().getSymbol();
>         System.err.println(getCurrentTime()+"- Update Symbol:" + symbol);
>        
>         Address[] addrs = param3.getUpdateAddresses ().getAddressesArray();
>         for (int i = 0; i < addrs.length; i++) {
>             Address addr = addrs[i];
>             if(addr instanceof USAddress) System.err.println("USAddress instance");
>             if(addr instanceof Address) System.err.println("Address instance");
>             System.err.println(addr.getClass().getName()+":"+addr);
>         }
>    ...}
>  ----Output from the code ----
> Address instance
> samples.quickstart.service.xmlbeans.xsd.impl.AddressImpl: <xml-fragment xsi:type="xsd:US-Address"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd=" http://quickstart.samples/xsd"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
>   <name xmlns=" http://quickstart.samples/xsd">company name</name>
>   <city xmlns="http://quickstart.samples/xsd">Sunnyvale</city>
>   <state xmlns=" http://quickstart.samples/xsd">CA</state>
>   <zip xmlns="http://quickstart.samples/xsd">94087</zip>
> </xml-fragment>
> Address instance
> samples.quickstart.service.xmlbeans.xsd.impl.AddressImpl:<xml-fragment xsi:type="xsd:Address"
xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://quickstart.samples/xsd"
xmlns:xsd="http://quickstart.samples/xsd " xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
>   <name xmlns="http://quickstart.samples/xsd ">company</name>
>   <city xmlns="http://quickstart.samples/xsd">Hong Kong</city>
> </xml-fragment>
> [Quoted text hidden]
> --------
> From: Ajith Ranabahu <ajith.ranabahu@gmail.com>
> Reply-To: axis-user@ws.apache.org
> To: axis-user@ws.apache.org
> Date: Wed, Jan 3, 2007 at 5:16 PM
> Hi,
> It seems to me that you have to go one level deep. See whether there
> is a getAddress method in the Address class.
> XMLBeans generates a lot of classes and things are a bit confusing
> specially when types and elements have similar names. AFAIK XMLBeans
> generates a class per type and element. So there would be a class
> generated for the address type and also for the address element. My
> guess is you have to check the address type object instead of the
> address element object.
> Ajith
> [Quoted text hidden]
> --
> [Quoted text hidden]
> --------
> From: Ramesh Gurunathan <ramesh.gurunathan@gmail.com>
> Reply-To: axis-user@ws.apache.org
> To: axis-user@ws.apache.org
> Date: Wed, Jan 3, 2007 at 8:32 PM
> Hi,
> What you are trying to achieve is the value inheritance in XML. I
> think, unfortunately, the web services / XML / SOAP community is
> paying less attention to this topic. I encountered the same issue with
> XMLBeans binding. It forced me to change the XML schema. I introduced
> a new complex type with a 'choice'
> <complexType name="Address">
>  <choice>
>    <element name="USAddress" type="USAddress"/>
>    <element name="OtherAddress" type="OtherAddress"/>
>  </choice>
> </complexType>
> <xs:complexType name="OtherAddress">
>  <xs:sequence>
>    <xs:element name="name" type="xs:string" minOccurs="0"/>
>    <xs:element name="street" type="xs:string"/>
>    <xs:element name="city" type="xs:string"/>
>  </xs:sequence>
> </xs:complexType>
> <xs:complexType name="USAddress">
>  <xs:complexContent>
>    <xs:extension base="ipo:OtherAddress">
>      <xs:sequence>
>        <xs:element name="state" type="ipo:US-State"/>
>        <xs:element name="zip" type="xs:positiveInteger"/>
>      </xs:sequence>
>   </xs:extension>
>  </xs:complexContent>
> </xs:complexType>
> <xs:element name="updateAddresses">
>  <xs:complexType>
>    <xs:sequence>
>      <xs:element name="symbol" type="xs:string" nillable="true"/>
>      <xs:element name="addresses" type="Address" maxOccurs="unbounded"/>
>    </xs:sequence>
>  </xs:complexType>
> </element>
> If you generate XML beans types with above changes, it will generate a
> Address type object which will have methods to check whether USAddress
> is set or the Other Address. No need of instanceof check. Do take a
> look at the generated method signatures of the Address XML type
> object, it should give you an idea to play with it.
> That said, this is just an another way of handling inheritance. I
> would like to see XML beans to inherantly support the polymorphism.
> Ramesh
> [Quoted text hidden]
> --------
> From: Bo Xie <mrboxie@gmail.com>
> To: axis-user@ws.apache.org
> Date: Wed, Jan 3, 2007 at 10:50 PM
> Hi Ajith,
>    The Address class only has getter and setter for name, city etc. No getAddress. Do
you see this ignoring of xsi:type in creating instance as a bug?
>    Besides using choice option as Ramesh suggested, do we run out of luck here? I am
a little hesitate to use choice as in my case, the choice list changes quite fast. Keeping
track of the exhaustive list of all the choices is a challenge.
> Thanks,
> -Bo
> [Quoted text hidden]
> --------
> From: Ajith Ranabahu <ajith.ranabahu@gmail.com>
> Reply-To: axis-user@ws.apache.org
> To: axis-user@ws.apache.org
> Date: Thu, Jan 4, 2007 at 5:08 AM
> Hi,
> > Hi Ajith,
> >
> >    The Address class only has getter and setter for name, city etc. No
> > getAddress. Do you see this ignoring of xsi:type in creating instance as a
> > bug?
> Yep. It is a bug. But AFAIK it was reported to be working. In any case
> you can file a Jira with your schema.
> Ajith

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: axis-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: axis-dev-help@ws.apache.org


Mime
View raw message