Serialization Error when using Guice AOP

53 views
Skip to first unread message

Anthony MULLER

unread,
May 30, 2008, 8:14:08 AM5/30/08
to google...@googlegroups.com
Hello,

Following my previous message, I did another test to check the serialization when I use Guice to instanciate a class where I wish to put an interceptor.

The result is awful for me :-(

As a member of this list said, this simply doesn't work at all!

I will post a complete example following this message... I really don't know how to do now... When I use Guice with interceptor, I can't serialize my Serializable classes any more!

This should be written in big in the user guide!

Does this feature will be add quicker? Somebody found a workaround?

Cheers,
Anthony

onlytoine

unread,
May 30, 2008, 8:16:48 AM5/30/08
to google-guice
package guice;

import static com.google.inject.matcher.Matchers.annotatedWith;
import static com.google.inject.matcher.Matchers.any;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;

public class SerializationTest {

static class MyInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation mi) throws Throwable {
return mi.proceed();
}
}

static class MyModule extends AbstractModule {
public void configure() {
bindInterceptor(any(), annotatedWith(MyAnno.class), new
MyInterceptor());
}
}

public static void main(String[] args) throws Throwable {
Injector injector = Guice.createInjector(new MyModule());
Toto toto1 = injector.getInstance(Toto.class);

// Serialize today's date to a file.
FileOutputStream f = new FileOutputStream("tmp");
ObjectOutput s1 = new ObjectOutputStream(f);
s1.writeObject(toto1);
s1.flush();

// Deserialize a string and date from a file.
FileInputStream in = new FileInputStream("tmp");
ObjectInputStream s2 = new ObjectInputStream(in);
Toto toto2 = (Toto)s2.readObject();

System.out.println(toto1);
System.out.println(toto2);
}
}


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {

}

@ImplementedBy(TotoImpl.class)
interface Toto extends Serializable {
String getBidule();
void setBidule(String bidule);
}

class TotoImpl implements Toto {

private static final long serialVersionUID = 1L;

private String bidule;

@Inject
public TotoImpl() {
}

public String getBidule() {
return bidule;
}

@MyAnno
public void setBidule(String bidule) {
this.bidule = bidule;
}
}

Anthony MULLER

unread,
May 30, 2008, 10:13:59 AM5/30/08
to google-guice
I read the javadoc for CGLIB, and I see I can do this:


class TotoImpl implements Toto {

    private static final long serialVersionUID = 1L;

    ...

    public Object writeReplace() throws ObjectStreamException {
        Toto toto = new TotoImpl();
        toto.setBidule(bidule);
        return toto;
    }
   
    public Object readResolve() throws ObjectStreamException {
        Toto toto = SerializationTest.injector.getInstance(Toto.class);
        toto.setBidule(bidule);
        return toto;
    }

    ...
}

The problem is that solution is very intrusive! I don't want my object model depends of Guice.

Is there a way to say to Guice to inject methods like this into the created proxy?

Cheers,
Anthony



2008/5/30 onlytoine <anthony...@gmail.com>:

Anthony MULLER

unread,
May 30, 2008, 10:46:11 AM5/30/08
to google-guice
I though to write:

    public Object writeReplace() throws ObjectStreamException {
        return this;

    }

    public Object readResolve() throws ObjectStreamException {
        return this;
    }

into my objects.

After that, I would intercept call to these methods and provide a generic mechanism through an interceptor.

Unfortunately, readResolve() can not be intercept...

Please... Help !

Anthony





2008/5/30 Anthony MULLER <anthony...@gmail.com>:

limpb...@gmail.com

unread,
May 30, 2008, 12:39:52 PM5/30/08
to google-guice

You've stumbled upon issue 12.
http://code.google.com/p/google-guice/issues/detail?id=12

I've updated that issue with a roundabout clever
approach to implementing this.

