David,
I agree a FAQ would be useful. I'll need to queue it up as a TODO after the
long weekend.
As a brief summary, static injection implies static state, which generally
complicates component / functional testing. This is especially true when
more than one instance of a class needs to reference the same static state,
but with a different value thereof. If the static state is effectively a
stateless block of logic, then this is not so much of an issue.
Consider a quick example:
class RpcClientThatIsInjectedStatically {
@Inject static ServerAddress serverAddress;
@Inject RpcClientThatIsInjectedStatically(...) { }
RpcResponse makeRpcRequest(RpcRequest rpcRequest) {
RpcStub rpcStub = getStubForServer(serverAddress);
...
return rpcStub.call(rpcRequest);
}
}
If I have two instances of this class in the same process, then I can't have
more than one ServerAddress. Naturally I might have several instances of
this class in a real application.
Even if you expect only one instance of such a class in an application, you
might want to create an in-process integration test with two different
applications running in the same process. You're then faced with the issue
of not being able to distinguish the ServerAddress used in one application
from the ServerAddress used in the other.
This problem also manifests itself at a simpler level, which is running
tests in the same process. If you set static state on a class in one test
and don't tear it down appropriately, then you might break other tests in a
nonobvious way. Yes, it's ideal to think that all tests clean up after
themselves nicely, but we know in practice what really happens. Also,
you're now precluded from running tests in parallel within the same process,
insofar as the static state is referenced from two different tests running
concurrently.
Fred
On Wed, Aug 31, 2011 at 1:17 PM, David Sowerby <[email protected]>wrote:
> Fred
>
> Thanks for the thoughtful response.
>
> First, could I suggest an FAQ on this subject? Static injection is
> documented, but not in the context of serialisation as I recall - and
> I don't remember seeing anything on the options you have put forward
> here.
>
> Your answer made me think - what really are my objections to static
> injection, as it seems to work? The testing has been limited, but
> serialization / de-serialization returns correctly set up objects.
>
> Ok, I lose the ability to make the member final - and it is static.
> That is not ideal, but now I really think about it I am trying to work
> out why it seemed so bad! (As opposed to spending time putting in
> place one of your suggested alternatives)
>
> I can unit test well enough, and the integration testing we have done
> so far (not a great deal admittedly) with static injection (using
> Mycila) has caused no problems.
>
> So at the moment, I am of the opinion that I should have thought about
> it more before posting the question - and leave it as static
> injection, unless I find it causes other issues somewhere.
> Thanks again for the response.
>
> On Aug 25, 6:30 pm, Fred Faber <[email protected]> wrote:
> > The best solution will depend on how you can hook the serialization code.
> >
> > If you can hook the objects that you want serialized by adding a
> > writeReplace() method, then you can use a serializable
> > proxy<
> http://books.google.com/books?id=ka2VUBqHiWkC&lpg=PP1&pg=PA312#v=onep..
> .>to
> > ship each over the wire. The proxy would contain the Key
> > corresponding
> > to the binding of the object. The trick here is establishing the reverse
> > mapping from { object => key }, but it's possible through use of either
> the
> > provision API or plain java code (I've done the latter myself).
> >
> > The proxy would have a readResolve() method that can find a handle to the
> > injector on the JVM (several options exist for how to do this), and then
> it
> > would return "injector.getInstance(key)." This solution would allow you
> to
> > have non-serializable types as "private final transient" instance vars on
> a
> > serializable object. Looks strange, but it's possible.
> >
> > As another solution, if you could only hook the deserialization code, you
> > could then declare the non-serializable types as non-final and use member
> > injection when types are deserialized (via
> > "injector.injectMembers(deserializedObject)").
> >
> > We could also brainstorm different ways if you provide specific problem
> > constraints.
> >
> > Fred
> >
> > On Wed, Aug 24, 2011 at 5:56 PM, David Sowerby <[email protected]
> >wrote:
> >
> >
> >
> >
> >
> >
> >
> > > I probably should have been a bit clearer - static injection clearly
> > > works (except when I get it wrong!), but I am curious whether this
> > > approach is still the recommended "best practice" as a way of handling
> > > non-serializable objects. It does seem to negate some of the
> > > advantages of Guice.
> >
> > > On Aug 24, 6:29 pm, David Sowerby <[email protected]> wrote:
> > > > I have read the post athttp://
> > > groups.google.com/group/google-guice/browse_thread/thread/4799...
> > > > but I am still confused by this issue (and it may have changed since
> > > > then, it was 4 years ago)
> >
> > > > The problem is the same - serialising session state in a web app
> which
> > > > has injections of Injector and of Providers - neither of which are
> > > > serializable.
> >
> > > > In the previous thread, Bob Lee says this is why he introduced static
> > > > injection - but I must be missing something, as I cannot get it to
> > > > work. If that is the answer, or for that matter whatever the answer,
> > > > could someone post a simple example?
> >
> > > --
> > > You received this message because you are subscribed to the Google
> Groups
> > > "google-guice" group.
> > > To post to this group, send email to [email protected].
> > > To unsubscribe from this group, send email to
> > > [email protected].
> > > For more options, visit this group at
> > >http://groups.google.com/group/google-guice?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>
>
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-guice?hl=en.