Guice users! I have a situation here and I could find a workaround, but I'm not satisfied with my solution. It's very similar to Using the provider from two different scopes, but the answer there doesn't fit my situation.
I have a class like this, which I inject in a lot of places:
MyBusinessClass {
@Inject
MyBusinessClass(@AuthenticatedUser User user) {};
}
Up to some moment in the past, I just got the @AuthenticatedUser User
from the web session, so I had:
bind(User.class).annotatedWith(AuthenticatedUser.class).toProvider(new AuthenticatedUserProvider());
...
public static class AuthenticatedUserProvider implements Provider<User> {
@Inject
Provider<Session> session;
public User get() {
return SessionUtil.getUserFromSession(session.get());
}
}
The problem:
That worked great till I needed to use the same MyBusinessClass
inside a different Guice scope (and also outside the request scope). I created a JobScope, very similiar to the scope example in Guice docs, created a kind of JobSession, binded it to the JobScope, and put the @AuthenticatedUser User
instance I want injected when MyBusinessClass
is used inside the JobSession.
That's where I'm not proud of what I did.. I "improved" my provider to try to provide the @AuthenticatedUser User
for all scopes, and I ended up with this ugly provider:
public static class AuthenticatedUserProvider implements Provider<User> {
@com.google.inject.Inject(optional=true)
Provider<Session> session;
@com.google.inject.Inject(optional=true)
Provider<JobSession> jobSession;
@Override
public User get() {
try {
return SessionUtil.getUserFromSession(session.get());
} catch (Exception e) {
try {
return SessionUtil.getUserFromJobSession(jobSession.get());
} catch (Exception ee) {
throw new IllegalStateException("Current scope doesn't have a auth user!");
}
}
}
}
The provider does a try-an-error approach to find which session (web session or job session) is available and return the user for the first one it is able to get. It works because of the @com.google.inject.Inject(optional=true)
and also because the scopes are mutually exclusive.
Is there a better way to achieve this? I just want to have MyBusinessClass
injected with @AuthenticatedUser User
for any scope it is used transparently, and let Guice modules/providers find the right place to get the satisfying instance.