If you're interested in writing the code, I'd love
for the community to implement this. The functionality
I believe we need is a method to swap a Subfoo for a
Foo and vice versa:
public Object removeSubtype(Object isSubtype);
public Object addSubtype(Class<?> subtype, Object hasSubtype);

For example, this test should pass:
class Foo {
private static int nextInstanceId = 1;
private final int instanceId = nextInstanceId++;
private final Object a;
public Foo(Object a) {
this.a = a;
}
}

class Subfoo extends Foo {
String b;
public Subfoo(Object a) {
super(a);
}
}

public void testRemoveSubtype() {
Foo.nextInstanceId = 1;
Foo subfoo = new Subfoo(new Object());
assertEquals(2, Foo.nextInstanceId);

Foo foo = removeSubtype(subfoo);
assertSame(1, foo.instanceId);
assertEquals(2, Foo.nextInstanceId);
assertEquals(Foo.class, foo.getClass());
assertSame(subfoo.a, foo.a);
}

public void testAddSubtype() {
Foo.nextInstanceId = 1;
Foo foo = new Foo(new Object());
assertEquals(2, Foo.nextInstanceId);

Foo subfoo = addSubtype(Subfoo.class, foo);
assertSame(1, subfoo.instanceId);
assertEquals(2, Foo.nextInstanceId);
assertEquals(Subfoo.class, subfoo.getClass());
assertSame(foo.a, subfoo.a);
}

I believe that with these primitives we can quickly
and cleanly implement serialization for interceptors.

Interested?

Bob Lee

unread,
May 30, 2008, 1:33:08 PM5/30/08
to google...@googlegroups.com
Dynaop used to support serialization, but I deliberately didn't support it in Guice. 95% of the time, you don't actually want to just serialize a proxied object, and in the 5% of the time where you do, you still need to write custom serialization code. The idea of comprehensive transparent serialization is seductive but not so great in real life.

Can you tell us a little more about how you're using it? I have a lot of experience serializing cglib proxies, so I'm sure I can suggest a solution.

Bob

Anthony MULLER

unread,
Jun 2, 2008, 4:08:43 AM6/2/08
to google...@googlegroups.com
Hi Bob,

If it is easy to add serialization support in Guice, it will be very helpful for me!

About my case, I work on a refactoring project of a SDK in my company (in Business Intelligence).

I studied Guice since many weeks personally, and I take this opportunity to introduce Guice into our SDK. So, all bindings and dependencies are handled by Guice.

And, a need is to listen to our business objects through a classic mechanism of listener/listenable... By now, I wish to use AOP capabilities of Guice to avoid to hardcode this feature.

Everything is going ok, except that we have to support serialization of our business objects and proxies created by Guice can not be serialized.

Guice must be fully transparent for 'old' users of our SDK, and we have to support serialization. Moreover, I don't want to introduce a hard coupling with Guice (even if I like it a lot ;-) )

So, what are your advices? Can you help me...

Cheers,
Anthony



2008/5/30 Bob Lee <craz...@crazybob.org>:

Anthony MULLER

unread,
Jun 2, 2008, 5:31:09 AM6/2/08
to google...@googlegroups.com
I look at 'dynaop', and it seems that the proxy strategy I need, is "Dynamic Proxies", rather than "Class Proxies" used as default in Guice.

Is it possible to change this?

Cheers,
Anthony


2008/6/2 Anthony MULLER <anthony...@gmail.com>:

Bob Lee

unread,
Jun 2, 2008, 11:16:35 AM6/2/08
to google...@googlegroups.com
On Mon, Jun 2, 2008 at 1:08 AM, Anthony MULLER <anthony...@gmail.com> wrote:
Everything is going ok, except that we have to support serialization of our business objects and proxies created by Guice can not be serialized.

Guice must be fully transparent for 'old' users of our SDK, and we have to support serialization. Moreover, I don't want to introduce a hard coupling with Guice (even if I like it a lot ;-) ) 

Under what circumstances will objects be serialized?

