You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by Martin van den Bemt <ml...@mvdb.net> on 2002/12/09 13:30:36 UTC

[Fwd: Re: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions]

Wtf.. The reply didn't get to the list..

Mvgr,
Martin

-----Forwarded Message-----

From: Martin van den Bemt <ml...@mvdb.net>
To: darren@darrenscott.com
Subject: Re: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions
Date: 09 Dec 2002 13:24:02 +0100

On Sat, 2002-12-07 at 21:10, Darren Scott wrote:
> I'm just starting to use betwixt for serializing beans to XML for later
> transformation into XHTML using XSLT. Things are generally working OK so
> far, although getting it to work was a lot of trial and error
> (particularly because I couldn't find good information about how to use
> the .betwixt files anywhere!).
> 
> Can anyone please answer the following questions:
> 
> 1) Is there a complete reference for how to use .betwixt files? I've
> seen the overview and FAQ betwixt project pages, but nothing else in
> detail.

Not there isn't (besides digging into the sourcecode and trial & error).
We have to do something about this.. One note : a .betwixt is only for
the bean the .betwixt file is for. So if you use a Person bean which
also contains an Address beean, Person.betwixt cannot be used to alter
the address behaviour. (or at least doesn't give the required results..)

> 
> 2) How does betwixt use "add" methods exactly? What use are they to
> betwixt? What relation do they have to the "get" methods?

add is called when the getter returns a collection. 

> 
> 3) I seem to get CyclicReferenceExceptions when I don't expect to. Maybe
> it's my misunderstanding of what a graph cycle is, but I took it to mean
> when you get into an infinite cycle with references e.g. A refers to B,
> B refers to C, C refers to A, A refers to B etc. I get these exceptions
> raised when I have a collection containing multiple references to the
> same object. I wouldn't have expected this situation to be treated as a
> cycle.

The cyclic checking isn't that advanced yet. The scenario that A refers
to another A is covered however. Since the cyclic stuff also has some
relation when you use id's (and I am not into id's that much), I
probably have to have some help with the id handling.
Time to read some specs on that :)

I'll will try to answer your questions in more details by updating the
docs, which will describe the correct behaviour

Mvgr,
Martin




Re: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by robert burrell donkin <ro...@blueyonder.co.uk>.
On Sunday, December 15, 2002, at 09:54 PM, Darren Scott wrote:

<snip>

> While we're still on the subject of betwixt I'm still confused about its
> use of "add" methods on beans? Am I right in thinking that if I'm only
> using betwixt to write XML from a bean, the "add" methods don't come
> into it? If I'm wrong about this, how exactly do they get used (after
> all that means betwixt would be adding objects to a collection in my
> bean - how can that be?)

AFAIK they are only used when reading but i'm not 100% sure on this point.
  this is something that i need to look into anyway so i'll try to get back 
to you if i'm wrong.

BTW if you're into IRC there's a #betwixt channel on irc.werken.com where 
martin hangs out (a lot) and myself (sometimes).

- robert


RE: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by Darren Scott <da...@darrenscott.com>.
> many thanks for the patch.
> 
> i haven't used the code but it did prove very useful. the version i 
> committed uses instance equality (==) rather than equals to determine 
> whether a bean is it's own ancester. it also uses the stack 
> implementation 
> in jakarta-commons-collections for greater backwards 
> compatibility. in 
> addition, i've tried to protect the ways that subclasses can 
> access the 
> stack.
> 
> - robert

I'm glad the patch was of use - my first Jakarta code contribution! I'm
so proud... ;-)

While we're still on the subject of betwixt I'm still confused about its
use of "add" methods on beans? Am I right in thinking that if I'm only
using betwixt to write XML from a bean, the "add" methods don't come
into it? If I'm wrong about this, how exactly do they get used (after
all that means betwixt would be adding objects to a collection in my
bean - how can that be?)

Darren



Re: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by robert burrell donkin <ro...@blueyonder.co.uk>.
many thanks for the patch.

