Skip to content

Instantly share code, notes, and snippets.

@joschi
Last active September 21, 2018 00:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joschi/f706e394172988f9200b to your computer and use it in GitHub Desktop.
Save joschi/f706e394172988f9200b to your computer and use it in GitHub Desktop.
Dropwizard HK2
public class DropwizardHaKaZwei extends Application<MyConfiguration> {
// [...]
public void run(MyConfiguration config, Environment environment) {
// HK2 stuff
environment.jersey().register(new AbstractBinder() {
@Override
protected void configure() {
bind(config).to(MyConfiguration.class);
bind(environment).to(Environment.class);
bind(environment.lifecycle()).to(LifecycleEnvironment.class);
bind(environment.metrics()).to(MetricRegistry.class);
bind(environment.getValidator()).to(Validator.class);
bind(jdbi).to(DBI.class);
bind(myDao).to(MyDao.class);
}
});
}
}
@Path("/foobar")
public class MyResource {
@Inject
private DBI jdbi;
@Context
private ContainerRequest request;
@Timed
@GET
@Consumes(MediaType.APPLICATION_JSON)
public Response foobar(@HeaderParam() {
// [...]
return Response.accepted().build();
}
}
@luckyluke80
Copy link

Can you make the binding of bind(myDao).to(MyDao.class); a little bit more clear?

What has to come first?
PersonDAO dao = new PersonDAO(hibernateBundle.getSessionFactory());
environment.jersey().register(new PeopleResource(dao));

and then
bind(myDao).to(MyDao.class);
?

@leordev
Copy link

leordev commented Aug 19, 2016

@luckyluke80 hey buddy the following code worked for me:

    // Register JDBI
    final DBIFactory factory = new DBIFactory();
    final DBI jdbi = factory.build(environment, configuration.getDataSourceFactory(), "database");

    // Import DAOs
    final UserProfileDAO userProfileDAO = jdbi.onDemand(UserProfileDAO.class);
    final UserLogDAO userLogDAO = jdbi.onDemand(UserLogDAO.class);
    final UserPageDAO userPageDAO = jdbi.onDemand(UserPageDAO.class);
    final AccountUserDAO accountUserDAO = jdbi.onDemand(AccountUserDAO.class);
    final ClientDAO clientDAO = jdbi.onDemand(ClientDAO.class);
    final AccountDAO accountDAO = jdbi.onDemand(AccountDAO.class);
    final AccountFeeDAO accountFeeDAO = jdbi.onDemand(AccountFeeDAO.class);
    final TransactionDAO transactionDAO = jdbi.onDemand(TransactionDAO.class);
    final InvoiceDAO invoiceDAO = jdbi.onDemand(InvoiceDAO.class);
    final InvoiceSettingsDAO invoiceSettingsDAO = jdbi.onDemand(InvoiceSettingsDAO.class);
    final CustomerDAO customerDAO = jdbi.onDemand(CustomerDAO.class);

    environment.jersey().register(new AbstractBinder() {
        @Override
        protected void configure() {
            bind(configuration).to(MainApplicationConfiguration.class);
            bind(environment).to(Environment.class);
            bind(environment.lifecycle()).to(LifecycleEnvironment.class);
            bind(environment.metrics()).to(MetricRegistry.class);
            bind(environment.getValidator()).to(Validator.class);
            bind(jdbi).to(DBI.class);

            bind(userProfileDAO).to(UserProfileDAO.class);
            bind(userLogDAO).to(UserLogDAO.class);
            bind(userPageDAO).to(UserPageDAO.class);
            bind(accountUserDAO).to(AccountUserDAO.class);
            bind(clientDAO).to(ClientDAO.class);
            bind(accountDAO).to(AccountDAO.class);
            bind(resellerDAO).to(ResellerDAO.class);
            bind(invoiceDAO).to(InvoiceDAO.class);
            bind(invoiceSettingsDAO).to(InvoiceSettingsDAO.class);
            bind(customerDAO).to(CustomerDAO.class);

            bind(Tasks.class).to(Tasks.class);

            bind(MainAuthenticator.class).to(MainAuthenticator.class);
            bind(AuthFeature.class).to(AuthFeature.class);
        }
    });

    // Add URL mapping
    environment.jersey().register(LoginResource.class);
    environment.jersey().register(UserResource.class);
    environment.jersey().register(ClientResource.class);
    environment.jersey().register(AccountResource.class);
    environment.jersey().register(InvoiceResource.class);
    environment.jersey().register(InvoiceSettingsResource.class);
    environment.jersey().register(CustomerResource.class);
    environment.jersey().register(GeneralSettingsResource.class);
    environment.jersey().register(APIResource.class);

