injection & serialization best practice

287 views
Skip to first unread message

Jan Kriesten

unread,
Jun 12, 2007, 1:07:33 AM6/12/07
to google...@googlegroups.com

hi,

i just came across this issue developing webapps where objects are serialized to
the session store.

if there are objects injected which aren't serializable and marked transient
e.g., what is the best practice to have them injected again after
deserialization back from the session store? or is this handled by guice
automatically?

how would you solve this? using serializable providers instead?

best regards, --- jan.


Bob Lee

unread,
Jun 12, 2007, 1:11:06 AM6/12/07
to google...@googlegroups.com
This is exactly why I added support for static injection. :)

Bob

Jan Kriesten

unread,
Jun 12, 2007, 1:13:58 AM6/12/07
to google...@googlegroups.com

hi bob,

> This is exactly why I added support for static injection. :)

right, i have done it that way, too. but there are cases, where static class
members are not desirable.

any alternatives to static?

regards, --- jan.


Bob Lee

unread,
Jun 12, 2007, 1:24:07 AM6/12/07
to google...@googlegroups.com
On 6/11/07, Jan Kriesten <jan.kr...@hamburg.de> wrote:

Not that I know of. :(

Don't forget, you can inject "static Provider<Foo> fooProvider", too.

I suppose you could inject serializable proxies instead--proxies which know how to look up the real implementation upon deserialization.

  @Inject @Serializable Foo foo;

Bob

Jan Kriesten

unread,
Jun 12, 2007, 2:18:11 AM6/12/07
to google...@googlegroups.com

hi bob,

> Not that I know of. :(

using aspectj, one could add an aspect to readObject(java.io.ObjectInputStream
stream) to inject the object again, but i don't have any other idea, too.

regards, --- jan.


Eelco Hillenius

unread,
Jun 12, 2007, 2:19:48 AM6/12/07
to google...@googlegroups.com
> I suppose you could inject serializable proxies instead--proxies which know
> how to look up the real implementation upon deserialization.

For the record Jan, as I know you are on the Wicket user list, what
Bob proposes here is exactly what the wicket-spring project does for
@SpringBean annotations it encounters, and probably what I would have
in mind for Guice integration (though it is unlikely I'll have time to
work on that within the next few months, so if someone else picks that
up, that would be great).

Regards,

Eelco

Jan Kriesten

unread,
Jun 12, 2007, 2:47:04 AM6/12/07
to google...@googlegroups.com

hi eelco,

> For the record Jan, as I know you are on the Wicket user list, what
> Bob proposes here is exactly what the wicket-spring project does for
> @SpringBean annotations it encounters, and probably what I would have
> in mind for Guice integration (though it is unlikely I'll have time to
> work on that within the next few months, so if someone else picks that
> up, that would be great).

right, that would be a real enhancement to wicket. since i'm not that firm in
working with proxies, cglib etc. i'm not yet up for the challenge. i think i
stay with static && aspects (to inject new()-created objects) for the moment.

btw - a little off topic here - you run into problems when having a wicket app
that wants to extend both wicket-auth-roles /and/ wicket-spring, don't you?

regards, --- jan.

Eelco Hillenius

unread,
Jun 12, 2007, 3:17:11 AM6/12/07
to google...@googlegroups.com
> > For the record Jan, as I know you are on the Wicket user list, what
> > Bob proposes here is exactly what the wicket-spring project does for
> > @SpringBean annotations it encounters, and probably what I would have
> > in mind for Guice integration (though it is unlikely I'll have time to
> > work on that within the next few months, so if someone else picks that
> > up, that would be great).
>
> right, that would be a real enhancement to wicket. since i'm not that firm in
> working with proxies, cglib etc. i'm not yet up for the challenge. i think i
> stay with static && aspects (to inject new()-created objects) for the moment.

Sure. It shouldn't be very hard actually, as the spring integration
project could serve as an example, but it'll always take at least a
couple of hours to dig in and understand what is going on.

> btw - a little off topic here - you run into problems when having a wicket app
> that wants to extend both wicket-auth-roles /and/ wicket-spring, don't you?

Not really. The problems are/ were:
1) We steered people in the wrong direction by packaging
AuthenticatedWebApplication. Imho, this should have been kept just an
example, like in fact the whole project is. It's dead simple to create
a custom authorization strategy, and that was kind of the point of
that project :)
2) The initial Spring support version was a bit inflexbile, making it
a bit more work (but never impossible) to install properly if you
didn't want to extend the spring application object. But in the
current version, I think it suffices to put this:

protected void init() {
addComponentInstantiationListener(new SpringComponentInjector(this));
}

in your application, so you don't have to extend SpringWebApplication.

Anyway, sorry for being OT Guice people. Jan, there's more in the
archives, or otherwise start a thread on the Wicket list or log on at
##wicket on freenode.net.

Cheers,

Eelco

Jan Kriesten

unread,
Jun 12, 2007, 5:07:32 AM6/12/07
to google...@googlegroups.com

hi bob,

> I suppose you could inject serializable proxies instead--proxies which
> know how to look up the real implementation upon deserialization.
>
> @Inject @Serializable Foo foo;

wouldn't that be a possible extension to guice? i mean - if i supply a provider
class, guice could set up a proxy using provider to get the real
implementation?! or is that out of guice' scope?

regards --- jan.

Dhanji R. Prasanna

unread,
Jun 12, 2007, 6:36:08 AM6/12/07
to google...@googlegroups.com
I think marshalling and unmarshalling objects over the wire is use-case specific. There are DI aspects to it--we have a system of externalizer bindings in jsr311/JAX-RS for representations of resources (to turn objects into xml for instance). By contrast, hibernate creates object proxies that are serializable for storage in disk and cluster caches. These are very different use cases, their aspect of externalization is similarly disparate. In one vein, this is even farther outside of guice's scope than lifecycle around which there have been similar requests.

Anyway that's my opinion, others may vary =)

Dhanji.

Dhanji R. Prasanna

unread,
Jun 12, 2007, 6:46:52 AM6/12/07
to google...@googlegroups.com
On 6/12/07, Bob Lee <craz...@crazybob.org> wrote:

Not that I know of. :(

Don't forget, you can inject "static Provider<Foo> fooProvider", too.

I suppose you could inject serializable proxies instead--proxies which know how to look up the real implementation upon deserialization.

  @Inject @Serializable Foo foo;

Bob

Hey Bob did you take a look at my email to the list about injector location? That would be useful here too =)

For instance, you could implement readResolve() and have it locate the injector statically using a pluggable strategy such as jndi. *hint hint*

Dhanji.

Bob Lee

unread,
Jun 12, 2007, 11:32:35 AM6/12/07
to google...@googlegroups.com
On 6/12/07, Dhanji R. Prasanna <dha...@gmail.com> wrote:
Hey Bob did you take a look at my email to the list about injector location? That would be useful here too =)

For instance, you could implement readResolve() and have it locate the injector statically using a pluggable strategy such as jndi. *hint hint*

That's not a bad idea. Static injection just seems simpler. I also like to unit test serialization.

We're talking about:

  static @Inject Foo foo;

vs.:

  @Inject Foo foo;

  private void readObject(...) {
    ...
    foo = relookup(Foo.class);
  }

Bob

Kevin Bourrillion

unread,
Jun 12, 2007, 12:12:11 PM6/12/07
to google...@googlegroups.com
The phrase "locate the injector statically" really freaks me out bad. :-)

On 6/12/07, Dhanji R. Prasanna <dha...@gmail.com> wrote:
>
>

Hani Suleiman

unread,
Jun 12, 2007, 12:14:22 PM6/12/07
to google...@googlegroups.com
I have to ask, other than the novelty value, what's the benefit of
injecting loggers? Is it worth all that overhead to get rid of typing
'= LogFactory.getLogger()' ?

Jan Kriesten

unread,
Jun 12, 2007, 12:35:05 PM6/12/07
to google...@googlegroups.com

hi,

> I have to ask, other than the novelty value, what's the benefit of
> injecting loggers? Is it worth all that overhead to get rid of typing
> '= LogFactory.getLogger()' ?

if you type it this way, the overhead is sure not worth it.

but right now, almost every programmer types the class name in the getlogger() -
which is prone to errors imho.

see http://www.javaspecialists.co.za/archive/Issue137.html

best regards, --- jan.


Bob Lee

unread,
Jun 12, 2007, 12:37:56 PM6/12/07
to google...@googlegroups.com
Did you mean to reply to the other thread?


On 6/12/07, Hani Suleiman <ha...@formicary.net> wrote:
I have to ask, other than the novelty value, what's the benefit of
injecting loggers? Is it worth all that overhead to get rid of typing
'= LogFactory.getLogger()' ?

There's very little benefit, unless of course you want to unit test which messages your class logs. I should have taken it out before release. I suppose I could still do so and provide a backward-compatible module.

Bob


Peter Reilly

unread,
Jun 12, 2007, 12:56:41 PM6/12/07
to google...@googlegroups.com
On 6/12/07, Hani Suleiman <ha...@formicary.net> wrote:
>
> I have to ask, other than the novelty value, what's the benefit of
> injecting loggers? Is it worth all that overhead to get rid of typing
> '= LogFactory.getLogger()' ?

1) you need to know (as in have class level dependency on) about LogFactory
and not just about the Logger interface. In a guice env, one should only
need to know about the interface, not the factory.
2) all the static Logger log =
LogFactory.getLogger(mysillyclass.class) look wrong and
are prone to errors from cut-and-paste coders.

Peter

Jan Kriesten

unread,
Jun 12, 2007, 3:14:58 PM6/12/07
to google...@googlegroups.com

hi dhanji,

> I think marshalling and unmarshalling objects over the wire is use-case
> specific.

agreed.

but i'd say that having support for optional proxy-functionality in combination
with providers / special annotations would simplify programming in many aspects.

since guice wouldn't have to bother with serializing but only supply a proxy to
the serializable class, it wouldn't be out of sight of guice central competence
(injecting, instantiation of objects) too much. in my opinion actually,
delivering proxy-support would make the instantiation aspect of guice even more
attractive.

> Anyway that's my opinion, others may vary =)

:-)

regards, --- jan.

Bob Lee

unread,
Jun 12, 2007, 3:47:25 PM6/12/07
to google...@googlegroups.com
I am thinking of adding some proxy support. I'll keep this in mind in case there's some way to improve things here.

Bob

On 6/12/07, Jan Kriesten <jan.kr...@hamburg.de> wrote:

Dhanji R. Prasanna

unread,
Jun 12, 2007, 5:35:48 PM6/12/07
to google...@googlegroups.com
On 6/13/07, Kevin Bourrillion <kevi...@gmail.com> wrote:

The phrase "locate the injector statically" really freaks me out bad.  :-)

well you create the injector statically, obtain matchers statically, expose scopes from static members, have static utils for wrapping named annotations...

It's just another factory fraternal to createInjector that Im suggesting =) 

Dhanji.

Dhanji R. Prasanna

unread,
Jun 12, 2007, 5:42:11 PM6/12/07
to google...@googlegroups.com
On 6/13/07, Peter Reilly <peter.ki...@gmail.com> wrote:

On 6/12/07, Hani Suleiman <ha...@formicary.net> wrote:
>
> I have to ask, other than the novelty value, what's the benefit of
> injecting loggers? Is it worth all that overhead to get rid of typing
> '= LogFactory.getLogger()' ?

