Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make proxies serializable #12

Closed
gissuebot opened this issue Jul 7, 2014 · 4 comments
Closed

Make proxies serializable #12

gissuebot opened this issue Jul 7, 2014 · 4 comments

Comments

@gissuebot
Copy link

From crazyboblee on February 14, 2007 14:13:01

So you can store proxies on the HTTP session, etc.

Original issue: http://code.google.com/p/google-guice/issues/detail?id=12

@gissuebot
Copy link
Author

From crazyboblee on February 14, 2007 11:13:17

(No comment was entered for this change.)

Labels: -Type-Defect Type-Enhancement

@gissuebot
Copy link
Author

From limpbizkit on May 30, 2008 09:22:52

I think I have a possible strategy for the fix, but its tricky.

Suppose the intercepted class looks like this:
  class Foo implements Serializable {
    private final String a;
    private final  long createdTime;
    private boolean haveIBeenSerialized;
    @Inject public Foo(String a) {
      this.a = a;
      this.b = System.currentTimeMillis();
    }
    public void bar() {
      System.out.println(a);
    }
  }

Then the Guice generated AOP class looks approximately like this. This is my speculation, I'm not actually
familiar with the implementation:
  class Foo$EnhancedByGuice extends Foo {
    Interceptors interceptors;
    Foo$EnhancedByGuice(String a) {
      super(a);
    }
    @Override public void bar() {
      interceptors.intercept(...);
    }
  }

The problem is that it's very unlikely that the other end is going to have a class like Foo$EnhancedByGuice.
Basically, serializing generated classes is about as unreliable as it gets. So what we want to do kind of might
look approximately like this:
  class SerializedInterceptable<T> implements Serializable {
    T base;
    Interceptors interceptors;
    public SerializedInterceptable(T base, Interceptors interceptors) { ... }
    public void readResolve() {
      Foo$EnhancedByGuice enhanced = asSubclass(Foo$EnhancedByGuice.class, base);
      enhanced.interceptors = interceptors;
      return enhanced;
    }
  }
  class Foo$EnhancedByGuice extends Foo {
    ...
    public Object writeReplace() {
      Foo baseFoo = removeSubclass(this);
      return new SerializedInterceptable(baseFoo, interceptors);
    }
  }

Of course, the removeSuperclass() and asSubclass() methods need to do something quite magical. They need
to reflectively turn a Foo$EnhancedByGuice into the corresponding Foo and vice versa. I suspect this will need
Sun's Unsafe class, since we must not invoke the Foo constructor a second time (it could have side effects).

One requirement is that we must use the user's provided Foo.writeReplace() and Foo.readResolve() methods.
This opens the door to the user type changing from say Foo to Bar during serialization. Another trick is that
we don't have any idea of what Foo will look like upon deserialization. In particular, it may have a completely
different set of methods. I suspect the best heuristic to solve these problems will be to re-run the matchers
post-serialization. So any newly-added methods will be intercepted if they match the initial criteria.

One way to get around Unsafe would be to get Java's serialization to do the unsafe stuff for us. Perhaps a
clever implementation of asSubclass() could create a byte[] that looked like just the Foo-parts of the class.
We'd get reflection to do the unsafety for us. Whichever way we go we're going to need to try to conserve
complexity!

@gissuebot
Copy link
Author

From limpbizkit on June 03, 2008 02:39:24

I talked to Bob about this. We're not going to implement this since it has dangerous consequences, especially if it
were to work "transparently".

* - serializing interceptors is dangerous (they require heavyweight configuration, like transaction managers,
which aren't serializable in general)

    • not serializing interceptors is dangerous (transaction management shouldn't disappear upon serialization)

Status: WontFix

@gissuebot
Copy link
Author

From limpbizkit on June 03, 2008 17:29:53

Turns out it isn't too difficult to implement removeSuperclass() and asSubclass() using reflection and
serialization. You'll need this tip: http://sixlegs.com/blog/java/skipping-constructors.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant