Open chriskessel opened 8 years ago
Do you have an example I can use to reproduce this?
No, I'll have to work on one. And since it's non-deterministic, I'm not sure what part of the complexity of my current setup might be related.
Ok, I think I have a stand alone test. I ran this, hit both endpoints:
http://localhost:8080/a/foo http://localhost:8080/b/foo
In my log output, I can see:
INFO [2016-09-13 19:49:38,180] org.eclipse.jetty.server.Server: Started @3827ms
I'm A and I got: module a
127.0.0.1 - - [13/Sep/2016:19:52:06 +0000] "GET /a/foo HTTP/1.1" 200 - "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36" 70
I'm B and I got: module a
127.0.0.1 - - [13/Sep/2016:19:52:09 +0000] "GET /b/foo HTTP/1.1" 200 - "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36" 5
As you can see, the ModuleBApi got injected with the wrong string despite the binding annotation. Unless I'm doing something wrong with annotations?
I crammed everything into one file, so hopefully this is easy for you to test:
package com.kessel.test;
import com.codahale.metrics.annotation.ExceptionMetered;
import com.codahale.metrics.annotation.Timed;
import com.google.inject.AbstractModule;
import com.google.inject.BindingAnnotation;
import com.google.inject.Provides;
import com.google.inject.Stage;
import com.hubspot.dropwizard.guice.GuiceBundle;
import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
public class TestMain extends Application<TestMain.TestConfig> {
public static void main(String... args) throws Exception {
new TestMain().run(args);
}
public void initialize(Bootstrap<TestConfig> bootstrap) {
GuiceBundle.Builder<TestConfig> guiceBundleBuilder = GuiceBundle.newBuilder();
guiceBundleBuilder.addModule(new GuiceModuleA());
guiceBundleBuilder.addModule(new GuiceModuleB());
GuiceBundle<TestConfig> guiceBundle = guiceBundleBuilder.enableAutoConfig(getAutoConfigPackages()).build(Stage.DEVELOPMENT);
bootstrap.addBundle(guiceBundle);
}
protected String[] getAutoConfigPackages() {
return new String[]{this.getClass().getPackage().getName()};
}
public void run(TestConfig config, Environment environment) throws Exception {
}
public static class TestConfig extends Configuration {
}
public static class GuiceModuleA extends AbstractModule {
@Override
protected void configure() {
}
@Provides
@Singleton
@ModuleA
public String provideModuleAString() {
return "module a";
}
@BindingAnnotation
@Target({FIELD, PARAMETER, METHOD})
@Retention(RUNTIME)
public @interface ModuleA {
}
}
public static class GuiceModuleB extends AbstractModule {
@Override
protected void configure() {
}
@Provides
@Singleton
@ModuleB
public String provideModuleString() {
return "module b";
}
@BindingAnnotation
@Target({FIELD, PARAMETER, METHOD})
@Retention(RUNTIME)
public @interface ModuleB {
}
}
@Path("/a")
public static class ModuleAApi {
@Inject
public ModuleAApi(@GuiceModuleA.ModuleA String injectableThing) {
System.out.println("I'm A and I got: " + injectableThing);
}
@GET
@Timed
@ExceptionMetered
@Path("foo")
public Response foo() {
return Response.ok().build();
}
}
@Path("/b")
public static class ModuleBApi {
@Inject
public ModuleBApi(@GuiceModuleB.ModuleB String injectableThing) {
System.out.println("I'm B and I got: " + injectableThing);
}
@GET
@Timed
@ExceptionMetered
@Path("foo")
public Response foo() {
return Response.ok().build();
}
}
}
I tried to file this with Guice, but they won't look at it because I'm using Dropwizard, so maybe this is the right place?
I have two modules, each provides an instance of the same class (a specific Gson configuration). So, each module has a method like so:
Then I have constructors for classes that use those Gson items, that look like:
This does NOT work consistently. Sometimes it injects the @ModuleB version of Gson into things annotationed with @ModuleA.
I'm using Dropwizard 0.8.5 with dropwizard-guice 0.8.4 and Guice 4.1.