Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class HelloWorldApplication extends Application<HelloWorldConfiguration>
}
```

Lastly, you can enable auto configuration via package scanning.
You can enable auto configuration via package scanning.
```java
public class HelloWorldApplication extends Application<HelloWorldConfiguration> {

Expand All @@ -69,6 +69,9 @@ public class HelloWorldApplication extends Application<HelloWorldConfiguration>
.build();

bootstrap.addBundle(guiceBundle);
// with AutoConfig enabled you don't need to add bundles or commands explicitly here.
// inherit from one of InjectedCommand, InjectedConfiguredCommand, or InjectedEnvironmentCommand
// to get access to all modules during injection.
}

@Override
Expand All @@ -83,6 +86,47 @@ public class HelloWorldApplication extends Application<HelloWorldConfiguration>
}
}
```

Modules will also be injected before being added. Field injections only, constructor based injections will not be available.
Configuration data and initialization module data will be available for injecting into modules.
```java


public class HelloWorldApplication extends Application<HelloWorldConfiguration> {

public static void main(String[] args) throws Exception {
new HelloWorldApplication().run(args);
}

@Override
public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {

GuiceBundle<HelloWorldConfiguration> guiceBundle = GuiceBundle.<HelloWorldConfiguration>newBuilder()
.addInitModule(new BaseModule())
// bindings defined in the BaseModule or any configuration data is available for
// injection into HelloWorldModule fields
.addModule(new HelloWorldModule())
//Any resource, task, bundle, etc within this class path will be included automatically.
.enableAutoConfig(getClass().getPackage().getName())
//The contents of any config objects within this package path will be auto-injected.
.addConfigPackages(getClass().getPackage().getName())
.setConfigClass(HelloWorldConfiguration.class)
.build();

bootstrap.addBundle(guiceBundle);
}

@Override
public String getName() {
return "hello-world";
}

@Override
public void run(HelloWorldConfiguration helloWorldConfiguration, Environment environment) throws Exception {
}
}
```

If you are having trouble accessing your Configuration or Environment inside a Guice Module, you could try using a provider.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update this documentation to refer to initiModules vs Modules?


```java
Expand Down
9 changes: 7 additions & 2 deletions pom.xml
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,9 @@
</developers>

<properties>
<io.dropwizard.version>0.8.0-rc3</io.dropwizard.version>
<io.dropwizard.version>0.8.0</io.dropwizard.version>
</properties>


<dependencies>
<dependency>
<groupId>com.google.code.findbugs</groupId>
Expand Down Expand Up @@ -109,6 +108,12 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>2.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-testing</artifactId>
Expand Down
99 changes: 79 additions & 20 deletions src/main/java/com/hubspot/dropwizard/guice/AutoConfig.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
package com.hubspot.dropwizard.guice;

import com.google.inject.ConfigurationException;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.hubspot.dropwizard.guice.command.InjectedCommand;
import com.hubspot.dropwizard.guice.command.InjectedConfiguredCommand;
import com.hubspot.dropwizard.guice.command.InjectedEnvironmentCommand;
import io.dropwizard.Bundle;
import io.dropwizard.ConfiguredBundle;
import io.dropwizard.cli.Command;
import io.dropwizard.cli.ConfiguredCommand;
import io.dropwizard.cli.EnvironmentCommand;
import io.dropwizard.lifecycle.Managed;
import io.dropwizard.servlets.tasks.Task;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;

import com.google.common.base.Preconditions;
import com.google.inject.Injector;
import org.glassfish.jersey.server.model.Resource;
Expand All @@ -21,6 +31,7 @@
import javax.ws.rs.Path;
import javax.ws.rs.ext.ParamConverterProvider;
import javax.ws.rs.ext.Provider;
import java.util.Collection;
import java.util.Set;

