Search code examples
javadependency-injectionjerseyhk2

Dependency-Injection of a class with constructor that need info about the user logged in SecurityContext


I'd like to use HK2 DI to automatically inject a new instance of a class depending on the user logged on my Jersey API.

User is logged with a class AuthenticationFilter and I can find get it into @Context SecurityContext in all my endpoints.

Thing is I have a DAO class that needs info about the user to be instanciated. It's just the schema on which I should execute the queries on the database.

So the constructor of my Dao is like this:

public UserDao(String schemaCompte) {
    super(schemaCompte);
}

What seems to be the solution is to use a Factory to instanciate my Dao with HK2 so I tried creating one like that:

public class UserDaoFactory implements Factory<UserDao> {

    @Context SecurityContext securityContext;

    @Override
    public UserDao provide() {
        User userPrincipal = (User) securityContext.getUserPrincipal();
        return new UserDao(userPrincipal.getCode());
    }

    @Override
    public void dispose(UserDao userDao) {
    }
}

And the binding goes like this:

bindFactory(UserDaoFactory.class).to(UserDao.class)

And implementation:

@Inject
public UserSvc(UserDao userDao) {
    ...
}

But this factory is called too soon in the lifecycle of my application and SecurityContext is still empty.

So as I understand it the solution for that to be executed at runtime would be to bind the Factory as a proxy like that:

bindFactory(UserDaoFactory.class).proxy(true).to(UserDao.class)

But when I do that I get a runtime exception:

java.lang.RuntimeException: java.lang.InstantiationException: com.metier.user.UserDao_$$_jvst5c_0

If anyone got an idea I've tried so many things and I'm completly out of luck


Solution

  • So, it turns out what I was missing was the annotation @PreMatching in the provider I registered in my Jersey Api.

    This annotation tells Jersey to execute this filter before everything else, even matching with the endpoint that was called.

    So in this filter I just read my Token and it was available in the UserDaoFactory where needed to inject the user account.

    I made a small github repo to explain my point: https://github.com/m4nu56/jersey-hk2 and also a Medium article: https://medium.com/@mnu/jersey-injection-dependency-example-with-hk2-84ebfb7cb2d2

    And In the end I didn't used the Factory since I didn't realize I can directly inject the user or the account in the constructor of my Dao.