i haven't used the code but it did prove very useful. the version i 
committed uses instance equality (==) rather than equals to determine 
whether a bean is it's own ancester. it also uses the stack implementation 
in jakarta-commons-collections for greater backwards compatibility. in 
addition, i've tried to protect the ways that subclasses can access the 
stack.

- robert

On Saturday, December 14, 2002, at 12:23 AM, Darren Scott wrote:

>> as i said, i had planned to take a look at creating a fix in
>> any case. if
>> you do make progress before then let me know so that i can
>> look at adding
>> some other features instead :)
>>
>> - robert
>
> I think I've got a fix for unexpected CyclicReferenceExceptions. Robert
> asked me to provide a cvs diff -u for the fix - I've never used -u on
> diff before and it seemed to produce a LOT of output, so here's output
> from a regular diff between my working copy and the top of the source
> tree (1.6):
>
> RCS file:
> /home/cvspublic/jakarta-commons/betwixt/src/java/org/apache/commons/betw
> ixt/io/AbstractBeanWriter.java,v
> retrieving revision 1.6
> diff -w -r1.6 AbstractBeanWriter.java
> 71a72
>> import java.util.Stack;
> 106a108,109
>>     /** Stack containing ID attribute values for beans seen so far in
> this graph */
>>     protected Stack idStack = new Stack();
> 183c186
> <             log.trace( "Writing bean graph (qualified name '" +
> qualifiedName + "'" );
> ---
>>             log.trace( "Writing bean graph (qualified name '" +
> qualifiedName + "')" );
> 210c213
> <                     if ( ref == null ) {
> ---
>>                     if ( idStack.search( bean ) == -1 ) {
> 216a220
>>                             idStack.push( bean );
> 249a254
>>                             idStack.push( bean );
> 256a262,264
>>
>>                         // about to finish writing this bean - no need
> to remember it any more
>>                         idStack.pop();
>
> Basically, as well as recording bean IDs in a Hashmap, we now also
> maintain a stack of beans currently being written. Each time we see a
> new bean we add the bean to the stack before recursing further down the
> graph by calling write(). When we leave the write() method, we pop the
> bean off the stack as we are no longer interested in it (at least for
> the purposes of checking for cycles). The decision as to whether a cycle
> exists is then based on whether the bean is already in the stack - if it
> is, we have already seen it as part of this graph and hence there is a
> cycle. This means that multiple occurences that are not part of a cycle
> no longer produce a CyclicReferenceException.
>
> Give it a go and let me know if you think it works.
>
> Regards,
>
> Darren
>
>
>
> --
> To unsubscribe, e-mail:   <mailto:commons-user-unsubscribe@jakarta.apache.
> org>
> For additional commands, e-mail: <mailto:commons-user-help@jakarta.apache.
> org>
>


RE: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by Darren Scott <da...@darrenscott.com>.
> as i said, i had planned to take a look at creating a fix in 
> any case. if 
> you do make progress before then let me know so that i can 
> look at adding 
> some other features instead :)
> 
> - robert

I think I've got a fix for unexpected CyclicReferenceExceptions. Robert
asked me to provide a cvs diff -u for the fix - I've never used -u on
diff before and it seemed to produce a LOT of output, so here's output
from a regular diff between my working copy and the top of the source
tree (1.6):

RCS file:
/home/cvspublic/jakarta-commons/betwixt/src/java/org/apache/commons/betw
ixt/io/AbstractBeanWriter.java,v
retrieving revision 1.6
diff -w -r1.6 AbstractBeanWriter.java
71a72
> import java.util.Stack;
106a108,109
>     /** Stack containing ID attribute values for beans seen so far in
this graph */
>     protected Stack idStack = new Stack();
183c186
<             log.trace( "Writing bean graph (qualified name '" +
qualifiedName + "'" );
---
>             log.trace( "Writing bean graph (qualified name '" +
qualifiedName + "')" );
210c213
<                     if ( ref == null ) {
---
>                     if ( idStack.search( bean ) == -1 ) {
216a220
>                             idStack.push( bean );
249a254
>                             idStack.push( bean );
256a262,264
> 
>                         // about to finish writing this bean - no need
to remember it any more
>                         idStack.pop();

Basically, as well as recording bean IDs in a Hashmap, we now also
maintain a stack of beans currently being written. Each time we see a
new bean we add the bean to the stack before recursing further down the
graph by calling write(). When we leave the write() method, we pop the
bean off the stack as we are no longer interested in it (at least for
the purposes of checking for cycles). The decision as to whether a cycle
exists is then based on whether the bean is already in the stack - if it
is, we have already seen it as part of this graph and hence there is a
cycle. This means that multiple occurences that are not part of a cycle
no longer produce a CyclicReferenceException.

Give it a go and let me know if you think it works.

Regards,

Darren



Re: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by robert burrell donkin <ro...@blueyonder.co.uk>.
On Thursday, December 12, 2002, at 10:33 PM, Darren Scott wrote:

>> i have been down this road before. i did start playing around
>> with stacks
>> but betwixt is hard to change without breaking things.
>
> I'm glad someone else has noticed it's easy to break it!

i think all the committers agree that the structure could be improved. the 
problem is that it's not easier to see the best way to do it...

>> i have some time this weekend and i was going to take a look at this
>> (provided that i can build maven by then). if you don't have
>> the time to
>> track down the problems by then, if you post your diff's (cvs
>> diff -u,
>> please) i'll (try to) finish the work off.
>
> I'll see how much time I get over the next couple of days...

as i said, i had planned to take a look at creating a fix in any case. if 
you do make progress before then let me know so that i can look at adding 
some other features instead :)

- robert


RE: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by Darren Scott <da...@darrenscott.com>.
> > I've almost got this working (I'm not getting 
> > CyclicReferenceExceptions any more but I seem to have 
> broken something 
> > else as my XML doesn't pay any attention to the .betwixt files!) As 
> > soon as I've got a working solution I'll post again.
> 
> i have been down this road before. i did start playing around 
> with stacks 
> but betwixt is hard to change without breaking things.

I'm glad someone else has noticed it's easy to break it!

> i have some time this weekend and i was going to take a look at this 
> (provided that i can build maven by then). if you don't have 
> the time to 
> track down the problems by then, if you post your diff's (cvs 
> diff -u, 
> please) i'll (try to) finish the work off.