public class AutoConfig {
Expand Down Expand Up @@ -55,34 +66,46 @@ public void run(Environment environment, Injector injector) {

public void initialize(Bootstrap<?> bootstrap, Injector injector) {
addBundles(bootstrap, injector);
addConfiguredBundles(bootstrap, injector);
addCommands(bootstrap, injector);
}

private void addManaged(Environment environment, Injector injector) {
Set<Class<? extends Managed>> managedClasses = reflections
.getSubTypesOf(Managed.class);
for (Class<? extends Managed> managed : managedClasses) {
environment.lifecycle().manage(injector.getInstance(managed));
logger.info("Added managed: {}", managed);
try {
environment.lifecycle().manage(injector.getInstance(managed));
logger.info("Added managed: {}", managed);
} catch (ConfigurationException e) {
logger.warn("Could not get instance of managed: {}", managed);
}
}
}

private void addTasks(Environment environment, Injector injector) {
Set<Class<? extends Task>> taskClasses = reflections
.getSubTypesOf(Task.class);
for (Class<? extends Task> task : taskClasses) {
environment.admin().addTask(injector.getInstance(task));
logger.info("Added task: {}", task);
try {
environment.admin().addTask(injector.getInstance(task));
logger.info("Added task: {}", task);
} catch (ConfigurationException e) {
logger.warn("Could not get instance of task: {}", task);
}
}
}

private void addHealthChecks(Environment environment, Injector injector) {
Set<Class<? extends InjectableHealthCheck>> healthCheckClasses = reflections
.getSubTypesOf(InjectableHealthCheck.class);
for (Class<? extends InjectableHealthCheck> healthCheck : healthCheckClasses) {
InjectableHealthCheck instance = injector.getInstance(healthCheck);
environment.healthChecks().register(instance.getName(), instance);
logger.info("Added injectableHealthCheck: {}", healthCheck);
try {
InjectableHealthCheck instance = injector.getInstance(healthCheck);
environment.healthChecks().register(instance.getName(), instance);
logger.info("Added injectableHealthCheck: {}", healthCheck);
} catch (ConfigurationException e) {
logger.warn("Could not get instance of InjectableHealthCheck: {}", healthCheck);
}
}
}

Expand All @@ -106,27 +129,63 @@ private void addResources(Environment environment) {
}
}

@SuppressWarnings("rawtypes")
private void addBundles(Bootstrap<?> bootstrap, Injector injector) {
Set<Class<? extends Bundle>> bundleClasses = reflections
.getSubTypesOf(Bundle.class);
for (Class<? extends Bundle> bundle : bundleClasses) {
bootstrap.addBundle(injector.getInstance(bundle));
logger.info("Added bundle class {} during bootstrap", bundle);
try {
bootstrap.addBundle(injector.getInstance(bundle));
logger.info("Added bundle class {} during bootstrap", bundle);
} catch (ConfigurationException e) {
logger.warn("Could not get instance of bundle: {}", bundle);
}
}
}

@SuppressWarnings("unchecked")
private void addConfiguredBundles(Bootstrap<?> bootstrap, Injector injector) {
Set<Class<? extends ConfiguredBundle>> configuredBundleClasses = reflections
.getSubTypesOf(ConfiguredBundle.class);
for (Class<? extends ConfiguredBundle> configuredBundle : configuredBundleClasses) {
if (configuredBundle != GuiceBundle.class) {
bootstrap.addBundle(injector.getInstance(configuredBundle));
logger.info("Added configured bundle class {} during bootstrap", configuredBundle);
Set<Class<? extends ConfiguredBundle>> configuredBundleClasses = reflections.getSubTypesOf(ConfiguredBundle.class);
for(Class<? extends ConfiguredBundle> bundle : configuredBundleClasses)
{
if(!bundle.equals(GuiceBundle.class))
{
try {
bootstrap.addBundle(injector.getInstance(bundle));
logger.info("Added configured bundle class {} during bootstrap", bundle);
} catch (ConfigurationException e) {
logger.warn("Could not get instance of configured bundle: {}", bundle);
}
}
}
}

private void addCommands(Bootstrap<?> bootstrap, Injector injector) {
Collection<Object> existingCommands = Collections2.transform(bootstrap.getCommands(),
new Function<Command, Object>() {
@Override
public Class<? extends Command> apply(Command input) {
return input.getClass();
}
});

Set<Class<? extends Command>> commandClasses = reflections.getSubTypesOf(Command.class);
//The SubTypesScanner does not resolve the entire ancestry of a class
//This won't get subtyped Commands. If this becomes a problem, a
//replacement Scanner could be written. It is getting a bit ridiculous
//with all the Injected commands as well.
commandClasses.addAll(reflections.getSubTypesOf(ConfiguredCommand.class));
commandClasses.addAll(reflections.getSubTypesOf(EnvironmentCommand.class));
commandClasses.addAll(reflections.getSubTypesOf(InjectedCommand.class));
commandClasses.addAll(reflections.getSubTypesOf(InjectedConfiguredCommand.class));
commandClasses.addAll(reflections.getSubTypesOf(InjectedEnvironmentCommand.class));
for(Class<? extends Command> command : commandClasses) {
if(existingCommands.contains(command)) continue;
try {
bootstrap.addCommand(injector.getInstance(command));
logger.info("Added command class {} during bootstrap", command);
} catch (ConfigurationException e) {
logger.warn("Could not get instance of command: {}", command);
}
}
}

private void addParamConverterProviders(Environment environment) {
Set<Class<? extends ParamConverterProvider>> providerClasses = reflections
.getSubTypesOf(ParamConverterProvider.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package com.hubspot.dropwizard.guice;

import com.google.common.base.Optional;
import com.google.inject.*;
import com.google.inject.name.Names;
import io.dropwizard.Configuration;
import io.dropwizard.jetty.MutableServletContextHandler;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import com.google.inject.AbstractModule;
import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import net.sourceforge.argparse4j.inf.Namespace;

import javax.servlet.ServletContext;

public class DropwizardEnvironmentModule<T extends Configuration> extends AbstractModule {
private static final String ILLEGAL_DROPWIZARD_MODULE_STATE = "The dropwizard environment has not yet been set. This is likely caused by trying to access the dropwizard environment during the bootstrap phase.";
private T configuration;
private Environment environment;
private static final String ILLEGAL_DROPWIZARD_MODULE_STATE = "The dropwizard environment has not been set. This is likely caused by trying to access the dropwizard environment during the bootstrap phase or during a non-configured command.";
private Optional<T> configuration;
private Optional<Environment> environment;
private Optional<Namespace> namespace = Optional.absent();
private Optional<Bootstrap<T>> bootstrap;
private Class<? super T> configurationClass;

public DropwizardEnvironmentModule(Class<T> configurationClass) {
Expand All @@ -20,32 +26,78 @@ public DropwizardEnvironmentModule(Class<T> configurationClass) {
@Override
protected void configure() {
Provider<T> provider = new CustomConfigurationProvider();
bind(configurationClass).toProvider(provider);
if (configurationClass != Configuration.class) {
bind(Configuration.class).toProvider(provider);
}
if(configuration.isPresent()){
bind(configurationClass).toProvider(provider);
if (configurationClass != Configuration.class) {
bind(Configuration.class).toProvider(provider);
}
}
if(environment.isPresent()) {
bindContext("application", environment.get().getApplicationContext());
}
}

/**
* Bind some of the context objects to be injectable. Annotated with a {@link com.google.inject.name.Names} to
* prevent collisions for any that the {@link com.google.inject.servlet.ServletModule} may bind later.
*/
private void bindContext(String name, MutableServletContextHandler context) {
bind(ServletContext.class)
.annotatedWith(Names.named(name))
.toInstance(context.getServletContext());
}

@Deprecated
public void setEnvironmentData(T configuration, Environment environment) {
this.configuration = configuration;
this.environment = environment;
setEnvironmentData(null, environment, configuration);
}

public void setEnvironmentData(Bootstrap<T> bootstrap,
Environment environment,
T configuration) {
this.bootstrap = Optional.fromNullable(bootstrap);
this.configuration = Optional.fromNullable(configuration);
this.environment = Optional.fromNullable(environment);
}

public void setNamespace(Namespace namespace) {
this.namespace = Optional.fromNullable(namespace);
}

@Provides
public Environment providesEnvironment() {
if (environment == null) {
if (environment == null || !environment.isPresent()) {
throw new ProvisionException(ILLEGAL_DROPWIZARD_MODULE_STATE);
}
return environment;
return environment.get();
}

@Provides
public Namespace providesNamespace() {
if (namespace == null || !namespace.isPresent()) {
throw new ProvisionException(ILLEGAL_DROPWIZARD_MODULE_STATE);
}
return namespace.get();
}

/**
* Note: This is a raw type. Guice cannot inject the full type due to type erasure
*/
@Provides
public Bootstrap providesBootstrap() {
if (bootstrap == null || !bootstrap.isPresent()) {
throw new ProvisionException(ILLEGAL_DROPWIZARD_MODULE_STATE);
}
return bootstrap.get();
}

private class CustomConfigurationProvider implements Provider<T> {
@Override
public T get() {
if (configuration == null) {
if (configuration == null || !configuration.isPresent()) {
throw new ProvisionException(ILLEGAL_DROPWIZARD_MODULE_STATE);
}
return configuration;
return configuration.get();
}
}
}
Loading