[betwixt] Making deserialise work like serialise (long)

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[betwixt] Making deserialise work like serialise (long)

Ricardo Gladwell
Hi All,

I'm using an external XML syntax to read and write data for payment
transactions. The format for specifying bank accounts is as follows:

<shopper>
   <bankAccount>
     <bankAcount-GB>...</bankAccount-GB>
   </bankAccount>
</shopper>

Rather than nest the country-specific bank account within a generic bank
account, I just have a shopper and bank account bean as follows:

public class Shopper {

   BankAccount bankAccount;

   public BankAccount getBankAccount() {..}
   public void setBankAccount(BankAccount ba) {..}

}

public abstract class BankAccount {...}

public class BritishBankAccount extends BankAccount {...}

To serialise this I have the following betwixt files:

# Shopper.betwixt
<?xml version="1.0" encoding="UTF-8" ?>
<info primitiveTypes="element">
   <element name="shopper">
     <element name="bankAccount" property="bankAccount" />
   </element>
</info>

# BritishBankAccount.bwtwixt
<?xml version="1.0" encoding="UTF-8" ?>
<info primitiveTypes="element">
   <element name="bankAccount">
     <element name="bankAccount-GB">
       ...
     </element>
   </element>
</info>

When serializing this creates the nested bank account tags for the
extenal XML representation without requiring an additional bean "layer"
for the bank account and country-specific bank account. However, when
deserialising with the above as standard, the bank account property of
the shopper bean is set to null.

How can I simulate this behaviour for serialisation? That is, how do I
force betwixt to interpret the bank account and generate an appropriate
country specific bank account, placing it into the bank account property
of the shopper, without having to create an additional bean for generic
bank account to hold the country-specific bank account.

Phew, I hope that is clear!

Kind regards...

-- Ricardo Gladwell

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [betwixt] Making deserialise work like serialise (long)

robert burrell donkin
On Tue, 2005-07-12 at 15:47 +0100, Ricardo Gladwell wrote:
> Hi All,

hi Ricardo

> How can I simulate this behaviour for serialisation? That is, how do I
> force betwixt to interpret the bank account and generate an appropriate
> country specific bank account, placing it into the bank account property
> of the shopper, without having to create an additional bean for generic
> bank account to hold the country-specific bank account.
>
> Phew, I hope that is clear!

very clear, thanks :)

i think the problem is to do with dealing with the subclassing. (this is
often known as the derived beans problem.) there is some limited support
in betwixt for derived beans
(http://jakarta.apache.org/commons/betwixt/guide/derived.html) but it's
not as generic or comprehensive as it should be. unfortunately, the
current level of support won't do what you need it to do and the support
you need is unlikely to be added soon enough for you.

so, i'm going to suggest that you adopt an approach that will work but
requires a little more work on your part.

i suggest that you being by getting hold of the betwixt source (either
from subversion see http://jakarta.apache.org/site/cvsindex.html or from
the latest release candidate
http://people.apache.org/~rdonkin/commons-betwixt/). you need to create
a custom ChainedBeanCreator which creates the right bean based on the
element type (take a look at ChainedBeanCreatorFactory for example of
creating a bean on the basis of an attribute value) and then add it to
the chain used to create new beans (see
<a href="http://jakarta.apache.org/commons/betwixt/guide/reading.html#Reading%">http://jakarta.apache.org/commons/betwixt/guide/reading.html#Reading%
20Beans%20-%20In%20Depth). though you'll have to add an entry for each
subclass, it should work.

BTW any ideas about the best way to solve (or at least, chip away at)
the general problem would be gratefully received

- robert


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [betwixt] Making deserialise work like serialise (long)

Ricardo Gladwell
In reply to this post by Ricardo Gladwell
robert burrell donkin wrote:

> On Tue, 2005-07-12 at 15:47 +0100, Ricardo Gladwell wrote:
>> Hi All,
>
> hi Ricardo
>
>> How can I simulate this behaviour for serialisation? That is, how do I
>> force betwixt to interpret the bank account and generate an appropriate
>> country specific bank account, placing it into the bank account property
>> of the shopper, without having to create an additional bean for generic
>> bank account to hold the country-specific bank account.
>
> i suggest that you being by getting hold of the betwixt source (either
> from subversion see http://jakarta.apache.org/site/cvsindex.html or from
> the latest release candidate
> http://people.apache.org/~rdonkin/commons-betwixt/). you need to create
> a custom ChainedBeanCreator which creates the right bean based on the
> element type (take a look at ChainedBeanCreatorFactory for example of
> creating a bean on the basis of an attribute value) and then add it to
> the chain used to create new beans (see
> <a href="http://jakarta.apache.org/commons/betwixt/guide/reading.html#Reading%">http://jakarta.apache.org/commons/betwixt/guide/reading.html#Reading%
> 20Beans%20-%20In%20Depth). though you'll have to add an entry for each
> subclass, it should work.

Thanks for the above. Unfortunately, the dependencies for the project
I'm working on are quite strict and it wouldn't be possible to use
snapshot code as you suggest above (it is worth noting the Maven
repository on Ibiblio for this project is out of date, snapshots and
all). Otherwise, implementing your own ChainedBeanCreator and modifying
the bean creator chain is a very good idea.

In the end, I cheated and hard-coded XPath to read specific bank
accounts using the BeanReader.registerBeanClass method:

reader.registerBeanClass("//bankAccount[bankAccount-AT]",
AustrianBankAccount.class);

And reading the file twice: once for the XML file, and again to extract
bank details and "manually" insert them into the appropriate bean. That
said, the bank accounts do not seem to be being read properly and the
parse() method returns null. Not sure what might be causing this.

> BTW any ideas about the best way to solve (or at least, chip away at)
> the general problem would be gratefully received

Not sure this problems is resolvable: it means creating a reverse of the
betwixt file and applying it intelligently to XML reading. For example,
the following betwixt file:

<!-- AustrianBankAccount.betwixt -->
<?xml version="1.0" encoding="UTF-8" ?>
<info primitiveTypes="element">
   <element name="bankAccount">
     <element name="bankAccount-AT">...

Would have to be interpreted as being /bankAccount[bankAccount-AT] ->
AustrianBankAccount. How would BeanReader be able to grasp this is what
is wanted from the above than, for example, the bankAccount-AT refers to
a property of the AustrianBankAccount bean, for example? Some sort of
intelligent comparison between the betwixt file and the bean object
model would be required to interpolate expected behaviour. Perhaps some
sort of additional scripting would be required?

Kind regards...

-- Ricardo Gladwell

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [betwixt] Making deserialise work like serialise (long)

robert burrell donkin
On Thu, 2005-07-14 at 17:46 +0100, Ricardo Gladwell wrote:

> robert burrell donkin wrote:
> > On Tue, 2005-07-12 at 15:47 +0100, Ricardo Gladwell wrote:
> >> Hi All,
> >
> > hi Ricardo
> >
> >> How can I simulate this behaviour for serialisation? That is, how do I
> >> force betwixt to interpret the bank account and generate an appropriate
> >> country specific bank account, placing it into the bank account property
> >> of the shopper, without having to create an additional bean for generic
> >> bank account to hold the country-specific bank account.
> >
> > i suggest that you being by getting hold of the betwixt source (either
> > from subversion see http://jakarta.apache.org/site/cvsindex.html or from
> > the latest release candidate
> > http://people.apache.org/~rdonkin/commons-betwixt/). you need to create
> > a custom ChainedBeanCreator which creates the right bean based on the
> > element type (take a look at ChainedBeanCreatorFactory for example of
> > creating a bean on the basis of an attribute value) and then add it to
> > the chain used to create new beans (see
> > <a href="http://jakarta.apache.org/commons/betwixt/guide/reading.html#Reading%">http://jakarta.apache.org/commons/betwixt/guide/reading.html#Reading%
> > 20Beans%20-%20In%20Depth). though you'll have to add an entry for each
> > subclass, it should work.
>
> Thanks for the above. Unfortunately, the dependencies for the project
> I'm working on are quite strict and it wouldn't be possible to use
> snapshot code as you suggest above (it is worth noting the Maven
> repository on Ibiblio for this project is out of date, snapshots and
> all).

it's a bit complicated by the fact that it's a release candidate (not a
SNAPSHOT). release candidates should not be uploaded to ibiblio (or any
other mirror). but thank's for the warning: i will remember to try to
check that the maven repository is right when the full release is cut.

> Otherwise, implementing your own ChainedBeanCreator and modifying
> the bean creator chain is a very good idea.

i think i managed to confuse matters a little (in the rush).

the chain is pluggable: just implement the interface and plug it in.

the reason why i suggested obtaining the source is that the code
contains better examples than the documentation. (no changes are needed
to the source to create a custom creation chain.)

FYI the release candidate is very close now to being accepted as betwixt
0.7. it is strongly recommended that all users upgrade to this new
version.

> In the end, I cheated and hard-coded XPath to read specific bank
> accounts using the BeanReader.registerBeanClass method:
>
> reader.registerBeanClass("//bankAccount[bankAccount-AT]",
> AustrianBankAccount.class);
>
> And reading the file twice: once for the XML file, and again to extract
> bank details and "manually" insert them into the appropriate bean. That
> said, the bank accounts do not seem to be being read properly and the
> parse() method returns null. Not sure what might be causing this.

it is possible to make betwixt work that way (you can integrate it with
digester rules) but it's pretty black belt...  

> > BTW any ideas about the best way to solve (or at least, chip away at)
> > the general problem would be gratefully received
>
> Not sure this problems is resolvable: it means creating a reverse of the
> betwixt file and applying it intelligently to XML reading. For example,
> the following betwixt file:
>
> <!-- AustrianBankAccount.betwixt -->
> <?xml version="1.0" encoding="UTF-8" ?>
> <info primitiveTypes="element">
>    <element name="bankAccount">
>      <element name="bankAccount-AT">...
>
> Would have to be interpreted as being /bankAccount[bankAccount-AT] ->
> AustrianBankAccount. How would BeanReader be able to grasp this is what
> is wanted from the above than, for example, the bankAccount-AT refers to
> a property of the AustrianBankAccount bean, for example?

exactly :)

i've seen some mappers do things using reflection to determine
inheritance but in the end they still need to know the names of the
classes involved so i'm not sure how much is gained...

> Some sort of
> intelligent comparison between the betwixt file and the bean object
> model would be required to interpolate expected behaviour. Perhaps some
> sort of additional scripting would be required?

scripting sounds very interesting (hadn't really thought about it
before). betwixt is generally declarative but maven's mix of declarative
data and scripting works very well. how do you see this working?

one way to solve your narrow problem would be to create a custom chain
bean creator using an option to pass element name -> class name mappings
through and add that to the default chain. if you need to use full
releases, then it'd probably be a little too late, though...

- robert


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [betwixt] Making deserialise work like serialise (long)

robert burrell donkin
In reply to this post by Ricardo Gladwell
On Tue, 2005-07-12 at 15:47 +0100, Ricardo Gladwell wrote:

> Hi All,
>
> I'm using an external XML syntax to read and write data for payment
> transactions. The format for specifying bank accounts is as follows:
>
> <shopper>
>    <bankAccount>
>      <bankAcount-GB>...</bankAccount-GB>
>    </bankAccount>
> </shopper>

i was wonder whether this structure is by design or just because Betwixt
forces it...

would (for example) the following be better?

<shopper>
        <bank-account-gb>...</bank-account-gb>.
</shopper>

(if betwixt could map it appropriately)

- robert


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [betwixt] Making deserialise work like serialise (long)

Ricardo Gladwell
In reply to this post by Ricardo Gladwell
> On Tue, 2005-07-12 at 15:47 +0100, Ricardo Gladwell wrote:
> i was wonder whether this structure is by design or just because Betwixt
> forces it...
>
> would (for example) the following be better?
>
> <shopper>
> <bank-account-gb>...</bank-account-gb>.
> </shopper>
>
> (if betwixt could map it appropriately)
>
> - robert

Unfortunately, I have no control over the XML syntax: its an format
we're using for an external web service developed by another company :)
Would that I could amend their poorly-designed syntax.

-- Ricardo


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [betwixt] Making deserialise work like serialise (long)

Ricardo Gladwell
In reply to this post by Ricardo Gladwell
robert burrell donkin wrote:
> On Thu, 2005-07-14 at 17:46 +0100, Ricardo Gladwell wrote:
> it's a bit complicated by the fact that it's a release candidate (not a
> SNAPSHOT). release candidates should not be uploaded to ibiblio (or any
> other mirror). but thank's for the warning: i will remember to try to
> check that the maven repository is right when the full release is cut.

Please do update it for the final release: so few project maintainers do
properly update the Maven repository and that extra work is really
appreciated by us downstream Maven users :) Shouldn't the Maven
repository have the latest CVS code in it's snapshot release, though?

> FYI the release candidate is very close now to being accepted as betwixt
> 0.7. it is strongly recommended that all users upgrade to this new
> version.

I'm confused by the above: some of the artefacts in the maven repository
are listed as 1.0-dev and -beta, yet 0.7 will be the next release version?

>> In the end, I cheated and hard-coded XPath to read specific bank
>> accounts using the BeanReader.registerBeanClass method:
>
> it is possible to make betwixt work that way (you can integrate it with
> digester rules) but it's pretty black belt...

Not sure what else to do at this point (BTW, what does "black belt"
mean? I'm familiar but not sure). Even the above does not seem to be
working.

>> Some sort of
>> intelligent comparison between the betwixt file and the bean object
>> model would be required to interpolate expected behaviour. Perhaps some
>> sort of additional scripting would be required?
>
> scripting sounds very interesting (hadn't really thought about it
> before). betwixt is generally declarative but maven's mix of declarative
> data and scripting works very well. how do you see this working?

Actually, I was thinking an entirely different approach might be
required: instead of having a XML configuration file describing how to
convert a bean to XML (one way) it would be better to map individual
properties to XML constructs using xdoclet tags or annotation, as in
Hibernate. This ensures relationships are two way and more easily
reversible. For example:

/**
  * @betwixt.xml
  *    path="bankAccount/bankAccount-AT"
  */
public class AustrianBankAccount {...}

Would mean that an occurrences of AustrianBankAccount could be clearly
read and written as <bankAccount><bankAccount-AT>... for example without
any confusion over how it should be interpreted.

P.S. If you could please CC responses to my home address I would be most
grateful. I'm not actually subscribed to this mailing list.

Kind regards...

-- Ricardo

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [betwixt] Making deserialise work like serialise (long)

robert burrell donkin
(back from apachecon now)

On Fri, 2005-07-15 at 12:26 +0100, Ricardo Gladwell wrote:

> robert burrell donkin wrote:
> > On Thu, 2005-07-14 at 17:46 +0100, Ricardo Gladwell wrote:
> > it's a bit complicated by the fact that it's a release candidate (not a
> > SNAPSHOT). release candidates should not be uploaded to ibiblio (or any
> > other mirror). but thank's for the warning: i will remember to try to
> > check that the maven repository is right when the full release is cut.
>
> Please do update it for the final release: so few project maintainers do
> properly update the Maven repository and that extra work is really
> appreciated by us downstream Maven users :) Shouldn't the Maven
> repository have the latest CVS code in it's snapshot release, though?

AIUI the apache releases at the maven repository at ibiblio are sync'd
from the from the apache repository. apache only allows full official
releases to be served from that repository. snapshots are uploaded by
the maven team manually but are not official apache releases. it is
common for snapshots to be out of date.

> > FYI the release candidate is very close now to being accepted as betwixt
> > 0.7. it is strongly recommended that all users upgrade to this new
> > version.
>
> I'm confused by the above: some of the artefacts in the maven repository
> are listed as 1.0-dev and -beta, yet 0.7 will be the next release version?

when betwixt was originally promoted from the sandbox, the number was
1.0 and the alpha was cut. the numbering system was then revised to
reflect more accurately the actual state of the betwixt (of release
quality but with an unstable interface and feature incomplete) starting
with 0.5 so that users requiring full, official releases could use
betwixt.

see http://jakarta.apache.org/commons/betwixt/

> >> In the end, I cheated and hard-coded XPath to read specific bank
> >> accounts using the BeanReader.registerBeanClass method:
> >
> > it is possible to make betwixt work that way (you can integrate it with
> > digester rules) but it's pretty black belt...
>
> Not sure what else to do at this point (BTW, what does "black belt"
> mean? I'm familiar but not sure).

just a friendly way of saying expert user :)

> Even the above does not seem to be
> working.

you'll find it tough because you need to use additional digester rules.
there are a lot of wrinkles and so i won't recommend that you go down
this path...

> >> Some sort of
> >> intelligent comparison between the betwixt file and the bean object
> >> model would be required to interpolate expected behaviour. Perhaps some
> >> sort of additional scripting would be required?
> >
> > scripting sounds very interesting (hadn't really thought about it
> > before). betwixt is generally declarative but maven's mix of declarative
> > data and scripting works very well. how do you see this working?
>
> Actually, I was thinking an entirely different approach might be
> required: instead of having a XML configuration file describing how to
> convert a bean to XML (one way) it would be better to map individual
> properties to XML constructs using xdoclet tags or annotation, as in
> Hibernate. This ensures relationships are two way and more easily
> reversible. For example:
>
> /**
>   * @betwixt.xml
>   *    path="bankAccount/bankAccount-AT"
>   */
> public class AustrianBankAccount {...}
>
> Would mean that an occurrences of AustrianBankAccount could be clearly
> read and written as <bankAccount><bankAccount-AT>... for example without
> any confusion over how it should be interpreted.

it is possible that support for annotations may be added sometime (maybe
soonish) but betwixt still needs to know which classes you intend to
include.

i now suspect that the problem is that polymorphic mappings are
supported fully only for collectives. (i added more information to the
documentation:
<a href="http://jakarta.apache.org/commons/betwixt/guide/derived.html#Mapping%">http://jakarta.apache.org/commons/betwixt/guide/derived.html#Mapping%
20An%20Element%20To%20A%20Class%20Name which might help explain what i
mean). i'll try to find some time to add this feature this week (but i
can't promise when). if anyone wants to jump in and volunteer to code
this feature, it'd probably speed things up and i'd provide help.

- robert


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]