1) you need to know (as in have class level dependency on) about LogFactory
   and not just about  the Logger interface. In a guice env, one should only
   need to know about the interface, not the factory.

But its a static factory, not a factory "bean. "
I mean, how would this argument apply to log4j:

Logger log = Logger.getLogger(...);

The dep on the static factory is a ghost. You can easily hide it away with a static import (and change the import without ever affecting the code).

2) all the static Logger log =
LogFactory.getLogger(mysillyclass.class) look wrong and
    are prone to errors from cut-and-paste coders.

IDEs can solve this one much better than having to rely on guice. One is not likely to change logging frameworks (moot if ur using commons logging), and even then a search and replace is easy.

And furthermore it's kinda nasty to have a Log parameter in every constructor of every class in the app =)

Dhanji.

Jan Kriesten

unread,
Jun 13, 2007, 2:25:29 AM6/13/07
to google...@googlegroups.com

> I am thinking of adding some proxy support. I'll keep this in mind in
> case there's some way to improve things here.

thanks bob, that would be great! :-)

--- jan.

thomas....@web.de

unread,
Jun 13, 2007, 4:51:20 AM6/13/07
to google-guice

Hello,

Wouldn't it be better to have some kind of generic "callback"
mechanism that sit's within the
ObjectInputStream and is invoked, when an Object is deserialized,
instead of implementing readObject()/readResolve() on "each" Class?

How about using a Custom ObjectInputStream (e.g.
InjectorAwareObjectInputStream extends ObjectInputStream ) that
overwrites readObjectOverride() ? In readObjectOverride() one could
call super.readObject(), save the deserialized Object in "result", in
inject Members into "result" and eventually return "result".

Perhaps something like this:

/**
*
*/
package de.tutorials.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.Field;

import de.tutorials.Main;

/**
* @author Thomas.Darimont
*
*/
public class InjectorAwareObjectInputStream extends ObjectInputStream
{

static Field enableOverrideField;
static {
try {
enableOverrideField = ObjectInputStream.class
.getDeclaredField("enableOverride");
enableOverrideField.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}

public InjectorAwareObjectInputStream(InputStream in) throws
IOException {
super(in);
try {
enableOverrideField.set(this, true);
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
protected Object readObjectOverride() throws IOException,
ClassNotFoundException {
try {
enableOverrideField.set(this, false);
} catch (Exception e) {
e.printStackTrace();
}
Object result = super.readObject();
try {
enableOverrideField.set(this, true);
} catch (Exception e) {
e.printStackTrace();
}
Main.INJECTOR.injectMembers(result);

return result;
}
}

Best regards,
Tom

Al Maw

unread,
Jun 20, 2007, 9:34:15 AM6/20/07
to google-guice

On Jun 12, 8:17 am, "Eelco Hillenius" <eelco.hillen...@gmail.com>
wrote:

For what it's worth, I just implemented this in Wicket. See
http://herebebeasties.com/2007-06-20/wicket-gets-guicy/ for details.

Regards,


Al

Eelco Hillenius

unread,
Jun 20, 2007, 10:48:36 AM6/20/07
to google...@googlegroups.com
Nice job Al.

Now, to really prove it's value, we could redo that phonebook example
with Guice (but without Spring). :)

Cheers,

Eelco

Stuart McCulloch

unread,
Jun 20, 2007, 12:58:52 PM6/20/07
to google...@googlegroups.com

very nice!

I've been looking for a guicy web-framework to test my Guice-OSGi bundle that lets
you use Guice to inject OSGi services - it's a bit like Spring-OSGi except it only uses
one bundle of ~500k ... but of course it doesn't cover everything that Spring does ;)

having used wicket (albeit not in anger) this looks like the perfect test subject - thanks!

( I'll post a link to the project page at the end of this week, once I tidy up the code )

Regards,


Al





--
Cheers, Stuart
Reply all
Reply to author
Forward
0 new messages