Bob

Anthony MULLER

unread,
Jun 2, 2008, 11:19:35 AM6/2/08
to google...@googlegroups.com
For instance, in a webfarm (to replicate data in session between several servers) or to save the state of the business objects temporary, or some customers use this to implement a cache...

Anthony

2008/6/2 Bob Lee <craz...@crazybob.org>:

Bob Lee

unread,
Jun 2, 2008, 3:26:03 PM6/2/08
to google...@googlegroups.com
Don't you know HttpSession is evil? It's a concurrency nightmare. ;-)

Seriously though, a general solution for making proxies serializable is far from trivial (if it's even possible).

Your best bet is to write custom serialization code. Something like this:

class MyProxiedType {

  Object writeReplace() {
    return new Handle(this);
  }


  static class Handle {
    ...

    Object readResolve() {
      Injector injector = ...;
      MyProxiedType o = injector.getInstance(MyProxiedType.class);
      o.update(this);
      return o;
    }
  }

}

My suggestion would be to avoid serialization if possible.

Bob

Anthony MULLER

unread,
Jun 3, 2008, 3:43:08 AM6/3/08
to google...@googlegroups.com
I don't work on the web part, but if you have some links about HttpSession issues and alternatives, I will read about this.

I did really hope you will give me a "crazy" solution to solve my problem... :-/

I would use Guice to avoid boilerplate code and finally I have to write such code because a basic behaviour of the java language is not supported :-(

About the code you talked about in your previous message, is there a way to put it automatically into generated proxy classes?

Cheers,

Anthony MULLER

unread,
Jun 3, 2008, 4:02:26 AM6/3/08
to google...@googlegroups.com
I read quickly this issue:

http://code.google.com/p/google-guice/issues/detail?id=12&q=Serializable

Does this mean that serialization problem will be fix in Guice N+1? (very soon so)

Anthony

2008/6/3 Anthony MULLER <anthony...@gmail.com>:

Anthony MULLER

unread,
Jun 3, 2008, 7:26:06 AM6/3/08
to google...@googlegroups.com
I tried XStream to serialized a proxied instance, and that seems to work. This is an example bellow.

What I forgot to say, is that serialization is always done for a short time in my case, or for replication purposes...

Anthony

<guice.ser.TotoImpl_-_-EnhancerByGuice_-_-84b8f86b>
  <bidule>machintruc</bidule>
  <CGLIB_-BOUND>true</CGLIB_-BOUND>
  <CGLIB_-CALLBACK__0 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor/>
    </interceptors>
    <method>
      <class>guice.ser.TotoImpl</class>
      <name>setBidule</name>
      <parameter-types>
        <class>java.lang.String</class>
      </parameter-types>
    </method>
  </CGLIB_-CALLBACK__0>
  <CGLIB_-CALLBACK__1 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>guice.ser.TotoImpl</class>
      <name>getBidule</name>
      <parameter-types/>
    </method>
  </CGLIB_-CALLBACK__1>
  <CGLIB_-CALLBACK__2 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>guice.ser.TotoImpl</class>
      <name>getTruc</name>
      <parameter-types/>
    </method>
  </CGLIB_-CALLBACK__2>
  <CGLIB_-CALLBACK__3 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>guice.ser.TotoImpl</class>
      <name>setTruc</name>
      <parameter-types>
        <class>java.lang.String</class>
      </parameter-types>
    </method>
  </CGLIB_-CALLBACK__3>
  <CGLIB_-CALLBACK__4 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>guice.ser.TotoImpl</class>
      <name>getMachin</name>
      <parameter-types/>
    </method>
  </CGLIB_-CALLBACK__4>
  <CGLIB_-CALLBACK__5 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>guice.ser.TotoImpl</class>
      <name>setMachin</name>
      <parameter-types>
        <class>java.lang.String</class>
      </parameter-types>
    </method>
  </CGLIB_-CALLBACK__5>
  <CGLIB_-CALLBACK__6 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>java.lang.Object</class>
      <name>finalize</name>
      <parameter-types/>
    </method>
  </CGLIB_-CALLBACK__6>
  <CGLIB_-CALLBACK__7 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>java.lang.Object</class>
      <name>hashCode</name>
      <parameter-types/>
    </method>
  </CGLIB_-CALLBACK__7>
  <CGLIB_-CALLBACK__8 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>java.lang.Object</class>
      <name>clone</name>
      <parameter-types/>
    </method>
  </CGLIB_-CALLBACK__8>
  <CGLIB_-CALLBACK__9 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>java.lang.Object</class>
      <name>equals</name>
      <parameter-types>
        <class>java.lang.Object</class>
      </parameter-types>
    </method>
  </CGLIB_-CALLBACK__9>
  <CGLIB_-CALLBACK__10 class="com.google.inject.InterceptorStackCallback">
    <interceptors>
      <guice.ser.SerializationTest_-MyInterceptor reference="../../../CGLIB_-CALLBACK__0/interceptors/guice.ser.SerializationTest_-MyInterceptor"/>
    </interceptors>
    <method>
      <class>java.lang.Object</class>
      <name>toString</name>
      <parameter-types/>
    </method>
  </CGLIB_-CALLBACK__10>
</guice.ser.TotoImpl_-_-EnhancerByGuice_-_-84b8f86b>

Bob Lee

unread,
Jun 3, 2008, 11:47:15 AM6/3/08
to google...@googlegroups.com
On Tue, Jun 3, 2008 at 12:43 AM, Anthony MULLER <anthony...@gmail.com> wrote:
I don't work on the web part, but if you have some links about HttpSession issues and alternatives, I will read about this.

The problem with HttpSession is it has no concurrency controls. Most implementations assume HTTP requests are synchronous, when in reality, they're very much not. You can easily have multiple requests coming in concurrently from the same person, if they click a link or button a couple times in succession, if you use AJAX, if they have multiple windows open. What's worse is the server can be serializing your session while another request is coming in and touching the same session object graph.

If you pay close attention to your exception logs and you use the session, you'll undoubtedly see weird exceptions that result from concurrency problems. The solution is to store your state in the DB instead.

Other problems: it's nearly impossible to maintain serialization compatibility between server versions (I wouldn't even try), while it's relatively easy to migrate relational data. If you can't migrate your session between server versions, that means your users will lose all their data when you deploy a new version. You could use rolling restarts, but they aren't perfect, and you're really just shifting the complexity.
 
I did really hope you will give me a "crazy" solution to solve my problem... :-/

Sorry I can't be of more help. :-(
 
About the code you talked about in your previous message, is there a way to put it automatically into generated proxy classes?

This problem is solvable (see the proxy serialization in Dynaop for an example). You'd have to use writeReplace() and write a "handle" object which contains:

  1) The serialized state of an unproxied version of your object.
  2) All the interceptor instances and which methods they apply to. This means your interceptors also have to be serializable. The easy way to do this is to just implement your interceptor using an enum. :-)