I'll see how much time I get over the next couple of days...

Darren



Re: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by robert burrell donkin <ro...@blueyonder.co.uk>.
On Thursday, December 12, 2002, at 10:07 PM, Darren Scott wrote:

>>> The cyclic checking isn't that advanced yet. The scenario that A
>>> refers to another A is covered however. Since the cyclic stuff also
>>> has some relation when you use id's (and I am not into id's that
>>> much), I probably have to have some help with the id
>> handling. Time to
>>> read some specs on that :)
>>
>> yeh. i've been wanting to improve this for some time now.
>>
>> your understanding of a cyclic graph is correct. the problem
>> is that at
>> the moment, betwixt is pretty dumb and will throw a cycle reference
>> exception if it encounters the same bean if id's aren't been written.
>>
>> i have played about with various ways of improving the
>> situation but they' ve all proved unsatisfactory. probably
>> the basic betwixt design needs to
>> be improved.
>>
>
> I've been looking into this a bit more, particularly at the main write()
> method in AbstractBeanWriter.  I think the use of a HashMap to store a
> record of previous visits to beans in the graph may be the cause of the
> problem. As this only stores a single reference to whether the bean has
> been seen anywhere before, this covers both genuine cyclic references
> and multiple non-cyclic references, which is incorrect (does this make
> sense?!)
>
> Wouldn't a stack based implementation be more suitable i.e. every time
> we recurse further down the graph by calling write() again, we push the
> current bean on the stack and when we work our way back up the graph and
> leave the write() method, we pop the bean off the stack. This way when
> we check whether the bean has been seen before (using stack.search()) we
> are only checking for genuine cyclic references and not just multiple
> (non-cyclic) references. When we get back to where we started, the stack
> will be empty ready for the next bean...
>
> Does this solution sound reasonable?

