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 <[EMAIL PROTECTED]> 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
On 1/17/07, Bo Xie <[EMAIL PROTECTED]> wrote:
>
> Hi Ramesh,
>
> Sorry to get back on this late.
>
> I noticed that the same code behave differently when invoked
> standalone(from main()), or from the service.
>
> From standalone, the xsi:type are in the XML properly(same as your
> test). While from service, the xsi:type attribute are missing. Please see
> attached file test program. They are calling the same
> method(populateAddress().
>
> I am just wondering if there is any setting on the service side that may
> influence the generation of the xsi:type?
>
> Below are the XML output from two cases and the populateAddress method.
>
> Thanks,
> -Bo
>
> XML dump when running from main(). xsi:type is generated.
>
> <xsd:getAddressesResponse xmlns:xsd=" http://quickstart.samples/xsd">
> <xsd:addresses xsi:type="xsd:US-Address" xmlns:xsi="
> http://www.w3.org/2001/XMLSchema-instance">
> <xsd:city>Sunnyvale</xsd:city>
> <xsd:name>XYZ</xsd:name>
> <xsd:state>CA</xsd:state>
> <xsd:zip>94087</xsd:zip>
> </xsd:addresses>
> <xsd:addresses xsd:export-code="66553322" xsi:type="xsd:EU-Address"
> xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance">
> <xsd:city>Hongkong</xsd:city>
> <xsd:name>XYZ</xsd:name>
> <xsd:postcode>2300331 E.C</xsd:postcode>
> </xsd:addresses>
> </xsd:getAddressesResponse>
>
> XML dump when running as service. xsi:type is missing.
>
> <xsd:getAddressesResponse xmlns:xsd=" http://quickstart.samples/xsd ">
> <xsd:addresses>
> <xsd:city>Sunnyvale</xsd:city>
> <xsd:name>XYZ</xsd:name>
> <xsd:state>CA</xsd:state>
> <xsd:zip>94087</xsd:zip>
> </xsd:addresses>
> <xsd:addresses xsd:export-code="66553322">
> <xsd:city>Hongkong</xsd:city>
> <xsd:name>XYZ</xsd:name>
> <xsd:postcode>2300331 E.C</xsd:postcode>
> </xsd:addresses>
> </xsd:getAddressesResponse>
>
> The populateAddress method.
>
> private static void populateAddress(GetAddressesResponseDocument resDoc)
> {
> // TODO Auto-generated method stub
> GetAddressesResponseDocument.GetAddressesResponse res =
> resDoc.addNewGetAddressesResponse();
> samples.quickstart.service.xmlbeans.xsd.Address[] addArray = new
> samples.quickstart.service.xmlbeans.xsd.Address [2];
> samples.quickstart.service.xmlbeans.xsd.USAddress addr =
> samples.quickstart.service.xmlbeans.xsd.USAddress.Factory.newInstance();
>
> //samples.quickstart.service.xmlbeans.xsd.USAddress addr =
> samples.quickstart.service.xmlbeans.xsd.USAddress.Factory.newInstance();
> addr.setName("XYZ");
> addr.setCity("Sunnyvale");
> addr.setState(USState.CA);
> addr.setZip (new BigInteger("94087"));
>
>
> //samples.quickstart.service.xmlbeans.xsd.EUAddress addr1 =
> (EUAddress) res.addNewAddresses().changeType(EUAddress.type);
> samples.quickstart.service.xmlbeans.xsd.EUAddress addr1 =
> samples.quickstart.service.xmlbeans.xsd.EUAddress.Factory.newInstance();
> addr1.setName("XYZ");
> addr1.setCity("Hongkong");
> addr1.setExportCode(new BigInteger("66553322"));
> addr1.setPostcode("2300331 E.C");
>
> addArray[0] = addr;
> addArray[1] = addr1;
>
> res.setAddressesArray(addArray);
>
> XmlOptions ops = new XmlOptions();
> ops.setSavePrettyPrint();
> ops.setSavePrettyPrintIndent(4);
> //String xmlStr = res.xmlText(ops);
> //System.out.println("Response Element String: \n" + xmlStr);
> String xmlStr1 = resDoc.xmlText(ops);
> System.out.println("Response Document String: \n" + xmlStr1);
> }
>
>
>
> On 1/8/07, Ramesh Gurunathan < [EMAIL PROTECTED]> wrote:
> >
> > Hi Bo,
> >
> > Sorry for getting back so late. I missed your mail from my email pool.
> >
> > I indeed used axis2 1.1 and with xbean-2.2.0.jar that is shipped with
> > the release. This is what I did to prove that polymorphism in XML
> > works. My schema defines three complex types - BaseAddress, USAddress,
> > and UKAddress. The second item extends first and the third item
> > extends second. There is an element called 'UpdateCustomerAddress'
> > that includes, by signature, type BaseAddress unbounded. The element
> > could be used in the WSDL messages, but I didn't want go there.
> >
> > Now I complied the schema using the schema compiler tool from XML
> > beans. (It makes no difference whether you use WSDL2Java of axis2 or
> > directly compile using scomp of XML beans).
> >
> > I then wrote a test class, which uses the XML beans classes generated
> > classes, to verify the runtime object type for the address property in
> > UpdateCustomerAddress document. Please refer to the attachment for the
> >
> > schema and test class.
> >
> > In essence, the test class creates an XML programmatically, which
> > contains a BaseAddress, an USAddress, and UKAddress all bound to the
> > addresses property. Then it dumps the objects into XML, re-parses it,
> > and examines the objects using instanceof operator to ensure that the
> > types are correctly created. The test output is also in the
> > attachment.
> >
> > TIP: I am not sure if this is significant, but ensure that your
> > schema's elementFormDefault is "qualified"
> >
> > I hope this helps you.
> >
> > Ramesh
> >
> > On 1/9/07, Bo Xie < [EMAIL PROTECTED]> wrote:
> > > Hi Ramesh,
> > >
> > > Did you by any chance use Axis2 1.1.1 instead of 1.1 for your
> > testing?
> > > If you indeed used 1.1 only, can you give some details on how did
> > you test
> > > the instanceof? BTW, I opened AXIS2-1938 for this issue before saw
> > your last
> > > reply.
> > >
> > > Thanks,
> > > -Bo
> > >
> > >
> > > On 1/5/07, Bo Xie <[EMAIL PROTECTED] > wrote:
> > > > Hi Ramesh,
> > > >
> > > > It is comforting to know it actually works. Thanks for trying
> > it out.
> > > >
> > > > I was using axis2. 1.1 and I just reinstall the axis2 1.1 and
> > tried it
> > > again, still get the same problem. I have two question.
> > > > 1. When you mentioned XML Bean 2.2.0, it is the one
> > xbean-2.2.0.jar
> > > comes with the axis2 package, not an outside jar, right?
> > > > 2. Do you mind share the test wsdl and the source file that
> > you did
> > > the instanceof test. I would like to see if I am not doing the right
> > thing
> > > using the generated object. Did you see the xsi:type in the soap
> > message for
> > > both directions?
> > > >
> > > > Thanks,
> > > > -Bo
> > > >
> > > >
> > > >
> > > > On 1/5/07, Ramesh Gurunathan < [EMAIL PROTECTED]> wrote:
> > > > > Hi Guys,
> > > > >
> > > > > I tested this today against axis2 1.1 [XML beans 2.2.0]. It
> > actually
> > > > > works. The instanceof check passes. I then switched to Debug
> > > > > perspective to introspect the object type, everything looks
> > perfect.
> > > > >
> > > > > Bo - Try again and see if you can duplicate the problem in axis2
> > 1.1
> > > > >
> > > > > Ramesh
> > > > >
> > > > > On 1/4/07, Ajith Ranabahu < [EMAIL PROTECTED]> wrote:
> > > > > > 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
> > > > > >
> > > > > >
> > >
> > ---------------------------------------------------------------------
> > > > > > To unsubscribe, e-mail:
> > > [EMAIL PROTECTED]
> > > > > > For additional commands, e-mail: [EMAIL PROTECTED]
> > > > > >
> > > > > >
> > > > >
> > > > >
> > >
> > ---------------------------------------------------------------------
> > > > > To unsubscribe, e-mail:
> > > [EMAIL PROTECTED]
> > > > > For additional commands, e-mail: [EMAIL PROTECTED]
> > > > >
> > > > >
> > > >
> > > >
> > >
> > >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> >
> >
>
>