The handle object would have a readResolve method which would:

  1) Re-create cglib class using method -> interceptor mappings.
  2) Copy state from unproxied object into proxied version.

We can create the proxied and unproxied versions of the objects w/ calling the constructors by generating serialized data w/ no field values and deserializing it (serialization doesn't call the constructor).

Is this really what you want?

My worry is that you don't really want to serialize all this garbage (method handles and interceptors). You'll also run into problems if you inject non-serializable objects like other singletons into your objects.

Also, the HttpSession is really the only case where serialization makes any sense. If someone else tries to pass an object from a server to a client, they probably want to drop the interceptors. If you serialize something for a longer period of time, you'd probably want to pick up the new interceptors, not the old ones. This is why I left it up to the user to do whatever makes sense for them and decided not to try to guess what they want, because I'll always be wrong (in your case, I'd be kind of right, but I'd still be serializing a boatload of repetitious garbage).

Bob

Anthony MULLER

unread,
Jun 3, 2008, 4:16:46 PM6/3/08
to google...@googlegroups.com
Thanks for your advice about HttpSession, I will have a closer look and share your point of view with my team.

In fact, my need is not really a matter of writing or not interceptors... It is to serialize my business objects (proxified by Guice) as it was the case before for reasons I already told you.

The game is so to serialize my object proxified and read it, transparently for users.

If I understand well, your proposal consists to create a special class (an handler) for each objet I have to serialize (I have more than 300 objects...).

My goal when I decided to integrate Guice was to not polluate my source code and I believe that, if I add so much class like this, it will be an evil... And my code will be worse than before :-(  I don't want to adapt all my code in order to work with Guice, I think Guice should adapt to this kind of basic use (even if it is not easy at all to handle serialization).

I begin to write something according your advice (if I understand well) but this solution add to much code in my object:


@ImplementedBy(TotoImpl.class)
interface Toto extends Serializable {

    String getBidule();

    void setBidule(String bidule);

}

@Type(TotoImpl.class)
class TotoImpl implements Toto, Updatable<TotoImpl> {


    private static final long serialVersionUID = 1L;

    private String bidule;
    private String truc;
    private String machin;


    @Inject
    public TotoImpl() {
       
    }

    public String getBidule() {
        return bidule;
    }

    public void setBidule(String bidule) {
        this.bidule = bidule;
    }

    public String getTruc() {
        return truc;
    }

    public void setTruc(String truc) {
        this.truc = truc;
    }

    public String getMachin() {
        return machin;
    }

    public void setMachin(String machin) {
        this.machin = machin;
    }

   
     
    public void update(TotoImpl from) {
     this.bidule = from.bidule;
     this.machin = from.machin;
     this.truc = from.truc;

    }
       
    public Object writeReplace() throws ObjectStreamException {
     return SerializeUtils.writeReplace(this);

    }
   
    public Object readResolve() throws ObjectStreamException {
     return SerializeUtils.readResolve(this);
    }
}

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Type {
    Class<?> value();
}

interface Updatable<T> {
    void update(T from);
}

class SerializeUtils {
    public static Object writeReplace(Object toWrite)
            throws ObjectStreamException {
        try {
            Class<?> realType = toWrite.getClass().getAnnotation(Type.class)
                    .value();
            Constructor<?> constructor = realType.getConstructor();
            Updatable newObject = (Updatable) constructor.newInstance();
            newObject.update(toWrite);
            return newObject;
        } catch (Exception e) {
            throw new WriteAbortedException("Unable to write " + toWrite, e);
        }
    }

    public static Object readResolve(Object toRead)
            throws ObjectStreamException {
        Updatable toto = (Updatable) SerializationTest.injector
                .getInstance(toRead.getClass());
        toto.update(toRead);
        return toto;
    }
}



2008/6/3 Bob Lee <craz...@crazybob.org>:

Bob Lee

unread,
Jun 3, 2008, 5:53:59 PM6/3/08
to google...@googlegroups.com
Disclaimer: I would *not* do this myself. If you're caching data (whether it's in a distributed cache or in the HttpSession) does it really make sense to serialize all the interceptor data for each method with each object? I can't imagine a case where the answer to that question would be "yes".

With an HttpSession, if you're proxying a Customer object for example, you'd be a lot better off just re-reading that Customer object from the database when you fail over to a different server than you would serializing the Customer object (and all it's interceptor meta data) on every single request.

If I wanted to cache a Customer object, I would only do so in memory. You can keep a transient reference to it from the HttpSession, and just recreate it from the database if your session moves to another server.

That said, if someone wants to implement transparent serialization today...

1) Make com.google.inject.InterceptorStackCallback itself serializable. See Dynaop for an example of serializing Methods. All your method interceptors also have to be serializable.

2) Write a proxy handle which you can serialize instead of the proxy itself. Here's how Dynaop does it for one interceptor per proxy: https://dynaop.dev.java.net/source/browse/dynaop/src/dynaop/CglibProxyHandle.java?rev=1.21&view=markup

