GrovyObjects and POJOs - summary

classic Classic list List threaded Threaded
70 messages Options
1234 ... 7
Reply | Threaded
Open this post in threaded view
|

GrovyObjects and POJOs - summary

tugwilson
This email tries to gather together the problems and possible  
solutions we have discussed over the past few days:

We have a problem serialising Groovy objects. There are two forms of  
serialisation and they hit different but related problems.

Bean Serialisation
This form of serialisation is used by XFire and http://java.sun.com/ 
j2se/1.4.2/docs/api/java/beans/XMLEncoder.html amongst others.

Basically these techniques look for all the properties on the Bean  
and write the values out (generally in the form of a XML document).  
Deserialisation reads the document creates an instance of the Bean  
and sets the properties.

All objects which implement GroovyObject have getMetaClass and  
setMetaClass methods. this means that metaClass is a property on all  
GroovyObjects.

The problem is that this causes the serialiser to try to serialise  
the GroovyObject's MetaClass. This cannot be done because the  
MetaClass has properties which are not themselves Beans so the  
serialisation process fails. However, even if MetaClass could be  
serialised IT SHOULD NOT BE. The problem of deserialising an object  
containing a reference to a MetaClass is complex - see later for  
details.

Normal Java Serialisation
This form of serialisation uses java.io.ObjectOutputStream.  You  
generally encounter this form Enterprise apps via RMI.

The problem here is again the MetaClass instance inside a  
GroovyObject. However the problem is not caused by the presence of  
the getMetaClas and setMetaClass methods it's the presence of the  
field itself which triggers the problem.

MetaClass (rightly) does not implement Serializable. So the correct  
way of making a GroovyObject serializable is to make the MetaObject  
transient and to have some initialisation code which initialises the  
field to the right value when the GroovyObject is deseriailzed.  
Unfortunately the deserialization problem is hard to crack. As we can  
and do have per instance MetaClasses we have to find some way of  
setting up the right MetaClass - this may not be a problem that can  
be solved in the general case.

Solutions:

Bean Serialisation

1/ rename the getMetaClass and setMetaClass methods

2/ find some way of declaring a class in Groovy which does not  
implement GroovyObject

3/ declare a static metaClass property in your Bean

4/ do nothing - use Java if you want to create these Beans

Normal Java Serialisation

options 2 and 4 from above

plus

5/ get the compiler to generate a transient reference and to generate  
some code to reset the metaClass instance on deserilization.

Details:

the "find some way of declaring a class in Groovy which does not  
implement GorovyObject" solution has had two suggestions

a/ introduce an annotation; @PureJavaBean  which would stop the  
compiler from implementing GroovyObject on the class

b/ if the class explicitly extends a POJO then don't silently  
implement GroovyObject unless the programmer explicitly requires it  
(with "implements GroovyObject)

If I have missed anything please comment.

Please comment on your preferences for these solutions with reasons.

Lets hope we can come to some consensus :)


John Wilson
The Wilson Partnership
web http://www.wilson.co.uk
blog http://eek.ook.org



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

tugwilson

On 8 Sep 2006, at 12:33, John Wilson wrote:

>
> Solutions:
>
> Bean Serialisation
>
> 1/ rename the getMetaClass and setMetaClass methods

I like this idea but I fear that it is too late to adopt it. It would  
potentially break existing code and I believe it would invalidate a  
part of GINA.

Also it does nothing to solve the standard Java Serialisation problem  
so we would have to do something else as well.
>
> 2/ find some way of declaring a class in Groovy which does not  
> implement GroovyObject

I think that this is the best solution

>
> 3/ declare a static metaClass property in your Bean

This exploits a weird Complier behaviour which I believe to be a bug:)

I do not recommend this!

>
> 4/ do nothing - use Java if you want to create these Beans
>
> Normal Java Serialisation
>
> options 2 and 4 from above
>
> plus
>
> 5/ get the compiler to generate a transient reference and to  
> generate some code to reset the metaClass instance on deserilization.

I think option 2 is the solution to this

Option 5 is interesting but I can't think how to make it work without  
introducing overhead in a vital part of the runtime system.

>
> Details:
>
> the "find some way of declaring a class in Groovy which does not  
> implement GorovyObject" solution has had two suggestions
>
> a/ introduce an annotation; @PureJavaBean  which would stop the  
> compiler from implementing GroovyObject on the class

I dislike this approach for two reasons

1/ it introduces ugly noise into Groovy programs (we have just rid  
ourselves of the @Property abomination I don't want to replace it  
with a new one)

2. it's an abuse of annotations. This changes the semantics of the  
program and annotations are not supposed to do that (see: http://
java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html)

>
> b/ if the class explicitly extends a POJO then don't silently  
> implement GroovyObject unless the programmer explicitly requires it  
> (with "implements GroovyObject)


I like this solution (but then I'm biased!)


John Wilson
The Wilson Partnership
web http://www.wilson.co.uk
blog http://eek.ook.org



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

Jochen Theodorou
In reply to this post by tugwilson
John Wilson schrieb:
[...]
> The problem is that this causes the serialiser to try to serialise the
> GroovyObject's MetaClass. This cannot be done because the MetaClass has
> properties which are not themselves Beans so the serialisation process
> fails. However, even if MetaClass could be serialised IT SHOULD NOT BE.
> The problem of deserialising an object containing a reference to a
> MetaClass is complex - see later for details.

MetaClass is our version of class, and there are good reasons why class
is not serializeable. Btw, this means also that MetaClass will never be
serializable, as it referes to a class. So I wouldn't only say it should
not be, I would say it musn't as well as from the point of desing as
from the point of implementation. Sun made a good trick in making
"class" some kind of invisible field. This is no way we can go - sadly.

[...]
> MetaClass (rightly) does not implement Serializable. So the correct way
> of making a GroovyObject serializable is to make the MetaObject
> transient and to have some initialisation code which initialises the
> field to the right value when the GroovyObject is deseriailzed.
> Unfortunately the deserialization problem is hard to crack. As we can
> and do have per instance MetaClasses we have to find some way of setting
> up the right MetaClass - this may not be a problem that can be solved in
> the general case.

I agree, even if we write custom deserialization methods I won't solve
the general case. It would solve the common case and we could throw an
exception in other cases.

> Solutions:
>
> Bean Serialisation
>
> 1/ rename the getMetaClass and setMetaClass methods

I think that is a must for post 1.0! For now... we may let it be.

> 2/ find some way of declaring a class in Groovy which does not implement
> GroovyObject

not GroovyObject is the problem, the methods and the field are the
problem. If we say we mark an class as not being able to have an per
instance MetaClass, we could rewrite the getter to use the same
mechanism as for java classes and the setter to throw an exception. In
that case no field would be generated, no default serialization problem
happens. In combination with 1, we would have a solution. we could even
allow a per instance MetaClass, but not set it per default. Again
problem solved, the getter would have to check if the field is !=null,
or not - but that is trivial.

> 3/ declare a static metaClass property in your Bean

I currently like the idea of an uninitalized field much more. It would
even solve the deserialization problem, as the getter is now able to
handle the null case. Only direct access to the field may cause
problems. for this I would like to rename the field to something like
__metaClass, to avoid this problem. Direct field access becomes invalid
then, in case of normal access the property methods are used. If we
rename them, the people will always have to use methods... I don't think
that would be too much of a problem.

> 4/ do nothing - use Java if you want to create these Beans

I think we should find a solution, as people will often want to do
something like that.

> Normal Java Serialisation
>
> options 2 and 4 from above
>
> plus
>
> 5/ get the compiler to generate a transient reference and to generate
> some code to reset the metaClass instance on deserilization.
>
> Details:
>
> the "find some way of declaring a class in Groovy which does not
> implement GorovyObject" solution has had two suggestions
>
> a/ introduce an annotation; @PureJavaBean  which would stop the compiler
> from implementing GroovyObject on the class
>
> b/ if the class explicitly extends a POJO then don't silently implement
> GroovyObject unless the programmer explicitly requires it (with
> "implements GroovyObject)

I think the option b) would too much create two worlds. We solved
@Property by redfining the default. We gave up the package private
visibility to solve this. That wasn't much of a loss, thius visibility
form is not widely used. But controling if something implements
GroovyObject or not by the usage of extends and even give a meaning to
the surplus "extends Object" is quite strange to me.

We Groovy does need is a way to tell the compiler things. If Annotations
shouldn't be used to that, then we have to think of something new.

--
Jochen Theodorou
Groovy Tech Lead
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

Jochen Theodorou
In reply to this post by tugwilson
John Wilson schrieb:
[...]

>> a/ introduce an annotation; @PureJavaBean  which would stop the
>> compiler from implementing GroovyObject on the class
>
> I dislike this approach for two reasons
>
> 1/ it introduces ugly noise into Groovy programs (we have just rid
> ourselves of the @Property abomination I don't want to replace it with a
> new one)
>
> 2. it's an abuse of annotations. This changes the semantics of the
> program and annotations are not supposed to do that (see:
> http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html)

We have different views on this, you know. If annotations are only there
to add meta data. @SuppressWarnings is clearly not to add meta data
@Retention defines semantics, @Target is also more than just meta data.
not to mention @interface, which is needed to define an annotation as
such. I have not very different views for @Override, @Deprecated and
@Inherited.

My view is that most of the annotations are interacting with the
compiler in more than just add metadata to something. Pratly they are
used to enable/disable functions in the compiler, or to let the compiler
produce different bytecode.

"Annotations do not directly affect program semantics, but they do
affect the way programs are treated by tools and libraries, which can in
turn affect the semantics of the running program. Annotations can be
read from source files, class files, or reflectively at run time."

That is right, but if the compiler is such a tools the border blurs.


>> b/ if the class explicitly extends a POJO then don't silently
>> implement GroovyObject unless the programmer explicitly requires it
>> (with "implements GroovyObject)
>
> I like this solution (but then I'm biased!)

I do not have something against not implementing GroovyObject in
general, but the page about "things where groovy surprises you" will get
bigger and bigger. Following the principle of last surprise means for
me, that I don't expect an difference between writing extends Object or not.

On the other hand we can't let people always implement GroovyObject
excplicitly. That would be noise again.


bye blackdrag

--
Jochen Theodorou
Groovy Tech Lead
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

tog
Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

tog
In reply to this post by tugwilson
Thanks john for this nice overview.  I really hope that  it will help us to reach concensus.
cheers
tog

On 9/8/06, John Wilson <[hidden email]> wrote:
This email tries to gather together the problems and possible
solutions we have discussed over the past few days:

We have a problem serialising Groovy objects. There are two forms of
serialisation and they hit different but related problems.

Bean Serialisation
This form of serialisation is used by XFire and http://java.sun.com/
j2se/1.4.2/docs/api/java/beans/XMLEncoder.html amongst others.

Basically these techniques look for all the properties on the Bean
and write the values out (generally in the form of a XML document).
Deserialisation reads the document creates an instance of the Bean
and sets the properties.

All objects which implement GroovyObject have getMetaClass and
setMetaClass methods. this means that metaClass is a property on all
GroovyObjects.

The problem is that this causes the serialiser to try to serialise
the GroovyObject's MetaClass. This cannot be done because the
MetaClass has properties which are not themselves Beans so the
serialisation process fails. However, even if MetaClass could be
serialised IT SHOULD NOT BE. The problem of deserialising an object
containing a reference to a MetaClass is complex - see later for
details.

Normal Java Serialisation
This form of serialisation uses java.io.ObjectOutputStream.  You
generally encounter this form Enterprise apps via RMI.

The problem here is again the MetaClass instance inside a
GroovyObject. However the problem is not caused by the presence of
the getMetaClas and setMetaClass methods it's the presence of the
field itself which triggers the problem.

MetaClass (rightly) does not implement Serializable. So the correct
way of making a GroovyObject serializable is to make the MetaObject
transient and to have some initialisation code which initialises the
field to the right value when the GroovyObject is deseriailzed.
Unfortunately the deserialization problem is hard to crack. As we can
and do have per instance MetaClasses we have to find some way of
setting up the right MetaClass - this may not be a problem that can
be solved in the general case.

Solutions:

Bean Serialisation

1/ rename the getMetaClass and setMetaClass methods

2/ find some way of declaring a class in Groovy which does not
implement GroovyObject

3/ declare a static metaClass property in your Bean

4/ do nothing - use Java if you want to create these Beans

Normal Java Serialisation

options 2 and 4 from above

plus

5/ get the compiler to generate a transient reference and to generate
some code to reset the metaClass instance on deserilization.

Details:

the "find some way of declaring a class in Groovy which does not
implement GorovyObject" solution has had two suggestions

a/ introduce an annotation; @PureJavaBean  which would stop the
compiler from implementing GroovyObject on the class

b/ if the class explicitly extends a POJO then don't silently
implement GroovyObject unless the programmer explicitly requires it
(with "implements GroovyObject)

If I have missed anything please comment.

Please comment on your preferences for these solutions with reasons.

Lets hope we can come to some consensus :)


John Wilson
The Wilson Partnership
web http://www.wilson.co.uk
blog http://eek.ook.org



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

tugwilson
In reply to this post by Jochen Theodorou

On 8 Sep 2006, at 13:59, Jochen Theodorou wrote:

>
> We have different views on this, you know. If annotations are only  
> there to add meta data. @SuppressWarnings is clearly not to add  
> meta data @Retention defines semantics, @Target is also more than  
> just meta data. not to mention @interface, which is needed to  
> define an annotation as such. I have not very different views for  
> @Override, @Deprecated and @Inherited.


None of these annotations change the semantics.

If you compile the program with annotations and then run it it will  
produce exactly the same result as compiling without annotations and  
running it.

There are annotations which cause the compiler to produce errors and  
warnings, of course. But annotations do not change the behaviour of  
compiled code.


John Wilson
The Wilson Partnership
web http://www.wilson.co.uk
blog http://eek.ook.org



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

tugwilson
In reply to this post by Jochen Theodorou

On 8 Sep 2006, at 13:31, Jochen Theodorou wrote:

>
> MetaClass is our version of class, and there are good reasons why  
> class is not serializeable. Btw, this means also that MetaClass  
> will never be serializable, as it referes to a class. So I wouldn't  
> only say it should not be, I would say it musn't as well as from  
> the point of desing as from the point of implementation. Sun made a  
> good trick in making "class" some kind of invisible field. This is  
> no way we can go - sadly.

I quite agree - that was what I intended to say - sorry for the  
confusion.

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

Jochen Theodorou
In reply to this post by tugwilson
John Wilson schrieb:

>
> On 8 Sep 2006, at 13:59, Jochen Theodorou wrote:
>
>>
>> We have different views on this, you know. If annotations are only
>> there to add meta data. @SuppressWarnings is clearly not to add meta
>> data @Retention defines semantics, @Target is also more than just meta
>> data. not to mention @interface, which is needed to define an
>> annotation as such. I have not very different views for @Override,
>> @Deprecated and @Inherited.
>
> None of these annotations change the semantics.
 >
> If you compile the program with annotations and then run it it will
> produce exactly the same result as compiling without annotations and
> running it.
>
> There are annotations which cause the compiler to produce errors and
> warnings, of course. But annotations do not change the behaviour of
> compiled code.

ah yes? not of compiled code, but to the way the code is compiled.
Remove @interface from a annotation declaration and yes, the semantics
of the class files is the same, but only because removing @interface
means that you don't get a class file at all. and @Retention does have
influence on the visibility. If I write an program reading this data
from an annotation, then the program will behave different if the
annotation is marked with another level of retention. That is no
semantic change? Of course it is not, because I changed the input, not
the program. So yes, you are right.


--
Jochen Theodorou
Groovy Tech Lead
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

tog
Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

tog
In reply to this post by Jochen Theodorou


On 9/8/06, Jochen Theodorou <[hidden email]> wrote:
John Wilson schrieb:
[...]
>> a/ introduce an annotation; @PureJavaBean  which would stop the
>> compiler from implementing GroovyObject on the class
>
> I dislike this approach for two reasons
>
> 1/ it introduces ugly noise into Groovy programs (we have just rid
> ourselves of the @Property abomination I don't want to replace it with a
> new one)

Well, I thought that annotation could be interesting to groovy as well. For example, why not supporting the JSR181 for designing web services in Groovy.

>
> 2. it's an abuse of annotations. This changes the semantics of the
> program and annotations are not supposed to do that (see:
> http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html )

We have different views on this, you know. If annotations are only there
to add meta data. @SuppressWarnings is clearly not to add meta data
@Retention defines semantics, @Target is also more than just meta data.
not to mention @interface, which is needed to define an annotation as
such. I have not very different views for @Override, @Deprecated and
@Inherited.

My view is that most of the annotations are interacting with the
compiler in more than just add metadata to something. Pratly they are
used to enable/disable functions in the compiler, or to let the compiler
produce different bytecode.

"Annotations do not directly affect program semantics, but they do
affect the way programs are treated by tools and libraries, which can in
turn affect the semantics of the running program. Annotations can be
read from source files, class files, or reflectively at run time."

That is right, but if the compiler is such a tools the border blurs.


>> b/ if the class explicitly extends a POJO then don't silently
>> implement GroovyObject unless the programmer explicitly requires it
>> (with "implements GroovyObject)
>
> I like this solution (but then I'm biased!)

I do not have something against not implementing GroovyObject in
general, but the page about "things where groovy surprises you" will get
bigger and bigger. Following the principle of last surprise means for
me, that I don't expect an difference between writing extends Object or not.

On the other hand we can't let people always implement GroovyObject
excplicitly. That would be noise again.

I think implementing this solution have the risk of breaking many existing applications.

So to make it practical I think the solution of the annotation has some elegance (but I'm biased :-D )

cheers
tog

PS: Hum I forgot I don't want to do it in Java ... this is not an option for me ;-)


bye blackdrag

--
Jochen Theodorou
Groovy Tech Lead
http://blackdragsview.blogspot.com/

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: GrovyObjects and POJOs - summary

tugwilson
In reply to this post by Jochen Theodorou

On 8 Sep 2006, at 13:31, Jochen Theodorou wrote:

> I think the option b) would too much create two worlds. We solved  
> @Property by redfining the default. We gave up the package private  
> visibility to solve this. That wasn't much of a loss, thius  
> visibility form is not widely used. But controling if something  
> implements GroovyObject or not by the usage of extends and even  
> give a meaning to the surplus "extends Object" is quite strange to me.


Being a GroovyObject gives you two things:

1/ being able to use a custom MetaClass per instance

2/ being able to supply invokeMethod, etc methods to be called by the  
MetaClass

If you have a custom Metaclass there is no way you can faithfully  
serialize the Bean using the Bean Serialisation. serialising it using  
standard Java serialization is hard and may not even be possible.

A custom MetaClass (not per instance but per class) can trivially do  
the calling of invokeMethod, etc. even if the class doesn't implement  
GroovyObject.

So if you want to serialise an object then it can have all the  
abilities of a GroovyObject with the exception of having a per  
instance custom MetaClass.

By and large we don't care if an object implements GroovyObject.  
either way it still can have dynamic behaviour and can provide  
default implementations for method and property access.

So changing the default behaviour when declaring a groovy class which  
extends a POJO is a *very* low impact change.


John Wilson
The Wilson Partnership
web http://www.wilson.co.uk
blog http://eek.ook.org



---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

1234 ... 7