All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hubspot.dropwizard.guicier.GuiceBundle Maven / Gradle / Ivy

package com.hubspot.dropwizard.guicier;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableSet;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Stage;
import com.google.inject.servlet.GuiceFilter;
import com.google.inject.servlet.ServletModule;
import com.squarespace.jersey2.guice.JerseyGuiceModule;
import com.squarespace.jersey2.guice.JerseyGuiceUtils;

import io.dropwizard.Configuration;
import io.dropwizard.ConfiguredBundle;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;

/**
 * @author Henning P. Schmiedehausen
 */
public class GuiceBundle implements ConfiguredBundle {
  private static final Logger LOG = LoggerFactory.getLogger(GuiceBundle.class);

  public static  Builder defaultBuilder(final Class configClass) {
    return new Builder<>(configClass);
  }

  private final Class configClass;
  private final ImmutableSet> dropwizardAwareModules;
  private final ImmutableSet guiceModules;
  private final Stage guiceStage;

  private Bootstrap bootstrap = null;

  private GuiceBundle(final Class configClass,
                      final ImmutableSet guiceModules,
                      final ImmutableSet> dropwizardAwareModules,
                      final Stage guiceStage) {
    this.configClass = configClass;

    this.guiceModules = guiceModules;
    this.dropwizardAwareModules = dropwizardAwareModules;
    this.guiceStage = guiceStage;
  }

  @Override
  public void initialize(final Bootstrap bootstrap) {
    this.bootstrap = bootstrap;
  }

  @Override
  public void run(final T configuration, final Environment environment) throws Exception {
    for (DropwizardAwareModule dropwizardAwareModule : dropwizardAwareModules) {
      dropwizardAwareModule.setBootstrap(bootstrap);
      dropwizardAwareModule.setConfiguration(configuration);
      dropwizardAwareModule.setEnvironment(environment);
    }

    final DropwizardModule dropwizardModule = new DropwizardModule();

    final Injector injector =
        Guice.createInjector(guiceStage,
                ImmutableSet.builder()
                        .addAll(guiceModules)
                        .addAll(dropwizardAwareModules)
                        .add(new GuiceEnforcerModule())
                        .add(new ServletModule())
                        .add(new JerseyGuiceModule("__HK2_Generated_0"))
                        .add(dropwizardModule)
                        .add(new Module() {
                          @Override
                          public void configure(final Binder binder) {
                            binder.bind(Environment.class).toInstance(environment);
                            binder.bind(configClass).toInstance(configuration);
                          }
                        }).build());
    JerseyGuiceUtils.install(injector);

    dropwizardModule.register(environment, injector);

    environment.servlets().addFilter("Guice Filter", GuiceFilter.class).addMappingForUrlPatterns(null, false, environment.getApplicationContext().getContextPath() + "*");
  }

  public static class GuiceEnforcerModule implements Module {
    @Override
    public void configure(final Binder binder) {
      binder.disableCircularProxies();
      binder.requireExplicitBindings();
      binder.requireExactBindingAnnotations();
      binder.requireAtInjectOnConstructors();
    }
  }

  public static class Builder {
    private final Class configClass;
    private final ImmutableSet.Builder guiceModules = ImmutableSet.builder();
    private final ImmutableSet.Builder> dropwizardAwareModules = ImmutableSet.builder();
    private Stage guiceStage = Stage.PRODUCTION;

    private Builder(final Class configClass) {
      this.configClass = configClass;
    }

    public final Builder stage(final Stage guiceStage) {
      checkNotNull(guiceStage, "guiceStage is null");
      if (guiceStage != Stage.PRODUCTION) {
        LOG.warn("Guice should only ever run in PRODUCTION mode except for testing!");
      }
      this.guiceStage = guiceStage;
      return this;
    }

    public final Builder modules(final Module... modules) {
      return modules(Arrays.asList(modules));
    }

    @SuppressWarnings("unchecked")
    public final Builder modules(final Iterable modules) {
      for (Module module : modules) {
        if (module instanceof DropwizardAwareModule) {
          dropwizardAwareModules.add((DropwizardAwareModule) module);
        } else {
          guiceModules.add(module);
        }
      }
      return this;
    }

    public final GuiceBundle build() {
      return new GuiceBundle(configClass, guiceModules.build(), dropwizardAwareModules.build(), guiceStage);
    }
  }
}