Guice has an interceptor per method (not one per object), so things will be a little different.

3) When creating an unproxied instance on the way out and a recreating a proxied instance on the way back in, you do *not* want to invoke the constructor (or call Injector.getInstance()). Use this trick to avoid doing so: http://sixlegs.com/blog/java/skipping-constructors.html

Now, how do you hook this into your objects? You have two options:

1) Patch Guice to do this by default.

or

2) Use a method interceptor to intercept writeReplace()! Perhaps we need a class matcher which picks all classes that will be proxied... In the mean time, I'm sure you could hack something up by explicitly annotating classes that need this or something.

Bob

Anthony MULLER

unread,
Jun 4, 2008, 8:26:01 AM6/4/08
to google...@googlegroups.com
I will look at this... I'm studying XStream too...

You often talk about DynaOp... Why Guice doesn't work with it (maybe this question is stupid)...

About all this discusion, I think Guice should offer some ways to customize easily its behavior (proxy creation for instance).

Last questions (I hope, and probably you too :-p):

- Is it possible to know the proxy class of an object, without instantiate it?

- Is it possible to know the original class of a proxified object, without adding an annotation as proposed by Robbie?

Cheers,
Anthony



2008/6/3 Bob Lee <craz...@crazybob.org>:

Bob Lee

unread,
Jun 4, 2008, 11:56:12 AM6/4/08
to google...@googlegroups.com
On Wed, Jun 4, 2008 at 5:26 AM, Anthony MULLER <anthony...@gmail.com> wrote:
I will look at this... I'm studying XStream too...

