To add to my last posting...
On Mon, 2006-01-09 at 10:09 -0500, Sandeep Khanna wrote:
> Read comments inline.
>
> On Fri, 2006-01-06 at 23:44 -0600, Keith Visco wrote:
> > Sandeep,
> >
> > See inline comments...
> >
> > Sandeep Khanna wrote:
> > > Keith,
> > >
> > > Thanks for your valuable info.
> > >
> > > A few questions:
> > >
> > > On Thu, 2006-01-05 at 22:29 -0600, Keith Visco wrote:
> > >
> > >>You can create a custom field handler to be your GUID generator.
> > >>
> > >>And then use the following mapping:
> > >>
> > >><class name="...ClientDcl" identity="clientGUID">
> > >> <map-to xml="ClientDcl"/>
> > >> ...
> > >> <field name="clientGUID" handler="MyGUIDHandler"/>
> > >> <bind-xml name="ClientGUID"/>
> > >> </field>
> > >> ...
> > >></class>
> > >
> > >
> > > I want the 'MyGUIDHandler' to be invoked only while Unmarshalling
> > > objects and not while Marshalling them.
> > >
> > > While marshalling, the objects being marshalled already have the GUIDs
> > > correctly set on them and is just a matter of printing them out.
> > >
> >
> > Ah ok, well that's easy enough to tweak your handler so that it doesn't
> > generate a GUID during marshalling...just have your handler can check
> > the respective field in the target object to see if the GUID has been
>
> > set, if so, just return it, if not it can generate one. So during
> > marshalling, since the GUID has already been set in the target object,
> > it will just return that value.
> >
> > > While unmarshalling the XML element placeholders are a hint to the
> > > Unmarshaller to create & populate the GUIDs on the objects being created
> > > from XML.
> > >
> > > Is this possible?
> >
> > See my comments above. However, I guess I'm a bit confused on what you
> > call a "placeholder". Castor will need an ID to be present in the XML
> > during unmarshalling or it won't know which object to reference.
>
> Objects created in the application would already have the GUIDs
> generated & correctly set on the parent/child objects. These objects
> will be marshalled into something like:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <AsClient>
> <ClientGUID>34AECA5B-C757-9352-0DE2-5A2144ADC7BC</ClientGUID>
> <Sex>M</Sex>
> <DateOfBirth>1970-01-01T00:00:00.000-05:00</DateOfBirth>
> <TypeCode>02</TypeCode>
> <TaxID>999-99-9999</TaxID>
> <FirstName>Sandeep</FirstName>
> <MiddleInitial>T</MiddleInitial>
> <LastName>Khanna</LastName>
> <Fields>
> <AsClientField>
> <key>PhoneType4</key>
> <value>
>
> <ClientGUID>34AECA5B-C757-9352-0DE2-5A2144ADC7BC</ClientGUID>
> <FieldName>PhoneType4</FieldName>
> <TextValue>00</TextValue>
> <FieldTypeCode>02</FieldTypeCode>
> </value>
> </AsClientField>
> </Fields>
> </AsClient>
>
> This XML will be sent out over the internet via web service calls to a
> remote system.
>
> GUID generation is specific to the original system.
>
> A remote system may decide to share Client data via XML but does not
> generate the GUIDs. We insert placeholders in the incoming XML to
> indicate to the Unmarshaller to create new GUIDs and populate them on
> the objects being unmarshalled. The incoming XML may look like:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <AsClient>
> <ClientGUID/>
> <Sex>M</Sex>
> <DateOfBirth>1970-01-01T00:00:00.000-05:00</DateOfBirth>
> <TypeCode>02</TypeCode>
> <TaxID>999-99-9999</TaxID>
> <FirstName>Sandeep</FirstName>
> <MiddleInitial>T</MiddleInitial>
> <LastName>Khanna</LastName>
> <Fields>
> <AsClientField>
> <key>PhoneType4</key>
> <value>
> <ClientGUID/>
> <FieldName>PhoneType4</FieldName>
> <TextValue>00</TextValue>
> <FieldTypeCode>02</FieldTypeCode>
> </value>
> </AsClientField>
> </Fields>
> </AsClient>
>
> To summarize, the marshalled XML is *not* the input for the
> Unmarshaller.
>
> >
> > >
> > >
> > >>Once you have your GUID generator working you can then add the following
> > >>to your mapping file:
> > >>
> > >><class name="...AddressRoleDcl">
> > >> <map-to xml="AddressRoleDcl"/>
> > >> ...
> > >> <field name="clientGUID" reference="true">
> > >> <bind-xml name="ClientGUID" node="element"/>
> > >> </field>
> > >> ...
> > >></class>
> > >
> > >
> > > After looking at the Castor docs, it appears that the attribute
> > > 'reference' is available on element 'bind-xml' rather than on 'field'.
> > > Is that correct?
> > >
> >
> > That sounds right...sorry for the confusion...you can place the
> > reference="true" on the bind-xml element.
> >
> > > By just saying reference="true" as shown above, how does the
> > > Unmarshaller know that it has to reference the parent/contained object's
> > > 'clientGuid' property. Don't we have to say reference so & so property
> > > name from the parent object? Or do the property names have to be same on
> > > the parent & the contained/child object?
> >
> > Ah yes, I knew I left out an important note. The GUID must be
> > document-unique. Basically references are treated as ID/IDREF within the
> > XML, which means each ID must be unique within the document, regardless
> > of the element name.
> >
> > During unmarshalling when Castor finds a field marked as a reference it
> > will find the object with the given ID and set the associated field with
> > that object.
> >
> > >
> > >
> > >>
> > >>Keep in mind that your handler (your GUID generator) will need to keep
> > >>track of GUIDs during the marshalling for each object that it generates
> > >>a GUID for so that when the handler is called again for the same object
> > >>it will return the correct GUID for that object as your handler will get
> > >>called each time it needs to output the GUID. This will be once for the
> > >>object itself and then once for each reference to the object.
> > >
> > >
> > > As per my comments above, I just need the GUID generation & setting
> > > functionality while Unmarshalling. Do you still see an issue here?
> > >
> >
> > Yes, I do seen an issue here, because for your fields that reference
> > another object Castor will need to know it's ID in order to resolve the
> > field properly during unmarshalling.
> >
> > So I guess I'm now having trouble understanding how you expect things to
> > work. During marshalling, you say the object already has a GUID...so
> > Castor will just print it out...which is fine...but how does that go
> > from having an actual GUID that got printed out into the XML to just
> > being a place holder which needs to generate a GUID upon unmarshalling
> > back to an object? Shouldn't the GUID still exist in the XML from the
> > marshalling?
>
> >From above the marshalled XML is *not* the input for the Unmarshaller.
>
> >
> > I guess I need more explaination in order to help you come up with a
> > solution.
>
> My current mapping file is:
>
> <?xml version="1.0" encoding="UTF-8"?>
> <mapping>
> <!--
> =================================================================== -->
> <!-- Mapping for class com.adminserver.dcl.ClientDcl -->
> <!--
> =================================================================== -->
> <class name="com.adminserver.dcl.ClientDcl" identity="clientGuid"
> access="shared"
> auto-complete="false">
> <map-to table="AsClient" xml="AsClient"/>
> <field name="clientGuid" type="string"
> get-method="getClientGuid"
> set-method="setClientGuid"
> handler="com.adminserver.utl.MyGuidHandler">
> <bind-xml name="ClientGUID" node="element"/>
> </field>
> <field name="firstName" type="string" get-method="getFirstName"
> set-method="setFirstName">
> <bind-xml name="FirstName" node="element"/>
> </field>
> <field name="lastName" type="string" get-method="getLastName"
> set-method="setLastName">
> <bind-xml name="LastName" node="element"/>
> </field>
> <field name="fields" type="com.adminserver.dcl.ClientFieldDcl"
> get-method="getFields"
> set-method="setFields" collection="map">
> <bind-xml name="AsClientField" node="element"
> location="Fields">
> <class name="org.exolab.castor.mapping.MapItem">
> <field name="key" type="java.lang.String" >
> <bind-xml name="key"/>
> </field>
> <field name="value"
> type="com.adminserver.dcl.ClientFieldDcl">
> <bind-xml name="value"/>
> </field>
> </class>
> </bind-xml>
> </field>
> </class>
> <!--
> =================================================================== -->
> <!-- Mapping for class com.adminserver.dcl.ClientFieldDcl -->
> <!--
> =================================================================== -->
> <class name="com.adminserver.dcl.ClientFieldDcl"
> identity="clientGuid fieldName"
> access="shared" auto-complete="false">
> <map-to table="AsClientField" xml="AsClientField"/>
> <field name="clientGuid" type="string"
> get-method="getClientGuid"
> set-method="setClientGuid">
> <bind-xml name="ClientGUID" node="element"
> type="com.adminserver.dcl.ClientDcl"
> reference="true"/>
> </field>
Since the <bind-xml reference="true"> depends on the enclosing <field>
element's 'type' attribute value. Can something along these lines work?
<field name="clientGuid" type="string" get-method="getClientGuid"
set-method="setClientGuid">
<bind-xml name="ClientGUID" node="element">
<class name="java.lang.String">
<field name="clientGuid"
type="com.adminserver.dcl.ClientDcl" required="false">
<bind-xml name="ClientGUID"
reference="true" ></bind-xml>
</field>
</class>
</bind-xml>
</field>
Also, isn't there some way for one to get the property value as a text
element in the mapping (sort of like a reference).
What is the "property" element in bind-xml for?
<bind-xml name="" node="element">
<property>
<name></name>
<value></value>
</property>
</bind-xml>
> <field name="fieldName" type="string" get-method="getFieldName"
> set-method="setFieldName">
> <bind-xml name="FieldName" node="element"/>
> </field>
> <field name="textValue" type="string" get-method="getTextValue"
> set-method="setTextValue">
> <bind-xml name="TextValue" node="element"/>
> </field>
> </class>
> </mapping>
>
> With the above mapping in place, I get the following Exception:
>
> [DEBUG]: (TestXMLBindingFrameworks.testCastor:75) - Unmarshalling AsXML
> to ClientDcl...
> [DEBUG]: (MyGuidHandler.convertUponSet:38) - original setValue value =
> [DEBUG]: (MyGuidHandler.convertUponSet:40) - new setValue value =
> 1402C8BA-6C29-FD7F-ED7D-ABADBB3BED06
> [DEBUG]: (TestXMLBindingFrameworks.testCastor:79) - Unmarshalling
> successful in 329 milliseconds.
> [DEBUG]: (TestXMLBindingFrameworks.testCastor:84) - Marshalling
> ClientDcl to AsXML ...
> Unable to resolve ID for instance of class 'java.lang.String' due to the
> following error: Unable to resolve ClassDescriptor.
> at org.exolab.castor.xml.Marshaller.getObjectID(Marshaller.java:2009)
> at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:1649)
> at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:1852)
> at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:1852)
> at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:1835)
> at org.exolab.castor.xml.Marshaller.marshal(Marshaller.java:842)
> at
> TestXMLBindingFrameworks.testCastor(TestXMLBindingFrameworks.java:86)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:324)
> at junit.framework.TestCase.runTest(TestCase.java:154)
> at junit.framework.TestCase.runBare(TestCase.java:127)
> at junit.framework.TestResult$1.protect(TestResult.java:106)
> at junit.framework.TestResult.runProtected(TestResult.java:124)
> at junit.framework.TestResult.run(TestResult.java:109)
> at junit.framework.TestCase.run(TestCase.java:118)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
>
> Shouldn't the following XML element make Castor to look for ClientDcl
> object's ID??
>
> <bind-xml name="ClientGUID" node="element"
> type="com.adminserver.dcl.ClientDcl"
> reference="true"/>
>
> But instead it is trying to lookup the ID for java.lang.String as per
> the following declaration in the ClientFieldDcl mapping:
>
> <field name="clientGuid" type="string"
> get-method="getClientGuid"
> set-method="setClientGuid">
>
> Also it sounds like you can use the reference="true" for referencing and
> setting the whole object and not just one of it's property! Is that
> true?
>
> In this case we just need the clientGuid property of the ClientDcl
> object and not the whole ClientDcl object!
>
> I am currently tasked with comparing Jibx (jibx.sf.net), Javolution
> (javolution.org) & Castor (castor.sf.net) with regards to Java <-> XML
> marshalling/unmarshalling. So far Castor seems to be a clear winner when
> it comes to supporting marshalling/unmarshalling most of the Java data
> structures with the exception of the above little requirement. The other
> solutions require addition of cryptic custom code to just handle say
> HashMaps.
>
> --Sandeep Khanna
>
> >
> > --Keith
> >
> >
> > -------------------------------------------------
> > If you wish to unsubscribe from this list, please
> > send an empty message to the following address:
> >
> > [EMAIL PROTECTED]
> > -------------------------------------------------
> >
>
>
> -------------------------------------------------
> If you wish to unsubscribe from this list, please
> send an empty message to the following address:
>
> [EMAIL PROTECTED]
> -------------------------------------------------
>
-------------------------------------------------
If you wish to unsubscribe from this list, please
send an empty message to the following address:
[EMAIL PROTECTED]
-------------------------------------------------