Guice - How to provide the same key differently in different scopes?

733 views Asked by At

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.

0

There are 0 answers