XStream is 6 and one half of a dozen here. In fact, you'll still want to use the serialization hack to create the objects.
 
You often talk about DynaOp... Why Guice doesn't work with it (maybe this question is stupid)...

Guice supersedes Dynaop. I took what I learned from Dynaop and applied it to Guice. Not trying to implement default serialization was one of those ideas. We need to make it easier to do the right thing and not surprise users with unexpected behavior. When you first started thinking about this, did you think serializing a proxy would also serialize a ton of method and interceptor objects?
 
About all this discusion, I think Guice should offer some ways to customize easily its behavior (proxy creation for instance).

That's the focus of 2.0.
 
- Is it possible to know the proxy class of an object, without instantiate it?

I'm not sure what you mean. If you're talking about at deserialization time, there may be no proxy class in that VM yet ub which case you need to create one. Either way, you just use cglib's API to do so.
 
- Is it possible to know the original class of a proxified object, without adding an annotation as proposed by Robbie?

We could add a marker interface to proxies and you could just look at the parent class.

Have you considered using AspectJ instead? Then, you'd be able to just serialize the classes w/o the interceptors.

Bob

Anthony MULLER

unread,
Jun 4, 2008, 3:30:11 PM6/4/08
to google...@googlegroups.com
XStream seems to offer a way to bypass the standard object creation during deserialization, and instead to create the object through a Guice's injector for instance... I just started to explore this API... It seems quite flexible and open... I will learn more soon :-)
 
When I started to think about this issue, I really don't think it was so complex... Now, it's clearer and I regret to not anticipate this problem before strongly asking to my manager to accept to use Guice in our developement.
 
It is quite difficult for me to continue to promote Guice when its use makes thing k=like serialization harder than before... Of course, we discuss about a potential solution, but we can't imagine to patch a 3trd party API or/and to add noisy piece of code into our freshly cleaned business objects...
 
Yes, it could be nice if we can recognize a proxy thanks to a particular tag interface or even an annotation.
 