the way i see it, there are two different issues:

1. ID-IDREF support. the hash map is useful for this implementation. 
(there is still quite a lot of work to do on this.)

2. detecting cycles properly. i agree that this is best done with a stack.

> I've almost got this working (I'm not getting CyclicReferenceExceptions
> any more but I seem to have broken something else as my XML doesn't pay
> any attention to the .betwixt files!) As soon as I've got a working
> solution I'll post again.

i have been down this road before. i did start playing around with stacks 
but betwixt is hard to change without breaking things.

i have some time this weekend and i was going to take a look at this 
(provided that i can build maven by then). if you don't have the time to 
track down the problems by then, if you post your diff's (cvs diff -u, 
please) i'll (try to) finish the work off.

- robert


RE: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by Darren Scott <da...@darrenscott.com>.
> > The cyclic checking isn't that advanced yet. The scenario that A 
> > refers to another A is covered however. Since the cyclic stuff also 
> > has some relation when you use id's (and I am not into id's that 
> > much), I probably have to have some help with the id 
> handling. Time to 
> > read some specs on that :)
> 
> yeh. i've been wanting to improve this for some time now.
> 
> your understanding of a cyclic graph is correct. the problem 
> is that at 
> the moment, betwixt is pretty dumb and will throw a cycle reference 
> exception if it encounters the same bean if id's aren't been written.
> 
> i have played about with various ways of improving the 
> situation but they' ve all proved unsatisfactory. probably 
> the basic betwixt design needs to 
> be improved.
> 

I've been looking into this a bit more, particularly at the main write()
method in AbstractBeanWriter.  I think the use of a HashMap to store a
record of previous visits to beans in the graph may be the cause of the
problem. As this only stores a single reference to whether the bean has
been seen anywhere before, this covers both genuine cyclic references
and multiple non-cyclic references, which is incorrect (does this make
sense?!)

Wouldn't a stack based implementation be more suitable i.e. every time
we recurse further down the graph by calling write() again, we push the
current bean on the stack and when we work our way back up the graph and
leave the write() method, we pop the bean off the stack. This way when
we check whether the bean has been seen before (using stack.search()) we
are only checking for genuine cyclic references and not just multiple
(non-cyclic) references. When we get back to where we started, the stack
will be empty ready for the next bean...

Does this solution sound reasonable?

I've almost got this working (I'm not getting CyclicReferenceExceptions
any more but I seem to have broken something else as my XML doesn't pay
any attention to the .betwixt files!) As soon as I've got a working
solution I'll post again.

Darren Scott



Re: [betwixt] info on .betwixt files, "add" methods, and CyclicReferenceExceptions

Posted by robert burrell donkin <ro...@blueyonder.co.uk>.
On Monday, December 9, 2002, at 12:30 PM, Martin van den Bemt wrote:

> On Sat, 2002-12-07 at 21:10, Darren Scott wrote:

<snip>

>> 3) I seem to get CyclicReferenceExceptions when I don't expect to. Maybe
>> it's my misunderstanding of what a graph cycle is, but I took it to mean
>> when you get into an infinite cycle with references e.g. A refers to B,
>> B refers to C, C refers to A, A refers to B etc. I get these exceptions
>> raised when I have a collection containing multiple references to the
>> same object. I wouldn't have expected this situation to be treated as a
>> cycle.
>
> The cyclic checking isn't that advanced yet. The scenario that A refers
> to another A is covered however. Since the cyclic stuff also has some
> relation when you use id's (and I am not into id's that much), I
> probably have to have some help with the id handling.
> Time to read some specs on that :)

yeh. i've been wanting to improve this for some time now.

your understanding of a cyclic graph is correct. the problem is that at 
the moment, betwixt is pretty dumb and will throw a cycle reference 
exception if it encounters the same bean if id's aren't been written.

i have played about with various ways of improving the situation but they'
ve all proved unsatisfactory. probably the basic betwixt design needs to 
be improved.

martin - if you've got some cycles, maybe we could throw ideas around.

- robert