    // Register Auth Service
    environment.jersey().register(AuthFeature.class);
    environment.jersey().register(RolesAllowedDynamicFeature.class);
    environment.jersey().register(new AuthValueFactoryProvider.Binder<>(UserProfile.class));

and then I just used @Inject in my resources...

@joschi can you confirm the above approach? is this correct?

Also, can you give me some directions how can I use AuthDynamicFeature (dropwizard-auth) in this DI scenario? I need to use the above MainAuthenticator class, which has UserProfileDAO dependency to check user access to the system and roles... After a lot of tries, I just give up, and created a class exactly the same, but injecting my needed object:

public class AuthFeature implements DynamicFeature {

@Inject
private MainAuthenticator mainAuthenticator;

@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
    final AnnotatedMethod am = new AnnotatedMethod(resourceInfo.getResourceMethod());
    final Annotation[][] parameterAnnotations = am.getParameterAnnotations();
    if (am.isAnnotationPresent(RolesAllowed.class) || am.isAnnotationPresent(DenyAll.class) ||
            am.isAnnotationPresent(PermitAll.class)) {
        context.register(new OAuthCredentialAuthFilter.Builder<UserProfile>()
                .setAuthenticator(mainAuthenticator)
                .setAuthorizer(new MainAuthorizer())
                .setPrefix("Bearer")
                .buildAuthFilter());
    } else {
        for (Annotation[] annotations : parameterAnnotations) {
            for (Annotation annotation : annotations) {
                if (annotation instanceof Auth) {
                    context.register(new OAuthCredentialAuthFilter.Builder<UserProfile>()
                            .setAuthenticator(mainAuthenticator)
                            .setAuthorizer(new MainAuthorizer())
                            .setPrefix("Bearer")
                            .buildAuthFilter());
                    return;
                }
            }
        }
    }
}
}

But I think it's not cool, also it's creating OAuthCredentialAuthFilter instead of use a singleton... Can you help me on that?

Thank you guys!

@saumitrabhave
Copy link

Have not tested, but you can do something like following in your Application's run method

environment.jersey().getResourceConfig().register(new ContainerLifecycleListener() {
      public void onStartup(Container container) {
        /*Get the HK2 Service Locator*/
        ServiceLocator serviceLocator = container.getApplicationHandler().getServiceLocator();
       /*Ask for Instance to ServiceLocator so that it resolves all Injections, Scopes, Qualifiers etc.*/
        MyAuthFeatureOrWhatever object = serviceLocator.getService(MyAuthFeatureOrWhatever.class);
        environment.jersey().register(object);
      }

      public void onReload(Container container) {/*...*/}

      public void onShutdown(Container container) {/*...*/}
    });

you can use the Factory based binding bindFactory() in HK2 configure() to construct a complex object line AuthFeature which transitively needs other objects.

@leordev
Copy link

leordev commented Aug 19, 2016

@saumitrabhave I'm receiving an exception when I try to register that object in onStartup Lifecycle... This is the code that I added on the end of my run method:

    environment.jersey().getResourceConfig().register(new ContainerLifecycleListener() {
        public void onStartup(Container container) {
            /*Get the HK2 Service Locator*/
            ServiceLocator serviceLocator = container.getApplicationHandler().getServiceLocator();
            MainAuthenticator mainAuthenticator = serviceLocator.getService(MainAuthenticator.class);
            environment.jersey().register(new OAuthCredentialAuthFilter.Builder<UserProfile>()
                    .setAuthenticator(mainAuthenticator)
                    .setAuthorizer(new MainAuthorizer())
                    .setPrefix("Bearer")
                    .buildAuthFilter());
        }

        public void onReload(Container container) {/*...*/}

        public void onShutdown(Container container) {/*...*/}
    });

And this is the exception that I'm receiving:
Caused by: java.lang.IllegalStateException: The resource configuration is not modifiable in this context.
at org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:274)
at org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:221)
at org.glassfish.jersey.server.ResourceConfig.register(ResourceConfig.java:453)
at io.dropwizard.jersey.setup.JerseyEnvironment.register(JerseyEnvironment.java:36)
at com.check21.v2.MainApplication$3.onStartup(MainApplication.java:265)
at org.glassfish.jersey.server.ApplicationHandler.onStartup(ApplicationHandler.java:1180)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:179)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:369)
at javax.servlet.GenericServlet.init(GenericServlet.java:244)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:640)
... 41 more

@luckyluke80
Copy link

awesome, thanks for the replys. your'e all great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment