Skip to content

Commit

Permalink
Merge pull request #2 from segfly/master
Browse files Browse the repository at this point in the history
Custom injectors support
  • Loading branch information
xvik committed Jan 2, 2015
2 parents cd37686 + 44d9be5 commit 5da8d7d
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 4 deletions.
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,37 @@ This will work only for modules set to `modules()` bundle option.

[Example](https://github.com/xvik/dropwizard-guicey/blob/master/src/test/groovy/ru/vyarus/dropwizard/guice/support/AutowiredModule.groovy)

### Custom Injectors

Some Guice extension libraries require Injectors created by their API.
A custom Injector may be supplied by implementing `InjectorFactory` and passing an instance of this implementation to the bundle builder.
For example, to add support for https://github.com/Netflix/governator one might create a factory like the following:

```java
public class GovernatorInjectorFactory implements InjectorFactory {
@Override
public Injector createInjector(Stage stage, Iterable<? extends Module> modules) {
return LifecycleInjector.builder().withModules(modules).build().createInjector();;
}
}
```

and provide this factory when building the bundle for dropwizard:

```java
@Override
void initialize(Bootstrap<TestConfiguration> bootstrap) {
bootstrap.addBundle(GuiceBundle.<TestConfiguration> builder()
.installers(ResourceInstaller.class, TaskInstaller.class, ManagedInstaller.class)
.extensions(MyTask.class, MyResource.class, MyManaged.class)
.modules(new MyModule())
.injectorFactory(new GovernatorInjectorFactory())
.build()
);
bootstrap.addCommand(new MyCommand())
}
```

### Extension ordering

Some installers support extensions ordering (managed, lifecycle and admin servlet and filters).
Expand Down
4 changes: 2 additions & 2 deletions gradle/config/pmd/pmd.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
<property name="minimum" value="30"/>
</properties>
</rule>
<rule ref="rulesets/java/codesize.xml/ExcessiveClassLength" message="Avoid classes longer than 200 lines">
<rule ref="rulesets/java/codesize.xml/ExcessiveClassLength" message="Avoid classes longer than 300 lines">
<properties>
<property name="minimum" value="200"/>
<property name="minimum" value="300"/>
</properties>
</rule>
<rule ref="rulesets/java/codesize.xml/TooManyMethods" message="Avoid classes longer than 25 methods">
Expand Down
32 changes: 30 additions & 2 deletions src/main/java/ru/vyarus/dropwizard/guice/GuiceBundle.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import java.util.List;
import java.util.Set;

import ru.vyarus.dropwizard.guice.api.InjectorFactory;

/**
* Bundle enables guice integration for dropwizard. Guice context is configured in initialization phase,
* but actual injector is created on run phase, This approach provides greater configuration options, because during
Expand Down Expand Up @@ -65,7 +67,8 @@
*/
public final class GuiceBundle<T extends Configuration> implements ConfiguredBundle<T> {

private static Injector injector;
private static Injector injector;
private InjectorFactory injectorFactory = new DefaultInjectorFactoryImpl();

private final List<Module> modules = Lists.newArrayList();
private final Set<String> autoscanPackages = Sets.newHashSet();
Expand Down Expand Up @@ -102,7 +105,7 @@ public void initialize(final Bootstrap bootstrap) {
public void run(final T configuration, final Environment environment) throws Exception {
modules.add(new GuiceSupportModule(scanner, installerConfig));
configureModules(configuration, environment);
GuiceBundle.injector = Guice.createInjector(stage, modules);
GuiceBundle.injector = injectorFactory.createInjector(stage, modules);
CommandSupport.initCommands(bootstrap.getCommands(), injector);
}

Expand Down Expand Up @@ -150,6 +153,18 @@ public static <T extends Configuration> Builder<T> builder() {
public static class Builder<T extends Configuration> {
private final GuiceBundle<T> bundle = new GuiceBundle<T>();

/**
* Configures as custom {@link InjectorFactory}.
*
* @param injectorFactory
* a custom factory for creating Guice injectors
* @return builder instance for chained calls
*/
public Builder<T> injectorFactory(final InjectorFactory injectorFactory) {
bundle.injectorFactory = injectorFactory;
return this;
}

/**
* Enables auto scan feature.
*
Expand Down Expand Up @@ -253,4 +268,17 @@ public GuiceBundle<T> build() {
return build(Stage.PRODUCTION);
}
}

/**
* A default {@link InjectorFactory} that simply delegates to {@link Guice#createInjector(Stage, Module...)}.
*
* @author Nicholas Pace
* @since Dec 26, 2014
*/
private class DefaultInjectorFactoryImpl implements InjectorFactory {
@Override
public Injector createInjector(final Stage stage, final Iterable<? extends Module> modules) {
return Guice.createInjector(stage, modules);
}
}
}
26 changes: 26 additions & 0 deletions src/main/java/ru/vyarus/dropwizard/guice/api/InjectorFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.vyarus.dropwizard.guice.api;

import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Stage;

/**
* This interface may be implemented to provide custom Guice injectors and support certain types of Guice extension
* libraries.
*
* @author Nicholas Pace
* @since Dec 26, 2014
*/
public interface InjectorFactory {

/**
* Creates an injector instance.
*
* @param stage
* The stage for which the injector is created.
* @param modules
* A list of modules for the injector.
* @return A new injector.
*/
Injector createInjector(Stage stage, Iterable<? extends Module> modules);
}
22 changes: 22 additions & 0 deletions src/test/groovy/ru/vyarus/dropwizard/guice/unit/BundleTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import io.dropwizard.setup.Bootstrap
import io.dropwizard.setup.Environment
import ru.vyarus.dropwizard.guice.AbstractTest
import ru.vyarus.dropwizard.guice.GuiceBundle
import ru.vyarus.dropwizard.guice.api.InjectorFactory;
import com.google.inject.Injector;

/**
* @author Vyacheslav Rusakov
Expand All @@ -30,6 +32,26 @@ class BundleTest extends AbstractTest {
then: "injector available"
true
}

def "Check custom injector factory"() {
InjectorFactory mockInjectorFactory = Mock()
Injector mockInjector = Mock()

when: "using default factory"
GuiceBundle bundle = GuiceBundle.builder().build()
bundle.initialize(Mock(Bootstrap))
bundle.run(Mock(Configuration), mockEnvironment())
then: "injector is a Guice injector"
GuiceBundle.getInjector() instanceof Injector

when: "using custom factory"
bundle = GuiceBundle.builder().injectorFactory(mockInjectorFactory).build()
bundle.initialize(Mock(Bootstrap))
bundle.run(Mock(Configuration), mockEnvironment())
then: "injector factory has been customized"
1 * mockInjectorFactory.createInjector(_, _) >> mockInjector
GuiceBundle.getInjector() == mockInjector
}

def "Check commands search" () {

Expand Down

0 comments on commit 5da8d7d

Please sign in to comment.