Hi,
My Guice module statically initializes fields in my servlet. Those
fields reference DAO classes, which in turn reference EntityManager.
As a consequence,
1) The Provider<EntityManager> is shared amongst multiple threads.
2) I am forced to refer to Provider<EntityManager> instead of
EntityManager in order to ensure that each thread sees its own request-
specific EntityManager.
I dislike having to use Provider in #2 instead of referencing
EntityManager directly, but I assume there is no better way?
My second question is about the Provider interface in general. Is the
interface is meant to be used from multiple threads? What are the
actual restrictions of sharing a Provider across multiple threads? Is
it okay so long as the callers have been created by the same Injector?
Are all restrictions implementation-specific? The Javadoc doesn't say
one way or another.
More specifically, I am wondering what the restrictions are of warp-
persist's Provider<EntityManager> implementation. I assume I can share
a single provider across multiple threads even if the thread using the
Provider was not itself injected. Is that correct?
class Bar {
private final Foo;
@Inject Bar(@ProviderProxy Foo foo) { // Proxies Foo by a Provider internally
this.foo = foo;
}
public void someMethod() {
foo.quux(); // internally calls fooProvider.get().quux()
}
}
Sam
The more I see this, the more I realize I don't like it.
Using Foo instead of Provider<Foo> violates the principal of least
surprise, especially given the fact that the annotation is in the
constructor instead of beside the field being proxied. If you were
looking at someone else's code and saw this you wouldn't quickly pick
up on the fact that any sort of look-up is taking place every time you
use Foo and this is dangerous.
That's OK if EntityManager is bound in request scope (or thread
On Jul 24, 3:14 pm, Cow_woC <gili.tzab...@gmail.com> wrote:
> My Guice module statically initializes fields in my servlet. Those
> fields reference DAO classes, which in turn reference EntityManager.
> As a consequence,
>
> 1) The Provider<EntityManager> is shared amongst multiple threads.
scope). From later responses, it looks like this is not true in your
case.
There is. You can wrap a Provider<T> with a dynamic proxy that makes
> 2) I am forced to refer to Provider<EntityManager> instead of
> EntityManager in order to ensure that each thread sees its own request-
> specific EntityManager.
>
> I dislike having to use Provider in #2 instead of referencing
> EntityManager directly, but I assume there is no better way?
it look like a T. Each method call on the wrapper T turns into a call
to get() on the Provider<T> to obtain the target T to which the method
call is forwarded.
The Guice user guide recommends using static injection for servlets.
On Jul 24, 6:37 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> I would strongly recommend *against* static initialization/injection unless
> you really have a complelling use case (e.g.: serialization). It is not
> really advisable for every day use, just as static fields and members aren't
> in general.
For example, a server that contains DAO fields. This is a
serialization use-case, is it not?
True, this is a very good point. I stepped back a bit and thought why
the pattern is compelling, and it seems the signifant use-case is when
you want to inject something, but do not want it to be constructed
immediately. That is, it enables easy lazy construction. With that
in mind it becomes clearer if the semantics & wording change. The
annotation would be @Lazy, as in:
@Inject Bar(@Lazy Foo foo) { ... }
This would instruct Guice to inject a Foo, but not actually construct
the underlying Foo until the first method is called. Internally it
would use something much like a Provider, the difference being
subsequent calls to get() return the same object. It's very much like
a non-eager Singleton within one injection scope.
Lazily constructing non-singletons today requires helper code and can
be bulky. Tim provided a nice package for simplifying it, but it
still requires the injecting a Provider of the object, and it's not
extremely clear what's going on.
Sam