What I asked is how to know the proxy class of an object, even if no instance of this object has been produced by Guice... It is probably not possible? I don't want to use directly CGLib, it is too "low level" for my original need.
 
About AspectJ, I must say that I never used it... My first idea about it, it is very complicated to learn and use... My needs were rather simple at the beginning, but probably I should take some time to study this framework too.
 
Thanks again for all your advice and explanation Bob :-)
 
I really very pleased to chat with you because I appreciate your work a lot.
 
Cheers,
Anthony
 
PS : excuse me also for my bad english... I do my best to improve it :-p
 
 


 
2008/6/4, Bob Lee <craz...@crazybob.org>:

Bob Lee

unread,
Jun 4, 2008, 3:56:08 PM6/4/08
to google...@googlegroups.com
I'm sorry I couldn't help more. :-(

It's probably best to steer clear of method interception, at least for objects you want to be serializable. Serialization and dynamically generated proxies just don't work well together.

Bob

Anthony MULLER

unread,
Jun 4, 2008, 5:22:42 PM6/4/08
to google...@googlegroups.com
Nevermind, I learned alot thanks to you.

Anthony


2008/6/4 Bob Lee <craz...@crazybob.org>:

Dhanji R. Prasanna

unread,
Jun 5, 2008, 6:25:59 PM6/5/08
to google...@googlegroups.com
On Thu, Jun 5, 2008 at 5:30 AM, Anthony MULLER <anthony...@gmail.com> wrote:
XStream seems to offer a way to bypass the standard object creation during deserialization, and instead to create the object through a Guice's injector for instance... I just started to explore this API... It seems quite flexible and open... I will learn more soon :-)

Is there a reason you can't do this with Java's serialization API? i.e. readResolve()

Dhanji.

Bob Lee

unread,
Jun 5, 2008, 6:50:11 PM6/5/08
to google...@googlegroups.com
I've already said this, but just to reiterate, I doubt you want to use the Injector to create your object upon deserialization. If you serialized injected dependencies along with your object, this would be the equivalent of injecting your object twice.

Whether you're using XStream or Serialization, Chris's serialization hack is the way to go. In fact, I think XStream already utilizes this hack.

Bob

Anthony MULLER

unread,
Jun 6, 2008, 8:03:45 AM6/6/08
to google...@googlegroups.com
I have written a "converter" for XStream which marshal the Guice proxy, without the extra data from CGLIB, like:

<Proxy_-_-Toto>
  <type>guice.ser.TotoImpl</type>
  <instance>
    <tutu>TEST2</tutu>
    <toto class="Proxy$$Toto">
      <type>guice.ser.TotoImpl</type>
      <instance>
        <tutu>TEST2</tutu>
        <toto class="Proxy$$Toto" reference="../../../.."/>
        <bidule>sub-machintruc</bidule>
        <currentValues>
          <list/>
        </currentValues>
      </instance>
    </toto>
    <bidule>machintruc</bidule>
    <currentValues>
      <list>
        <string>ONE</string>
        <string>TWO</string>
      </list>
    </currentValues>
  </instance>
</Proxy_-_-Toto>

So, when XStream find a Guice proxy, it uses this converter to write it down like shown above.

When XStream tries to read it back, I call the Guice injector to get a proxy for the class, and I let XStream fill it in with data it found.

Maybe this could be not very good with performance, but it is a transparent solution to serialize the proxy produced by Guice.

What is your point of view about it?

Cheers,
Anthony MÜLLER



2008/6/6 Bob Lee <craz...@crazybob.org>:

Anthony MULLER

unread,
Jun 9, 2008, 4:59:22 AM6/9/08
to google...@googlegroups.com
I published the XStream converter code to the XStream JIRA website... It will be add to XStream soon I think.

For this, the best will be to be able to know the "Guice" real class without to instanciate an object... That allows to configure XStream mapping without to instanciate an object of each type, just to know the underlying type... You see?

Anthony



2008/6/6 Anthony MULLER <anthony...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages