
com.hubspot.dropwizard.guicier.GuiceBundle Maven / Gradle / Ivy
package com.hubspot.dropwizard.guicier;
import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.Field;
import java.util.Arrays;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.internal.ServiceLocatorFactoryImpl;
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.GuiceServletContextListener;
import com.google.inject.servlet.ServletModule;
import com.google.inject.util.Modules;
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 final boolean allowUnknownFields;
private final boolean enableGuiceEnforcer;
private final InjectorFactory injectorFactory;
private Bootstrap> bootstrap = null;
private Injector injector = null;
private GuiceBundle(final Class configClass,
final ImmutableSet guiceModules,
final ImmutableSet> dropwizardAwareModules,
final Stage guiceStage,
final boolean allowUnknownFields,
final boolean enableGuiceEnforcer,
final InjectorFactory injectorFactory) {
this.configClass = configClass;
this.guiceModules = guiceModules;
this.dropwizardAwareModules = dropwizardAwareModules;
this.guiceStage = guiceStage;
this.allowUnknownFields = allowUnknownFields;
this.enableGuiceEnforcer = enableGuiceEnforcer;
this.injectorFactory = injectorFactory;
}
@Override
public void initialize(final Bootstrap> bootstrap) {
this.bootstrap = bootstrap;
if (allowUnknownFields) {
AllowUnknownFieldsObjectMapper.applyTo(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(environment);
// We assume that the next service locator will be the main application one
final String serviceLocatorName = getNextServiceLocatorName();
ImmutableSet.Builder modulesBuilder =
ImmutableSet.builder()
.addAll(guiceModules)
.addAll(dropwizardAwareModules)
.add(new ServletModule())
.add(dropwizardModule)
.add(new JerseyGuiceModule(serviceLocatorName))
.add(new JerseyGuicierModule())
.add(new Module() {
@Override
public void configure(final Binder binder) {
binder.bind(Environment.class).toInstance(environment);
binder.bind(configClass).toInstance(configuration);
}
});
if (enableGuiceEnforcer) {
modulesBuilder.add(new GuiceEnforcerModule());
}
this.injector = injectorFactory.create(guiceStage, Modules.combine(modulesBuilder.build()));
JerseyGuiceUtils.install((name, parent) -> {
if (!name.startsWith("__HK2_")) {
return null;
} else if (serviceLocatorName.equals(name)) {
return injector.getInstance(ServiceLocator.class);
} else {
LOG.debug("Returning a new ServiceLocator for name '%s'", name);
return JerseyGuiceUtils.newServiceLocator(name, parent);
}
});
dropwizardModule.register(injector);
environment.servlets().addFilter("Guice Filter", GuiceFilter.class).addMappingForUrlPatterns(null, false, "/*");
environment.servlets().addServletListeners(new GuiceServletContextListener() {
@Override
protected Injector getInjector() {
return injector;
}
});
}
public Injector getInjector() {
return checkNotNull(injector, "injector has not been initialized yet");
}
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 boolean allowUnknownFields = true;
private boolean enableGuiceEnforcer = true;
private InjectorFactory injectorFactory = Guice::createInjector;
private Builder(final Class configClass) {
this.configClass = configClass;
}
public final Builder stage(final Stage guiceStage) {
checkNotNull(guiceStage, "guiceStage is null");
this.guiceStage = guiceStage;
return this;
}
public final Builder allowUnknownFields(final boolean allowUnknownFields) {
this.allowUnknownFields = allowUnknownFields;
return this;
}
public final Builder enableGuiceEnforcer(final boolean enableGuiceEnforcer) {
this.enableGuiceEnforcer = enableGuiceEnforcer;
return this;
}
public final Builder modules(final Module... modules) {
return modules(Arrays.asList(modules));
}
@SuppressWarnings("unchecked")
public final Builder modules(final Iterable extends Module> modules) {
for (Module module : modules) {
if (module instanceof DropwizardAwareModule>) {
dropwizardAwareModules.add((DropwizardAwareModule) module);
} else {
guiceModules.add(module);
}
}
return this;
}
public final Builder injectorFactory(final InjectorFactory injectorFactory) {
this.injectorFactory = injectorFactory;
return this;
}
public final GuiceBundle build() {
return new GuiceBundle<>(configClass,
guiceModules.build(),
dropwizardAwareModules.build(),
guiceStage,
allowUnknownFields,
enableGuiceEnforcer,
injectorFactory);
}
}
private static String getNextServiceLocatorName() {
Class factoryClass = ServiceLocatorFactoryImpl.class;
try {
Field nameCountField = factoryClass.getDeclaredField("name_count");
nameCountField.setAccessible(true);
int count = (int) nameCountField.get(null);
Field namePrefixField = factoryClass.getDeclaredField("GENERATED_NAME_PREFIX");
namePrefixField.setAccessible(true);
String prefix = (String) namePrefixField.get(null);
return prefix + count;
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy