diff --git a/README.md b/README.md
index 8a9810e..666eb4c 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ A Dropwizard bundle to handle Guice integration.
com.hubspot.dropwizard
dropwizard-guicier
- 1.3.5.2
+ 5.0.0
```
diff --git a/pom.xml b/pom.xml
index 3f14b47..1e95fa4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,36 +5,70 @@
com.hubspot
basepom
- 63.7
+ 65.2-SNAPSHOT
com.hubspot.dropwizard
dropwizard-guicier
- 1.3.5.4-SNAPSHOT
-
- dropwizard-guicier
- Integrates Dropwizard REST framework with Guice dependency injection
+ 5.0.0-SNAPSHOT
true
+
+ 5.0.0
+ 4.2.37
+ 33.5.0-jre
+ 7.0.0
+ 3.0.6
+ 2.20.0
+ 3.1.11
+ 12.1.1
+ 1.5.18
+ 2.0.17
+
+ 17
- com.google.code.findbugs
- jsr305
- 3.0.2
+ jakarta.annotation
+ jakarta.annotation-api
+ 2.1.1
+
+
+ jakarta.inject
+ jakarta.inject-api
+ 2.0.1
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+ 6.0.0
+
+
+ jakarta.ws.rs
+ jakarta.ws.rs-api
+ 3.1.0
+
+
+ org.glassfish.jersey.inject
+ jersey-hk2
+ ${dep.jersey2.version}
- com.squarespace.jersey2-guice
- jersey2-guice-impl
- 1.0.6
-
+ org.hibernate.validator
+ hibernate-validator
+ 8.0.3.Final
+
+
+ org.eclipse.jetty
+ jetty-server
+ ${dep.jetty.version}
- com.google.inject.extensions
- guice-multibindings
+ org.eclipse.jetty.toolchain
+ jetty-servlet-api
@@ -42,54 +76,37 @@
-
-
- com.squarespace.jersey2-guice
- jersey2-guice-impl
-
-
- com.google.inject
- guice
-
- com.google.inject.extensions
- guice-servlet
+ com.fasterxml.jackson.core
+ jackson-databind
com.google.code.findbugs
annotations
-
- javax.inject
- javax.inject
-
com.google.guava
guava
- javax.servlet
- javax.servlet-api
-
-
- javax.validation
- validation-api
+ com.google.inject
+ guice
- javax.ws.rs
- javax.ws.rs-api
+ com.google.inject.extensions
+ guice-servlet
- org.slf4j
- slf4j-api
+ io.dropwizard
+ dropwizard-core
io.dropwizard
- dropwizard-servlets
+ dropwizard-jersey
io.dropwizard
- dropwizard-core
+ dropwizard-jetty
io.dropwizard
@@ -97,68 +114,104 @@
io.dropwizard
- dropwizard-jackson
+ dropwizard-servlets
- io.dropwizard
- dropwizard-jersey
+ io.dropwizard.metrics
+ metrics-healthchecks
- io.dropwizard
- dropwizard-jetty
+ jakarta.annotation
+ jakarta.annotation-api
- io.dropwizard.metrics
- metrics-core
+ jakarta.servlet
+ jakarta.servlet-api
- io.dropwizard.metrics
- metrics-healthchecks
+ jakarta.ws.rs
+ jakarta.ws.rs-api
- org.glassfish.jersey.core
- jersey-server
+ org.eclipse.jetty
+ jetty-server
+
+
+ org.glassfish.hk2
+ guice-bridge
org.glassfish.hk2
hk2-api
- com.fasterxml.jackson.core
- jackson-databind
+ org.glassfish.hk2
+ hk2-utils
- org.eclipse.jetty
- jetty-server
+ org.glassfish.jersey.core
+ jersey-common
-
- junit
- junit
- test
+ org.glassfish.jersey.core
+ jersey-server
- org.assertj
- assertj-core
- test
+ org.glassfish.jersey.inject
+ jersey-hk2
- org.mockito
- mockito-core
- test
+ org.slf4j
+ slf4j-api
+
io.dropwizard
dropwizard-testing
test
- io.dropwizard
- dropwizard-client
+ org.assertj
+ assertj-core
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
test
+
+
+
+
+ org.basepom.maven
+ duplicate-finder-maven-plugin
+
+
+
+
+
+ org.jspecify
+ jspecify
+
+
+ io.dropwizard.logback
+ logback-throttling-appender
+
+
+
+ org.jspecify.annotations.Nullable
+
+
+
+
+
+
+
+
+
https://github.com/HubSpot/dropwizard-guicier
@@ -184,4 +237,3 @@
HEAD
-
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/AllowUnknownFieldsObjectMapper.java b/src/main/java/com/hubspot/dropwizard/guicier/AllowUnknownFieldsObjectMapper.java
index 32ad71f..d9d98bb 100644
--- a/src/main/java/com/hubspot/dropwizard/guicier/AllowUnknownFieldsObjectMapper.java
+++ b/src/main/java/com/hubspot/dropwizard/guicier/AllowUnknownFieldsObjectMapper.java
@@ -2,7 +2,7 @@
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
-import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.core.setup.Bootstrap;
/**
* Dropwizard makes it really hard to allow unknown fields in the {@link io.dropwizard.Configuration}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/DropwizardAwareModule.java b/src/main/java/com/hubspot/dropwizard/guicier/DropwizardAwareModule.java
index 336a1eb..a830193 100644
--- a/src/main/java/com/hubspot/dropwizard/guicier/DropwizardAwareModule.java
+++ b/src/main/java/com/hubspot/dropwizard/guicier/DropwizardAwareModule.java
@@ -4,9 +4,9 @@
import static com.google.common.base.Preconditions.checkState;
import com.google.inject.Module;
-import io.dropwizard.Configuration;
-import io.dropwizard.setup.Bootstrap;
-import io.dropwizard.setup.Environment;
+import io.dropwizard.core.Configuration;
+import io.dropwizard.core.setup.Bootstrap;
+import io.dropwizard.core.setup.Environment;
public abstract class DropwizardAwareModule implements Module {
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/DropwizardModule.java b/src/main/java/com/hubspot/dropwizard/guicier/DropwizardModule.java
index 25084d0..d0b6486 100644
--- a/src/main/java/com/hubspot/dropwizard/guicier/DropwizardModule.java
+++ b/src/main/java/com/hubspot/dropwizard/guicier/DropwizardModule.java
@@ -7,13 +7,14 @@
import com.google.inject.Module;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.ProvisionListener;
+import com.hubspot.dropwizard.guicier.injection.InjectorProvider;
+import io.dropwizard.core.setup.Environment;
import io.dropwizard.lifecycle.Managed;
import io.dropwizard.lifecycle.ServerLifecycleListener;
import io.dropwizard.servlets.tasks.Task;
-import io.dropwizard.setup.Environment;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.ext.Provider;
import java.lang.reflect.Type;
-import javax.ws.rs.Path;
-import javax.ws.rs.ext.Provider;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.model.Resource;
import org.slf4j.Logger;
@@ -59,6 +60,7 @@ public void onProvision(ProvisionInvocation provision) {
}
public void register(Injector injector) {
+ InjectorProvider.set(injector);
registerResourcesAndProviders(environment.jersey().getResourceConfig(), injector);
}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/GuiceBundle.java b/src/main/java/com/hubspot/dropwizard/guicier/GuiceBundle.java
index 9bd65ac..9b54637 100644
--- a/src/main/java/com/hubspot/dropwizard/guicier/GuiceBundle.java
+++ b/src/main/java/com/hubspot/dropwizard/guicier/GuiceBundle.java
@@ -11,16 +11,12 @@
import com.google.inject.servlet.GuiceFilter;
import com.google.inject.servlet.GuiceServletContextListener;
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;
-import java.lang.reflect.Field;
+import com.hubspot.dropwizard.guicier.injection.InjectionManagerProviderFeature;
+import io.dropwizard.core.Configuration;
+import io.dropwizard.core.ConfiguredBundle;
+import io.dropwizard.core.setup.Bootstrap;
+import io.dropwizard.core.setup.Environment;
import java.util.Arrays;
-import org.glassfish.hk2.api.ServiceLocator;
-import org.glassfish.hk2.internal.ServiceLocatorFactoryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -84,38 +80,25 @@ public void run(final T configuration, final Environment environment) throws Exc
}
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(binder -> {
binder.bind(Environment.class).toInstance(environment);
binder.bind(configClass).toInstance(configuration);
+ binder.bind(InjectionManagerProviderFeature.class);
});
if (enableGuiceEnforcer) {
modulesBuilder.add(new GuiceEnforcerModule());
}
this.injector = injectorFactory.create(guiceStage, 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 '{}'", name);
- return JerseyGuiceUtils.newServiceLocator(name, parent);
- }
- });
-
dropwizardModule.register(injector);
-
environment
.servlets()
.addFilter("Guice Filter", GuiceFilter.class)
@@ -211,21 +194,4 @@ public final GuiceBundle build() {
);
}
}
-
- 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);
- }
- }
}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/JerseyGuicierModule.java b/src/main/java/com/hubspot/dropwizard/guicier/JerseyGuicierModule.java
index 57bed64..d60793a 100644
--- a/src/main/java/com/hubspot/dropwizard/guicier/JerseyGuicierModule.java
+++ b/src/main/java/com/hubspot/dropwizard/guicier/JerseyGuicierModule.java
@@ -1,49 +1,95 @@
package com.hubspot.dropwizard.guicier;
+import com.google.inject.AbstractModule;
import com.google.inject.Provides;
+import com.google.inject.Scopes;
import com.google.inject.servlet.RequestScoped;
-import com.squarespace.jersey2.guice.JerseyModule;
-import javax.servlet.ServletConfig;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ResourceContext;
-import javax.ws.rs.core.Configuration;
-import org.glassfish.hk2.api.ServiceLocator;
+import com.hubspot.dropwizard.guicier.injection.InjectionManagerProvider;
+import jakarta.servlet.ServletConfig;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ResourceContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.ext.Providers;
+import org.glassfish.jersey.internal.inject.InjectionManager;
import org.glassfish.jersey.server.ExtendedUriInfo;
/**
* This supplements the bindings provided in {@link com.squarespace.jersey2.guice.JerseyGuiceModule}.
*/
-public class JerseyGuicierModule extends JerseyModule {
+public class JerseyGuicierModule extends AbstractModule {
@Override
- protected void configure() {}
+ protected void configure() {
+ bind(InjectionManager.class)
+ .toProvider(InjectionManagerProvider.class)
+ .in(Scopes.NO_SCOPE);
+ }
+
+ @Provides
+ public Application providesApplication(InjectionManager injectionManager) {
+ return injectionManager.getInstance(Application.class);
+ }
+
+ @Provides
+ public Providers providesProviders(InjectionManager injectionManager) {
+ return injectionManager.getInstance(Providers.class);
+ }
+
+ @Provides
+ @RequestScoped
+ public UriInfo providesUriInfo(InjectionManager injectionManager) {
+ return injectionManager.getInstance(UriInfo.class);
+ }
+
+ @Provides
+ @RequestScoped
+ public HttpHeaders providesHttpHeaders(InjectionManager injectionManager) {
+ return injectionManager.getInstance(HttpHeaders.class);
+ }
+
+ @Provides
+ @RequestScoped
+ public SecurityContext providesSecurityContext(InjectionManager injectionManager) {
+ return injectionManager.getInstance(SecurityContext.class);
+ }
+
+ @Provides
+ @RequestScoped
+ public Request providesRequest(InjectionManager injectionManager) {
+ return injectionManager.getInstance(Request.class);
+ }
@Provides
- public Configuration providesConfiguration(ServiceLocator serviceLocator) {
- return serviceLocator.getService(Configuration.class);
+ public Configuration providesConfiguration(InjectionManager injectionManager) {
+ return injectionManager.getInstance(Configuration.class);
}
@Provides
@RequestScoped
public ContainerRequestContext providesContainerRequestContext(
- ServiceLocator serviceLocator
+ InjectionManager injectionManager
) {
- return serviceLocator.getService(ContainerRequestContext.class);
+ return injectionManager.getInstance(ContainerRequestContext.class);
}
@Provides
@RequestScoped
- public ExtendedUriInfo providesExtendedUriInfo(ServiceLocator serviceLocator) {
- return serviceLocator.getService(ExtendedUriInfo.class);
+ public ExtendedUriInfo providesExtendedUriInfo(InjectionManager injectionManager) {
+ return injectionManager.getInstance(ExtendedUriInfo.class);
}
@Provides
- public ResourceContext providesResourceContext(ServiceLocator serviceLocator) {
- return serviceLocator.getService(ResourceContext.class);
+ public ResourceContext providesResourceContext(InjectionManager injectionManager) {
+ return injectionManager.getInstance(ResourceContext.class);
}
@Provides
- public ServletConfig providesServletConfig(ServiceLocator serviceLocator) {
- return serviceLocator.getService(ServletConfig.class);
+ public ServletConfig providesServletConfig(InjectionManager injectionManager) {
+ return injectionManager.getInstance(ServletConfig.class);
}
}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/injection/BindingUtils.java b/src/main/java/com/hubspot/dropwizard/guicier/injection/BindingUtils.java
new file mode 100644
index 0000000..0263ab0
--- /dev/null
+++ b/src/main/java/com/hubspot/dropwizard/guicier/injection/BindingUtils.java
@@ -0,0 +1,248 @@
+package com.hubspot.dropwizard.guicier.injection;
+
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Key;
+import com.google.inject.Provider;
+import com.google.inject.internal.Nullability;
+import jakarta.inject.Qualifier;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+import javax.annotation.Nullable;
+import org.glassfish.hk2.utilities.reflection.ParameterizedTypeImpl;
+import org.glassfish.hk2.utilities.reflection.ReflectionHelper;
+import org.glassfish.jersey.internal.inject.Injectee;
+
+public class BindingUtils {
+
+ public static Optional translateGuiceProviderType(Injectee injectee) {
+ Type requiredType = injectee.getRequiredType();
+ if (requiredType instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) requiredType;
+ if (parameterizedType.getRawType().equals(Provider.class)) {
+ return Optional.of(
+ new ParameterizedTypeImpl(
+ jakarta.inject.Provider.class,
+ parameterizedType.getActualTypeArguments()
+ )
+ );
+ }
+ }
+ return Optional.empty();
+ }
+
+ public static Provider> javaxToGuiceProvider(Object instance) {
+ if (!(instance instanceof jakarta.inject.Provider)) {
+ throw new IllegalArgumentException(
+ "Given instance is not of type jakarta.inject.Provider: " + instance
+ );
+ }
+
+ jakarta.inject.Provider> provider = (jakarta.inject.Provider>) instance;
+ return provider::get;
+ }
+
+ /**
+ * Returns {@code true} if the given {@link Injectee} can be {@code null}.
+ *
+ * @see Optional
+ * @see Injectee#isOptional()
+ * @see Nullable
+ * @see com.google.inject.Inject#optional()
+ * @see Nullability#hasNullableAnnotation(Annotation[])
+ */
+ public static boolean isNullable(Injectee injectee) {
+ // HK2's optional
+ if (injectee.isOptional()) {
+ return true;
+ }
+
+ // Guice's optional
+ AnnotatedElement element = injectee.getParent();
+ if (isGuiceOptional(element)) {
+ return true;
+ }
+
+ // Any @Nullable?
+ int position = injectee.getPosition();
+
+ if (element instanceof Field) {
+ return Nullability.hasNullableAnnotation(((Field) element).getAnnotations());
+ } else if (element instanceof Method) {
+ Annotation annotations[][] = ((Method) element).getParameterAnnotations();
+ return Nullability.hasNullableAnnotation(annotations[position]);
+ } else if (element instanceof Constructor>) {
+ Annotation annotations[][] = ((Constructor>) element).getParameterAnnotations();
+ return Nullability.hasNullableAnnotation(annotations[position]);
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns {@code true} if the given {@link AnnotatedElement} has a
+ * {@link com.google.inject.Inject} {@link Annotation} and it's marked
+ * as being optional.
+ *
+ * @see com.google.inject.Inject#optional()
+ */
+ private static boolean isGuiceOptional(AnnotatedElement element) {
+ com.google.inject.Inject inject = element.getAnnotation(
+ com.google.inject.Inject.class
+ );
+
+ if (inject != null) {
+ return inject.optional();
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns {@code true} if the {@link Injectee} has a HK2 SPI
+ * {@link org.jvnet.hk2.annotations.Contract} annotation.
+ *
+ * @see org.jvnet.hk2.annotations.Contract
+ */
+ public static boolean isHk2Contract(Injectee injectee) {
+ Type type = injectee.getRequiredType();
+ return hasTypeAnnotation(type, org.jvnet.hk2.annotations.Contract.class);
+ }
+
+ /**
+ * Returns {@code true} if the {@link Injectee} has a Jersey SPI
+ * {@link org.glassfish.jersey.spi.Contract} annotation.
+ *
+ * @see org.glassfish.jersey.spi.Contract
+ */
+ public static boolean isJerseyContract(Injectee injectee) {
+ Type type = injectee.getRequiredType();
+ return hasTypeAnnotation(type, org.glassfish.jersey.spi.Contract.class);
+ }
+
+ public static boolean hasTypeAnnotation(
+ Type type,
+ Class extends Annotation> annotationType
+ ) {
+ if (type instanceof Class>) {
+ return ((Class>) type).isAnnotationPresent(annotationType);
+ }
+
+ if (type instanceof ParameterizedType) {
+ Type rawType = ((ParameterizedType) type).getRawType();
+ return hasTypeAnnotation(rawType, annotationType);
+ }
+
+ return false;
+ }
+
+ /**
+ * Creates and returns a {@link Key} from the given {@link Injectee}.
+ */
+ public static Key> toKey(Injectee injectee) {
+ Type type = injectee.getRequiredType();
+ Set qualifiers = getQualifiers(injectee);
+ return newKey(type, qualifiers);
+ }
+
+ /**
+ * Creates and returns a {@link Key} for the given {@link Type} and {@link Set} of {@link Annotation}s.
+ */
+ public static Key> newKey(Type type, Set extends Annotation> qualifiers) {
+ if (qualifiers.isEmpty()) {
+ return Key.get(type);
+ }
+
+ // There can be only one qualifier.
+ if (qualifiers.size() == 1) {
+ for (Annotation first : qualifiers) {
+ return Key.get(type, first);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * NOTE: There can be only one {@link Annotation} that is a {@link Qualifier} or {@link BindingAnnotation}.
+ * They're the same but HK2 does not know about {@link BindingAnnotation}.
+ *
+ * @see Qualifier
+ * @see BindingAnnotation
+ * @see jakarta.inject.Named
+ * @see com.google.inject.name.Named
+ */
+ private static Set getQualifiers(Injectee injectee) {
+ // JSR 330's @Qualifier
+ Set qualifiers = injectee.getRequiredQualifiers();
+ if (!qualifiers.isEmpty()) {
+ return qualifiers;
+ }
+
+ AnnotatedElement element = injectee.getParent();
+ int position = injectee.getPosition();
+
+ // Guice's @BindingAnnotation is the same as @Qualifier
+ Annotation annotation = getBindingAnnotation(element, position);
+ if (annotation != null) {
+ return Collections.singleton(annotation);
+ }
+
+ return Collections.emptySet();
+ }
+
+ /**
+ * Returns a {@link BindingAnnotation} for the given {@link AnnotatedElement} and position.
+ */
+ private static Annotation getBindingAnnotation(AnnotatedElement element, int position) {
+ if (element instanceof Field) {
+ return getBindingAnnotation(((Field) element).getAnnotations());
+ }
+
+ if (element instanceof Method) {
+ Annotation annotations[][] = ((Method) element).getParameterAnnotations();
+ return getBindingAnnotation(annotations[position]);
+ }
+
+ if (element instanceof Constructor>) {
+ Annotation annotations[][] = ((Constructor>) element).getParameterAnnotations();
+ return getBindingAnnotation(annotations[position]);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the first {@link Annotation} from the given array that
+ * is a {@link BindingAnnotation}.
+ *
+ * @see BindingAnnotation
+ */
+ private static Annotation getBindingAnnotation(Annotation[] annotations) {
+ for (Annotation annotation : annotations) {
+ Class extends Annotation> type = annotation.annotationType();
+ if (type.isAnnotationPresent(BindingAnnotation.class)) {
+ return annotation;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @see ReflectionHelper#getNameFromAllQualifiers(Set, AnnotatedElement)
+ */
+ public static String getNameFromAllQualifiers(
+ Set qualifiers,
+ AnnotatedElement element
+ ) {
+ return ReflectionHelper.getNameFromAllQualifiers(qualifiers, element);
+ }
+}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/injection/BridgedGuiceInjectionManager.java b/src/main/java/com/hubspot/dropwizard/guicier/injection/BridgedGuiceInjectionManager.java
new file mode 100644
index 0000000..7f4ff3d
--- /dev/null
+++ b/src/main/java/com/hubspot/dropwizard/guicier/injection/BridgedGuiceInjectionManager.java
@@ -0,0 +1,64 @@
+package com.hubspot.dropwizard.guicier.injection;
+
+import static com.hubspot.dropwizard.guicier.injection.BindingUtils.newKey;
+
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+/**
+ * InjectionManager which gets instances from Guice bindings first, falling back to delegate
+ */
+public class BridgedGuiceInjectionManager extends DelegatingInjectionManager {
+
+ private final Injector guiceInjector;
+
+ public BridgedGuiceInjectionManager(InjectionManager delegate, Injector guiceInjector) {
+ super(delegate);
+ this.guiceInjector = guiceInjector;
+ }
+
+ @Override
+ public T getInstance(Class contractOrImpl, Annotation... qualifiers) {
+ T guiceInstance = getGuiceInstance(newKey(contractOrImpl, Set.of(qualifiers)));
+ return guiceInstance != null
+ ? guiceInstance
+ : super.getInstance(contractOrImpl, qualifiers);
+ }
+
+ @Override
+ public T getInstance(Class contractOrImpl, String classAnalyzer) {
+ T guiceInstance = getGuiceInstance(newKey(contractOrImpl, Set.of()));
+ return guiceInstance != null
+ ? guiceInstance
+ : super.getInstance(contractOrImpl, classAnalyzer);
+ }
+
+ @Override
+ public T getInstance(Class contractOrImpl) {
+ T guiceInstance = getGuiceInstance(newKey(contractOrImpl, Set.of()));
+ return guiceInstance != null ? guiceInstance : super.getInstance(contractOrImpl);
+ }
+
+ @Override
+ public T getInstance(Type contractOrImpl) {
+ T guiceInstance = getGuiceInstance(newKey(contractOrImpl, Set.of()));
+ return guiceInstance != null ? guiceInstance : super.getInstance(contractOrImpl);
+ }
+
+ @SuppressWarnings("unchecked")
+ private T getGuiceInstance(Key> key) {
+ if (guiceInjector.getExistingBinding(key) == null) {
+ return null;
+ }
+
+ T instance = (T) guiceInjector.getInstance(key);
+ if (instance != null) {
+ super.inject(instance);
+ }
+ return instance;
+ }
+}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/injection/BridgedGuiceInjectionManagerFactory.java b/src/main/java/com/hubspot/dropwizard/guicier/injection/BridgedGuiceInjectionManagerFactory.java
new file mode 100644
index 0000000..32043b9
--- /dev/null
+++ b/src/main/java/com/hubspot/dropwizard/guicier/injection/BridgedGuiceInjectionManagerFactory.java
@@ -0,0 +1,68 @@
+package com.hubspot.dropwizard.guicier.injection;
+
+import com.google.inject.Injector;
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.ConstrainedTo;
+import jakarta.ws.rs.RuntimeType;
+import java.util.Optional;
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManagerFactory;
+import org.jvnet.hk2.guice.bridge.api.GuiceBridge;
+import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Priority(15)
+@ConstrainedTo(RuntimeType.SERVER)
+public class BridgedGuiceInjectionManagerFactory implements InjectionManagerFactory {
+
+ private static final Logger LOG = LoggerFactory.getLogger(
+ BridgedGuiceInjectionManagerFactory.class
+ );
+
+ @Override
+ public InjectionManager create(Object parent) {
+ ImmediateHk2InjectionManager injectionManager =
+ (ImmediateHk2InjectionManager) new Hk2InjectionManagerFactory()
+ .create(getHk2Parent(parent));
+
+ Optional guiceInjectorMaybe = InjectorProvider.getMaybe();
+
+ if (guiceInjectorMaybe.isEmpty()) {
+ LOG.warn("No guice injector is set");
+ return injectionManager;
+ }
+
+ Injector guiceInjector = guiceInjectorMaybe.get();
+
+ // initialize HK2 guice-bridge
+ GuiceBridge
+ .getGuiceBridge()
+ .initializeGuiceBridge(injectionManager.getServiceLocator());
+ GuiceIntoHK2Bridge guiceBridge = injectionManager.getInstance(
+ GuiceIntoHK2Bridge.class
+ );
+ guiceBridge.bridgeGuiceInjector(guiceInjector);
+
+ injectionManager.register(
+ Bindings.injectionResolver(
+ new GuiceInjectionResolver(guiceInjector, injectionManager.getServiceLocator())
+ )
+ );
+ injectionManager.register(Bindings.service(guiceInjector).to(Injector.class));
+
+ LOG.debug("Guice Component Provider initialized");
+ return new BridgedGuiceInjectionManager(injectionManager, guiceInjector);
+ }
+
+ private static Object getHk2Parent(Object parent) {
+ if (parent instanceof DelegatingInjectionManager) {
+ DelegatingInjectionManager injectionManager = (DelegatingInjectionManager) parent;
+ return injectionManager.getDelegate();
+ }
+ return parent;
+ }
+}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/injection/DelegatingInjectionManager.java b/src/main/java/com/hubspot/dropwizard/guicier/injection/DelegatingInjectionManager.java
new file mode 100644
index 0000000..28ef85f
--- /dev/null
+++ b/src/main/java/com/hubspot/dropwizard/guicier/injection/DelegatingInjectionManager.java
@@ -0,0 +1,131 @@
+package com.hubspot.dropwizard.guicier.injection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.List;
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.ForeignDescriptor;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+
+public class DelegatingInjectionManager implements InjectionManager {
+
+ private final InjectionManager delegate;
+
+ public DelegatingInjectionManager(InjectionManager delegate) {
+ this.delegate = delegate;
+ }
+
+ public InjectionManager getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ public void completeRegistration() {
+ delegate.completeRegistration();
+ }
+
+ @Override
+ public void shutdown() {
+ delegate.shutdown();
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return delegate.isShutdown();
+ }
+
+ @Override
+ public void register(Binding binding) {
+ delegate.register(binding);
+ }
+
+ @Override
+ public void register(Iterable descriptors) {
+ delegate.register(descriptors);
+ }
+
+ @Override
+ public void register(Binder binder) {
+ delegate.register(binder);
+ }
+
+ @Override
+ public void register(Object provider) throws IllegalArgumentException {
+ delegate.register(provider);
+ }
+
+ @Override
+ public boolean isRegistrable(Class> clazz) {
+ return delegate.isRegistrable(clazz);
+ }
+
+ @Override
+ public T create(Class createMe) {
+ return delegate.create(createMe);
+ }
+
+ @Override
+ public T createAndInitialize(Class createMe) {
+ return delegate.createAndInitialize(createMe);
+ }
+
+ @Override
+ public List> getAllServiceHolders(
+ Class contractOrImpl,
+ Annotation... qualifiers
+ ) {
+ return delegate.getAllServiceHolders(contractOrImpl, qualifiers);
+ }
+
+ @Override
+ public T getInstance(Class contractOrImpl, Annotation... qualifiers) {
+ return delegate.getInstance(contractOrImpl, qualifiers);
+ }
+
+ @Override
+ public T getInstance(Class contractOrImpl, String classAnalyzer) {
+ return delegate.getInstance(contractOrImpl, classAnalyzer);
+ }
+
+ @Override
+ public T getInstance(Class contractOrImpl) {
+ return delegate.getInstance(contractOrImpl);
+ }
+
+ @Override
+ public T getInstance(Type contractOrImpl) {
+ return delegate.getInstance(contractOrImpl);
+ }
+
+ @Override
+ public Object getInstance(ForeignDescriptor foreignDescriptor) {
+ return delegate.getInstance(foreignDescriptor);
+ }
+
+ @Override
+ public ForeignDescriptor createForeignDescriptor(Binding binding) {
+ return delegate.createForeignDescriptor(binding);
+ }
+
+ @Override
+ public List getAllInstances(Type contractOrImpl) {
+ return delegate.getAllInstances(contractOrImpl);
+ }
+
+ @Override
+ public void inject(Object injectMe) {
+ delegate.inject(injectMe);
+ }
+
+ @Override
+ public void inject(Object injectMe, String classAnalyzer) {
+ delegate.inject(injectMe, classAnalyzer);
+ }
+
+ @Override
+ public void preDestroy(Object preDestroyMe) {
+ delegate.preDestroy(preDestroyMe);
+ }
+}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/injection/GuiceInjectionResolver.java b/src/main/java/com/hubspot/dropwizard/guicier/injection/GuiceInjectionResolver.java
new file mode 100644
index 0000000..a248dcc
--- /dev/null
+++ b/src/main/java/com/hubspot/dropwizard/guicier/injection/GuiceInjectionResolver.java
@@ -0,0 +1,77 @@
+package com.hubspot.dropwizard.guicier.injection;
+
+import com.google.inject.ConfigurationException;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import jakarta.inject.Singleton;
+import java.lang.reflect.Type;
+import java.util.Optional;
+import org.glassfish.hk2.api.ServiceLocator;
+import org.glassfish.jersey.internal.inject.Injectee;
+import org.glassfish.jersey.internal.inject.InjectionResolver;
+
+@Singleton
+public class GuiceInjectionResolver implements InjectionResolver {
+
+ private final Injector injector;
+ private final ServiceLocator serviceLocator;
+
+ public GuiceInjectionResolver(Injector injector, ServiceLocator serviceLocator) {
+ this.injector = injector;
+ this.serviceLocator = serviceLocator;
+ }
+
+ @Override
+ public Object resolve(Injectee injectee) {
+ Key> key = BindingUtils.toKey(injectee);
+
+ Object instance = null;
+ try {
+ instance = injector.getInstance(key);
+ } catch (ConfigurationException e) {
+ /* fallback to jersey hk2 injector */
+ }
+
+ if (instance == null) {
+ Optional translatedGuiceProviderType =
+ BindingUtils.translateGuiceProviderType(injectee);
+
+ instance =
+ serviceLocator.getService(
+ translatedGuiceProviderType.orElse(injectee.getRequiredType())
+ );
+
+ if (instance != null && translatedGuiceProviderType.isPresent()) {
+ return BindingUtils.javaxToGuiceProvider(instance);
+ }
+ }
+
+ if (instance == null) {
+ if (BindingUtils.isNullable(injectee)) {
+ return null;
+ }
+
+ throw new RuntimeException(
+ "There was no object available for injection at " + injectee
+ );
+ }
+
+ return instance;
+ }
+
+ @Override
+ public boolean isConstructorParameterIndicator() {
+ return true;
+ }
+
+ @Override
+ public boolean isMethodParameterIndicator() {
+ return false;
+ }
+
+ @Override
+ public Class getAnnotation() {
+ return Inject.class;
+ }
+}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectionManagerProvider.java b/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectionManagerProvider.java
new file mode 100644
index 0000000..09f1b03
--- /dev/null
+++ b/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectionManagerProvider.java
@@ -0,0 +1,38 @@
+package com.hubspot.dropwizard.guicier.injection;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.dropwizard.core.setup.Environment;
+import jakarta.inject.Inject;
+import jakarta.inject.Provider;
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.core.Application;
+import java.util.HashMap;
+import java.util.Map;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+@Singleton
+public class InjectionManagerProvider implements Provider {
+
+ private static final Map INJECTION_MANAGERS_BY_APP =
+ new HashMap<>();
+
+ private final Application application;
+
+ @Inject
+ public InjectionManagerProvider(Environment environment) {
+ this.application = environment.jersey().getResourceConfig();
+ }
+
+ public static void set(Application application, InjectionManager injectionManager) {
+ INJECTION_MANAGERS_BY_APP.put(application, injectionManager);
+ }
+
+ @Override
+ public InjectionManager get() {
+ return checkNotNull(
+ INJECTION_MANAGERS_BY_APP.get(application),
+ "InjectionManager not set"
+ );
+ }
+}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectionManagerProviderFeature.java b/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectionManagerProviderFeature.java
new file mode 100644
index 0000000..1974df3
--- /dev/null
+++ b/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectionManagerProviderFeature.java
@@ -0,0 +1,31 @@
+package com.hubspot.dropwizard.guicier.injection;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Feature;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.ext.Provider;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+/**
+ * This links the active InjectionManager to the Guice InjectionManagerProvider,
+ * to the active jakarta.ws.rs.core.Application, for use in the JerseyGuicierModule.
+ */
+@Provider
+public class InjectionManagerProviderFeature implements Feature {
+
+ private final InjectionManager injectionManager;
+
+ @Inject
+ public InjectionManagerProviderFeature(InjectionManager injectionManager) {
+ this.injectionManager = injectionManager;
+ }
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ Application application = injectionManager.getInstance(Application.class);
+ InjectionManagerProvider.set(application, injectionManager);
+
+ return true;
+ }
+}
diff --git a/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectorProvider.java b/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectorProvider.java
new file mode 100644
index 0000000..c538d82
--- /dev/null
+++ b/src/main/java/com/hubspot/dropwizard/guicier/injection/InjectorProvider.java
@@ -0,0 +1,26 @@
+package com.hubspot.dropwizard.guicier.injection;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.inject.Injector;
+import jakarta.inject.Provider;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class InjectorProvider implements Provider {
+
+ private static final AtomicReference REF = new AtomicReference<>();
+
+ public static void set(Injector injector) {
+ REF.set(injector);
+ }
+
+ public static Optional getMaybe() {
+ return Optional.ofNullable(REF.get());
+ }
+
+ @Override
+ public Injector get() {
+ return checkNotNull(REF.get(), "Guice Injector not set");
+ }
+}
diff --git a/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory b/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory
new file mode 100644
index 0000000..aa50640
--- /dev/null
+++ b/src/main/resources/META-INF/services/org.glassfish.jersey.internal.inject.InjectionManagerFactory
@@ -0,0 +1 @@
+com.hubspot.dropwizard.guicier.injection.BridgedGuiceInjectionManagerFactory
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/GuiceBundleTest.java b/src/test/java/com/hubspot/dropwizard/guicier/GuiceBundleTest.java
index 0b46211..62221b0 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/GuiceBundleTest.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/GuiceBundleTest.java
@@ -2,11 +2,7 @@
import static org.assertj.core.api.Assertions.as;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import com.codahale.metrics.MetricRegistry;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.inject.Injector;
import com.hubspot.dropwizard.guicier.objects.ExplicitResource;
import com.hubspot.dropwizard.guicier.objects.InjectedHealthCheck;
@@ -21,44 +17,37 @@
import com.hubspot.dropwizard.guicier.objects.ProvidedServerLifecycleListener;
import com.hubspot.dropwizard.guicier.objects.ProvidedTask;
import com.hubspot.dropwizard.guicier.objects.ProviderManaged;
-import com.hubspot.dropwizard.guicier.objects.TestModule;
-import com.squarespace.jersey2.guice.JerseyGuiceUtils;
-import io.dropwizard.Configuration;
-import io.dropwizard.jackson.Jackson;
-import io.dropwizard.setup.Bootstrap;
-import io.dropwizard.setup.Environment;
+import com.hubspot.dropwizard.guicier.objects.TestApplication;
+import io.dropwizard.core.Configuration;
+import io.dropwizard.core.setup.Environment;
+import io.dropwizard.testing.ResourceHelpers;
+import io.dropwizard.testing.junit5.DropwizardAppExtension;
+import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
+import jakarta.servlet.ServletException;
import java.util.Set;
-import javax.servlet.ServletException;
import org.assertj.core.api.InstanceOfAssertFactories;
-import org.glassfish.hk2.api.ServiceLocator;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnitRunner;
-
-@RunWith(MockitoJUnitRunner.class)
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(DropwizardExtensionsSupport.class)
public class GuiceBundleTest {
+ private static final DropwizardAppExtension EXT =
+ new DropwizardAppExtension<>(
+ TestApplication.class,
+ ResourceHelpers.resourceFilePath("test-config.yml")
+ );
+
private Environment environment;
private GuiceBundle guiceBundle;
- @After
- public void tearDown() {
- JerseyGuiceUtils.reset();
- }
-
- @Before
- public void setUp() throws Exception {
- ObjectMapper objectMapper = Jackson.newObjectMapper();
- environment =
- new Environment("test env", objectMapper, null, new MetricRegistry(), null);
- guiceBundle =
- GuiceBundle.defaultBuilder(Configuration.class).modules(new TestModule()).build();
- Bootstrap bootstrap = mock(Bootstrap.class);
- when(bootstrap.getObjectMapper()).thenReturn(objectMapper);
- guiceBundle.initialize(bootstrap);
- guiceBundle.run(new Configuration(), environment);
+ @BeforeEach
+ public void setup() {
+ TestApplication testApplication = EXT.getApplication();
+ this.guiceBundle = testApplication.getGuiceBundle();
+ this.environment = EXT.getEnvironment();
}
@Test
@@ -68,11 +57,11 @@ public void createsInjectorWhenInit() throws ServletException {
}
@Test
- public void serviceLocatorIsAvaliable() throws ServletException {
- ServiceLocator serviceLocator = guiceBundle
+ public void serviceLocatorIsAvailable() throws ServletException {
+ InjectionManager injectionManager = guiceBundle
.getInjector()
- .getInstance(ServiceLocator.class);
- assertThat(serviceLocator).isNotNull();
+ .getInstance(InjectionManager.class);
+ assertThat(injectionManager).isNotNull();
}
@Test
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/HK2LinkerTest.java b/src/test/java/com/hubspot/dropwizard/guicier/HK2LinkerTest.java
index a833f46..30989ea 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/HK2LinkerTest.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/HK2LinkerTest.java
@@ -1,63 +1,47 @@
package com.hubspot.dropwizard.guicier;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.*;
-import com.codahale.metrics.MetricRegistry;
-import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.hubspot.dropwizard.guicier.objects.ExplicitResource;
import com.hubspot.dropwizard.guicier.objects.HK2ContextBindings;
-import com.hubspot.dropwizard.guicier.objects.TestModule;
-import com.squarespace.jersey2.guice.JerseyGuiceUtils;
-import io.dropwizard.Configuration;
-import io.dropwizard.jackson.Jackson;
-import io.dropwizard.setup.Bootstrap;
-import io.dropwizard.setup.Environment;
-import javax.servlet.ServletException;
-import org.glassfish.hk2.api.ServiceLocator;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-
+import com.hubspot.dropwizard.guicier.objects.TestApplication;
+import io.dropwizard.core.Configuration;
+import io.dropwizard.testing.ResourceHelpers;
+import io.dropwizard.testing.junit5.DropwizardAppExtension;
+import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
+import jakarta.servlet.ServletException;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(DropwizardExtensionsSupport.class)
public class HK2LinkerTest {
+ private static final DropwizardAppExtension EXT =
+ new DropwizardAppExtension<>(
+ TestApplication.class,
+ ResourceHelpers.resourceFilePath("test-config.yml")
+ );
+
private Injector injector;
- private ServiceLocator serviceLocator;
+ private InjectionManager injectionManager;
- @Before
- public void setup() throws Exception {
- ObjectMapper objectMapper = Jackson.newObjectMapper();
- Environment environment = new Environment(
- "test env",
- objectMapper,
- null,
- new MetricRegistry(),
- null
- );
- GuiceBundle guiceBundle = GuiceBundle
- .defaultBuilder(Configuration.class)
- .modules(new TestModule())
- .build();
- Bootstrap bootstrap = mock(Bootstrap.class);
- when(bootstrap.getObjectMapper()).thenReturn(objectMapper);
- guiceBundle.initialize(bootstrap);
- guiceBundle.run(new Configuration(), environment);
+ @BeforeEach
+ public void setup() {
+ TestApplication testApplication = EXT.getApplication();
+ GuiceBundle guiceBundle = testApplication.getGuiceBundle();
injector = guiceBundle.getInjector();
- serviceLocator = injector.getInstance(ServiceLocator.class);
- }
-
- @AfterClass
- public static void tearDown() {
- JerseyGuiceUtils.reset();
+ injectionManager = injector.getInstance(InjectionManager.class);
}
@Test
public void explicitGuiceBindingsAreBridgedToHk2() throws ServletException {
- ExplicitResource resource = serviceLocator.createAndInitialize(
+ ExplicitResource resource = injectionManager.createAndInitialize(
ExplicitResource.class
);
@@ -68,7 +52,7 @@ public void explicitGuiceBindingsAreBridgedToHk2() throws ServletException {
@Test
public void contextBindingsAreBridgedToGuice() {
for (Class> clazz : HK2ContextBindings.SET) {
- Binding binding = injector.getExistingBinding(Key.get(clazz));
+ Binding> binding = injector.getExistingBinding(Key.get(clazz));
assertThat(binding).as("%s has a Guice binding", clazz.getName()).isNotNull();
}
}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/InjectedIntegrationTest.java b/src/test/java/com/hubspot/dropwizard/guicier/InjectedIntegrationTest.java
index d8bdf9d..1b8ef6e 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/InjectedIntegrationTest.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/InjectedIntegrationTest.java
@@ -2,47 +2,36 @@
import static org.assertj.core.api.Assertions.assertThat;
-import com.google.common.io.Resources;
+import com.hubspot.dropwizard.guicier.objects.ComponentInvocationCounter;
+import com.hubspot.dropwizard.guicier.objects.ContextInjectedFilter;
import com.hubspot.dropwizard.guicier.objects.HK2ContextBindings;
import com.hubspot.dropwizard.guicier.objects.TestApplication;
-import com.squarespace.jersey2.guice.JerseyGuiceUtils;
-import io.dropwizard.Configuration;
-import io.dropwizard.client.JerseyClientBuilder;
-import io.dropwizard.testing.junit.DropwizardAppRule;
-import java.io.File;
-import javax.ws.rs.client.Client;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.ClassRule;
-import org.junit.Test;
+import io.dropwizard.core.Configuration;
+import io.dropwizard.testing.ResourceHelpers;
+import io.dropwizard.testing.junit5.DropwizardAppExtension;
+import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status.Family;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+@ExtendWith(DropwizardExtensionsSupport.class)
public class InjectedIntegrationTest {
- @ClassRule
- public static final DropwizardAppRule RULE = new DropwizardAppRule<>(
- TestApplication.class,
- resourceFilePath("test-config.yml")
- );
+ private static final DropwizardAppExtension EXT =
+ new DropwizardAppExtension<>(
+ TestApplication.class,
+ ResourceHelpers.resourceFilePath("test-config.yml")
+ );
protected static Client client;
- @BeforeClass
+ @BeforeAll
public static void setUp() {
- client = new JerseyClientBuilder(RULE.getEnvironment()).build("test client");
- }
-
- @AfterClass
- public static void tearDown() {
- JerseyGuiceUtils.reset();
- }
-
- public static String resourceFilePath(String resourceClassPathLocation) {
- try {
- return new File(Resources.getResource(resourceClassPathLocation).toURI())
- .getAbsolutePath();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ client = EXT.client();
}
@Test
@@ -54,20 +43,51 @@ public void shouldGetExplicitMessage() {
assertThat(message).isEqualTo("this DAO was bound explicitly");
}
+ @Test
+ public void emptyCtorGoogleInject() {
+ assertThat(
+ client.target(getUri("/empty-ctor-google-inject")).request().get(String.class)
+ )
+ .isEqualTo("world");
+ }
+
+ @Test
+ public void testContextInjectedFilter() {
+ Response response = client.target(getUri("/explicit/message")).request().get();
+ assertThat(response.getStatusInfo().getFamily()).isEqualTo(Family.SUCCESSFUL);
+ assertThat(response.getHeaderString(ContextInjectedFilter.RESPONSE_HEADER))
+ .isEqualTo("true");
+
+ TestApplication app = EXT.getApplication();
+ ComponentInvocationCounter counter = app
+ .getGuiceBundle()
+ .getInjector()
+ .getInstance(ComponentInvocationCounter.class);
+ assertThat(counter.count("ContextInjectedFilter")).isGreaterThanOrEqualTo(1);
+ }
+
@Test
public void hk2ContextBindingsAreResolvableInGuice() {
- for (Class> clazz : HK2ContextBindings.SET) {
- boolean resolvable = client
- .target(getUri("/jersey-context/is-resolvable-by-guice"))
- .queryParam("className", clazz.getName())
- .request()
- .get(Boolean.class);
- assertThat(resolvable).as("%s is resolvable by Guice", clazz.getName()).isTrue();
- }
+ Assertions.assertAll(
+ HK2ContextBindings.SET
+ .stream()
+ .map(clazz ->
+ () -> {
+ boolean resolvable = client
+ .target(getUri("/jersey-context/is-resolvable-by-guice"))
+ .queryParam("className", clazz.getName())
+ .request()
+ .get(Boolean.class);
+ assertThat(resolvable)
+ .as("%s is resolvable by Guice", clazz.getName())
+ .isTrue();
+ }
+ )
+ );
}
private static String getUri(String path) {
- String domain = "http://localhost:" + RULE.getLocalPort();
+ String domain = "http://localhost:" + EXT.getLocalPort();
return domain + (path.startsWith("/") ? "" : "/") + path;
}
}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/InjectedResourcesTest.java b/src/test/java/com/hubspot/dropwizard/guicier/InjectedResourcesTest.java
index d987d2a..e5ed093 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/InjectedResourcesTest.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/InjectedResourcesTest.java
@@ -4,22 +4,19 @@
import com.hubspot.dropwizard.guicier.objects.ExplicitDAO;
import com.hubspot.dropwizard.guicier.objects.ExplicitResource;
-import com.squarespace.jersey2.guice.JerseyGuiceUtils;
-import io.dropwizard.testing.junit.ResourceTestRule;
-import org.junit.ClassRule;
-import org.junit.Test;
+import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
+import io.dropwizard.testing.junit5.ResourceExtension;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
/**
* this test is created to address to Null Pointer Exceptions in JerseyTest.teardown() related to ServiceLocator
* See: https://github.com/dropwizard/dropwizard/issues/828 and http://permalink.gmane.org/gmane.comp.java.dropwizard.devel/376
*/
+@ExtendWith(DropwizardExtensionsSupport.class)
public class InjectedResourcesTest {
- static {
- JerseyGuiceUtils.reset();
- }
- @ClassRule
- public static final ResourceTestRule resources = ResourceTestRule
+ private static final ResourceExtension EXT = ResourceExtension
.builder()
.addResource(new ExplicitResource(new ExplicitDAO()))
.build();
@@ -27,11 +24,7 @@ public class InjectedResourcesTest {
@Test
public void shouldGetExplicitMessage() {
// when
- String message = resources
- .client()
- .target("/explicit/message")
- .request()
- .get(String.class);
+ String message = EXT.client().target("/explicit/message").request().get(String.class);
// then
assertThat(message).isEqualTo("this DAO was bound explicitly");
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/StashesTest.java b/src/test/java/com/hubspot/dropwizard/guicier/StashesTest.java
new file mode 100644
index 0000000..8997a9a
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/StashesTest.java
@@ -0,0 +1,80 @@
+package com.hubspot.dropwizard.guicier;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.hubspot.dropwizard.guicier.objects.StashesTestModule;
+import com.hubspot.dropwizard.guicier.objects.TestApplication;
+import io.dropwizard.core.Configuration;
+import io.dropwizard.testing.ResourceHelpers;
+import io.dropwizard.testing.junit5.DropwizardAppExtension;
+import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
+import jakarta.ws.rs.client.Client;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(DropwizardExtensionsSupport.class)
+public class StashesTest {
+
+ private static final DropwizardAppExtension EXT =
+ new DropwizardAppExtension<>(
+ TestApplication.class,
+ ResourceHelpers.resourceFilePath("test-config.yml")
+ );
+
+ private Client client;
+
+ @BeforeEach
+ public void setup() {
+ this.client = EXT.client();
+ }
+
+ private int doGet(String path) {
+ return client
+ .target("http://localhost:" + EXT.getLocalPort() + "/stashes/" + path)
+ .request()
+ .get(int.class);
+ }
+
+ @Test
+ public void itConstructorInjectsAStashedInt() {
+ assertThat(doGet("itConstructorInjectsAStashedInt"))
+ .isEqualTo(StashesTestModule.STASHED_INT_VALUE);
+ }
+
+ @Test
+ public void itConstructorInjectsAStashedIntGuiceProvider() {
+ assertThat(doGet("itConstructorInjectsAStashedIntGuiceProvider"))
+ .isEqualTo(StashesTestModule.STASHED_INT_VALUE);
+ }
+
+ @Test
+ public void itConstructorInjectsAStashedIntJavaxProvider() {
+ assertThat(doGet("itConstructorInjectsAStashedIntJavaxProvider"))
+ .isEqualTo(StashesTestModule.STASHED_INT_VALUE);
+ }
+
+ @Test
+ public void itFieldInjectsAStashedInt() {
+ assertThat(doGet("itFieldInjectsAStashedInt"))
+ .isEqualTo(StashesTestModule.STASHED_INT_VALUE);
+ }
+
+ @Test
+ public void itFieldInjectsAStashedIntGuiceProvider() {
+ assertThat(doGet("itFieldInjectsAStashedIntGuiceProvider"))
+ .isEqualTo(StashesTestModule.STASHED_INT_VALUE);
+ }
+
+ @Test
+ public void itFieldInjectsAStashedIntJavaxProvider() {
+ assertThat(doGet("itFieldInjectsAStashedIntJavaxProvider"))
+ .isEqualTo(StashesTestModule.STASHED_INT_VALUE);
+ }
+
+ @Test
+ public void itMethodInjectsAStashedInt() {
+ assertThat(doGet("itMethodInjectsAStashedInt"))
+ .isEqualTo(StashesTestModule.STASHED_INT_VALUE);
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/aop/AopTest.java b/src/test/java/com/hubspot/dropwizard/guicier/aop/AopTest.java
new file mode 100644
index 0000000..a0e19df
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/aop/AopTest.java
@@ -0,0 +1,42 @@
+package com.hubspot.dropwizard.guicier.aop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.dropwizard.core.Configuration;
+import io.dropwizard.testing.ResourceHelpers;
+import io.dropwizard.testing.junit5.DropwizardAppExtension;
+import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
+import jakarta.ws.rs.client.Client;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(DropwizardExtensionsSupport.class)
+public class AopTest {
+
+ private static final DropwizardAppExtension EXT =
+ new DropwizardAppExtension<>(
+ AopTestApplication.class,
+ ResourceHelpers.resourceFilePath("test-config.yml")
+ );
+
+ protected static Client client;
+ protected static AopTestApplication app;
+
+ @BeforeAll
+ public static void setUp() {
+ client = EXT.client();
+ }
+
+ @Test
+ public void itInterceptsMethod() {
+ String response = client
+ .target("http://localhost:" + EXT.getLocalPort() + MyResource.PATH)
+ .request()
+ .get(String.class);
+ assertThat(response).isEqualTo(MyResource.RESPONSE);
+
+ AopTestApplication app = EXT.getApplication();
+ assertThat(app.getInterceptor().counter.get()).isEqualTo(1);
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/aop/AopTestApplication.java b/src/test/java/com/hubspot/dropwizard/guicier/aop/AopTestApplication.java
new file mode 100644
index 0000000..acd5375
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/aop/AopTestApplication.java
@@ -0,0 +1,45 @@
+package com.hubspot.dropwizard.guicier.aop;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.matcher.Matchers;
+import com.hubspot.dropwizard.guicier.GuiceBundle;
+import io.dropwizard.core.Application;
+import io.dropwizard.core.Configuration;
+import io.dropwizard.core.setup.Bootstrap;
+import io.dropwizard.core.setup.Environment;
+
+public class AopTestApplication extends Application {
+
+ private MyInterceptor interceptor = new MyInterceptor();
+
+ public MyInterceptor getInterceptor() {
+ return interceptor;
+ }
+
+ @Override
+ public void initialize(Bootstrap bootstrap) {
+ bootstrap.addBundle(
+ GuiceBundle
+ .defaultBuilder(Configuration.class)
+ .modules(
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(MyResource.class);
+
+ bindInterceptor(
+ Matchers.any(),
+ Matchers.annotatedWith(MyAnnotation.class),
+ interceptor
+ );
+ }
+ }
+ )
+ .build()
+ );
+ }
+
+ @Override
+ public void run(Configuration configuration, Environment environment)
+ throws Exception {}
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/aop/MyAnnotation.java b/src/test/java/com/hubspot/dropwizard/guicier/aop/MyAnnotation.java
new file mode 100644
index 0000000..9dfcb8a
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/aop/MyAnnotation.java
@@ -0,0 +1,12 @@
+package com.hubspot.dropwizard.guicier.aop;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target(METHOD)
+@Retention(RUNTIME)
+public @interface MyAnnotation {
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/aop/MyInterceptor.java b/src/test/java/com/hubspot/dropwizard/guicier/aop/MyInterceptor.java
new file mode 100644
index 0000000..d140420
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/aop/MyInterceptor.java
@@ -0,0 +1,16 @@
+package com.hubspot.dropwizard.guicier.aop;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+class MyInterceptor implements MethodInterceptor {
+
+ public final AtomicInteger counter = new AtomicInteger();
+
+ @Override
+ public Object invoke(MethodInvocation invocation) throws Throwable {
+ counter.incrementAndGet();
+ return invocation.proceed();
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/aop/MyResource.java b/src/test/java/com/hubspot/dropwizard/guicier/aop/MyResource.java
new file mode 100644
index 0000000..ef99d8e
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/aop/MyResource.java
@@ -0,0 +1,25 @@
+package com.hubspot.dropwizard.guicier.aop;
+
+import com.google.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+@Path(MyResource.PATH)
+public class MyResource {
+
+ public static final String PATH = "/aop-rsrc";
+
+ public static final String RESPONSE = "Hello, World!";
+
+ @Inject
+ public MyResource() {}
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ @MyAnnotation
+ public String sayHello() {
+ return RESPONSE;
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/ComponentInvocationCounter.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/ComponentInvocationCounter.java
new file mode 100644
index 0000000..7d0cc1f
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/ComponentInvocationCounter.java
@@ -0,0 +1,23 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import com.google.common.collect.LinkedHashMultiset;
+import com.google.common.collect.Multiset;
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+
+@Singleton
+public class ComponentInvocationCounter {
+
+ private final Multiset invocations = LinkedHashMultiset.create();
+
+ @Inject
+ public ComponentInvocationCounter() {}
+
+ public void inc(String name) {
+ invocations.add(name);
+ }
+
+ public int count(String name) {
+ return invocations.count(name);
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/ContextInjectedFilter.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/ContextInjectedFilter.java
new file mode 100644
index 0000000..e5c9262
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/ContextInjectedFilter.java
@@ -0,0 +1,39 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerResponseContext;
+import jakarta.ws.rs.container.ContainerResponseFilter;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.ext.Provider;
+import java.io.IOException;
+import org.glassfish.jersey.server.ExtendedUriInfo;
+
+@Provider
+public class ContextInjectedFilter implements ContainerResponseFilter {
+
+ public static final String RESPONSE_HEADER = "x-context-injected-filter";
+
+ private final ComponentInvocationCounter counter;
+
+ @Context
+ private ExtendedUriInfo extendedUriInfo;
+
+ @Inject
+ public ContextInjectedFilter(ComponentInvocationCounter counter) {
+ this.counter = counter;
+ }
+
+ @Override
+ public void filter(
+ ContainerRequestContext requestContext,
+ ContainerResponseContext responseContext
+ ) throws IOException {
+ checkNotNull(extendedUriInfo, "@Context injected ExtendedUriInfo null");
+
+ counter.inc(getClass().getSimpleName());
+ responseContext.getHeaders().putSingle(RESPONSE_HEADER, "true");
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/EmptyCtorGoogleInjectResource.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/EmptyCtorGoogleInjectResource.java
new file mode 100644
index 0000000..8d3e724
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/EmptyCtorGoogleInjectResource.java
@@ -0,0 +1,21 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+
+import com.google.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+
+@Path("/empty-ctor-google-inject")
+@Produces(APPLICATION_JSON)
+public class EmptyCtorGoogleInjectResource {
+
+ @Inject
+ public EmptyCtorGoogleInjectResource() {}
+
+ @GET
+ public String hello() {
+ return "world";
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/ExplicitResource.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/ExplicitResource.java
index b4f0790..4796dae 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/ExplicitResource.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/ExplicitResource.java
@@ -1,11 +1,11 @@
package com.hubspot.dropwizard.guicier.objects;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import com.google.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
@Path("/explicit")
@Produces(APPLICATION_JSON)
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/HK2ContextBindings.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/HK2ContextBindings.java
index 4b74a79..29c3de8 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/HK2ContextBindings.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/HK2ContextBindings.java
@@ -1,19 +1,19 @@
package com.hubspot.dropwizard.guicier.objects;
import com.google.common.collect.ImmutableSet;
+import jakarta.servlet.ServletConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ResourceContext;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Request;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
+import jakarta.ws.rs.ext.Providers;
import java.util.Set;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ResourceContext;
-import javax.ws.rs.core.Application;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Request;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.core.UriInfo;
-import javax.ws.rs.ext.Providers;
import org.glassfish.jersey.server.ExtendedUriInfo;
public class HK2ContextBindings {
@@ -21,7 +21,7 @@ public class HK2ContextBindings {
// This list comes from https://stackoverflow.com/a/35868654
public static final Set> SET = ImmutableSet.of(
Application.class,
- javax.ws.rs.core.Configuration.class,
+ jakarta.ws.rs.core.Configuration.class,
ContainerRequestContext.class,
HttpHeaders.class,
HttpServletRequest.class,
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/InjectedProvider.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/InjectedProvider.java
index 09a329d..b4a4f41 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/InjectedProvider.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/InjectedProvider.java
@@ -1,7 +1,7 @@
package com.hubspot.dropwizard.guicier.objects;
import com.google.inject.Inject;
-import javax.ws.rs.ext.Provider;
+import jakarta.ws.rs.ext.Provider;
@Provider
public class InjectedProvider {
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/InjectedTask.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/InjectedTask.java
index 2b6efc5..ba54598 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/InjectedTask.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/InjectedTask.java
@@ -1,11 +1,12 @@
package com.hubspot.dropwizard.guicier.objects;
-import com.google.common.collect.ImmutableMultimap;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import io.dropwizard.servlets.tasks.Task;
import java.io.PrintWriter;
+import java.util.List;
+import java.util.Map;
@Singleton
public class InjectedTask extends Task {
@@ -16,8 +17,6 @@ protected InjectedTask(@Named("TestTaskName") String name) {
}
@Override
- public void execute(
- ImmutableMultimap immutableMultimap,
- PrintWriter printWriter
- ) throws Exception {}
+ public void execute(Map> parameters, PrintWriter output)
+ throws Exception {}
}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/JerseyContextResource.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/JerseyContextResource.java
index 7fcd5d0..3939bbd 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/JerseyContextResource.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/JerseyContextResource.java
@@ -1,14 +1,14 @@
package com.hubspot.dropwizard.guicier.objects;
-import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
import com.google.inject.ConfigurationException;
import com.google.inject.Inject;
import com.google.inject.Injector;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
@Path("/jersey-context")
@Produces(APPLICATION_JSON)
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/ProvidedProvider.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/ProvidedProvider.java
index 999cff4..3695ec7 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/ProvidedProvider.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/ProvidedProvider.java
@@ -1,6 +1,6 @@
package com.hubspot.dropwizard.guicier.objects;
-import javax.ws.rs.ext.Provider;
+import jakarta.ws.rs.ext.Provider;
@Provider
public class ProvidedProvider {}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/ProvidedTask.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/ProvidedTask.java
index 475af70..446b128 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/ProvidedTask.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/ProvidedTask.java
@@ -1,8 +1,9 @@
package com.hubspot.dropwizard.guicier.objects;
-import com.google.common.collect.ImmutableMultimap;
import io.dropwizard.servlets.tasks.Task;
import java.io.PrintWriter;
+import java.util.List;
+import java.util.Map;
public class ProvidedTask extends Task {
@@ -11,8 +12,6 @@ public ProvidedTask(String name) {
}
@Override
- public void execute(
- ImmutableMultimap immutableMultimap,
- PrintWriter printWriter
- ) {}
+ public void execute(Map> parameters, PrintWriter output)
+ throws Exception {}
}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/ProviderManagedProvider.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/ProviderManagedProvider.java
index 53dafd8..ff552ed 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/ProviderManagedProvider.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/ProviderManagedProvider.java
@@ -1,7 +1,7 @@
package com.hubspot.dropwizard.guicier.objects;
-import javax.inject.Inject;
-import javax.inject.Provider;
+import jakarta.inject.Inject;
+import jakarta.inject.Provider;
public class ProviderManagedProvider implements Provider {
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/Stashed.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/Stashed.java
new file mode 100644
index 0000000..56f521b
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/Stashed.java
@@ -0,0 +1,15 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import com.google.inject.BindingAnnotation;
+import jakarta.inject.Qualifier;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Qualifier
+@BindingAnnotation
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Stashed {
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/StashedValueFactoryProvider.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/StashedValueFactoryProvider.java
new file mode 100644
index 0000000..2917bb0
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/StashedValueFactoryProvider.java
@@ -0,0 +1,35 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import jakarta.inject.Inject;
+import jakarta.inject.Provider;
+import java.util.function.Function;
+import org.glassfish.jersey.model.Parameter.Source;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.internal.inject.AbstractValueParamProvider;
+import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
+import org.glassfish.jersey.server.model.Parameter;
+
+public class StashedValueFactoryProvider extends AbstractValueParamProvider {
+
+ private final Injector injector;
+
+ @Inject
+ public StashedValueFactoryProvider(
+ Provider extractorProviderProvider,
+ Injector injector
+ ) {
+ super(extractorProviderProvider, Source.UNKNOWN);
+ this.injector = injector;
+ }
+
+ @Override
+ protected Function createValueProvider(Parameter parameter) {
+ if (!parameter.isAnnotationPresent(Stashed.class)) {
+ return null;
+ }
+
+ return request -> injector.getInstance(Key.get(parameter.getType(), Stashed.class));
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/StashedValueFeature.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/StashedValueFeature.java
new file mode 100644
index 0000000..de2de9b
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/StashedValueFeature.java
@@ -0,0 +1,31 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.core.Feature;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.ext.Provider;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
+
+@Provider
+public class StashedValueFeature implements Feature {
+
+ @Inject
+ StashedValueFeature() {}
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(
+ new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(StashedValueFactoryProvider.class)
+ .to(ValueParamProvider.class)
+ .in(Singleton.class);
+ }
+ }
+ );
+ return true;
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/StashesTestModule.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/StashesTestModule.java
new file mode 100644
index 0000000..e776be9
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/StashesTestModule.java
@@ -0,0 +1,21 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import com.google.inject.Binder;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+
+public class StashesTestModule implements Module {
+
+ public static final int STASHED_INT_VALUE = 42;
+
+ @Override
+ public void configure(Binder binder) {
+ binder.bind(StashesTestResource.class);
+ }
+
+ @Stashed
+ @Provides
+ public int providesStashedInt() {
+ return STASHED_INT_VALUE;
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/StashesTestResource.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/StashesTestResource.java
new file mode 100644
index 0000000..16112ee
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/StashesTestResource.java
@@ -0,0 +1,82 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON;
+
+import com.google.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+
+@Path("/stashes")
+@Produces(APPLICATION_JSON)
+public class StashesTestResource {
+
+ private final int stashedIntCtor;
+ private final com.google.inject.Provider stashedIntGuiceProviderCtor;
+ private final jakarta.inject.Provider stashedIntJavaxProviderCtor;
+
+ @Inject
+ @Stashed
+ private int stashedIntField;
+
+ @Inject
+ @Stashed
+ private com.google.inject.Provider stashedIntGuiceProviderField;
+
+ @Inject
+ @Stashed
+ private jakarta.inject.Provider stashedIntJavaxProviderField;
+
+ @Inject
+ public StashesTestResource(
+ @Stashed int stashedIntCtor,
+ @Stashed com.google.inject.Provider stashedIntGuiceProviderCtor,
+ @Stashed jakarta.inject.Provider stashedIntJavaxProviderCtor
+ ) {
+ this.stashedIntCtor = stashedIntCtor;
+ this.stashedIntGuiceProviderCtor = stashedIntGuiceProviderCtor;
+ this.stashedIntJavaxProviderCtor = stashedIntJavaxProviderCtor;
+ }
+
+ @GET
+ @Path("/itConstructorInjectsAStashedInt")
+ public int itConstructorInjectsAStashedInt() {
+ return stashedIntCtor;
+ }
+
+ @GET
+ @Path("/itConstructorInjectsAStashedIntGuiceProvider")
+ public Integer itConstructorInjectsAStashedIntGuiceProvider() {
+ return stashedIntGuiceProviderCtor.get();
+ }
+
+ @GET
+ @Path("/itConstructorInjectsAStashedIntJavaxProvider")
+ public Integer itConstructorInjectsAStashedIntJavaxProvider() {
+ return stashedIntJavaxProviderCtor.get();
+ }
+
+ @GET
+ @Path("/itFieldInjectsAStashedInt")
+ public int itFieldInjectsAStashedInt() {
+ return stashedIntField;
+ }
+
+ @GET
+ @Path("/itFieldInjectsAStashedIntGuiceProvider")
+ public Integer itFieldInjectsAStashedIntGuiceProvider() {
+ return stashedIntGuiceProviderField.get();
+ }
+
+ @GET
+ @Path("/itFieldInjectsAStashedIntJavaxProvider")
+ public Integer itFieldInjectsAStashedIntJavaxProvider() {
+ return stashedIntJavaxProviderField.get();
+ }
+
+ @GET
+ @Path("/itMethodInjectsAStashedInt")
+ public int itMethodInjectsAStashedInt(@Stashed int stashedInt) {
+ return stashedInt;
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/TestApplication.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestApplication.java
index cc91062..c9d1722 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/TestApplication.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestApplication.java
@@ -1,20 +1,24 @@
package com.hubspot.dropwizard.guicier.objects;
import com.hubspot.dropwizard.guicier.GuiceBundle;
-import io.dropwizard.Application;
-import io.dropwizard.Configuration;
-import io.dropwizard.setup.Bootstrap;
-import io.dropwizard.setup.Environment;
+import io.dropwizard.core.Application;
+import io.dropwizard.core.Configuration;
+import io.dropwizard.core.setup.Bootstrap;
+import io.dropwizard.core.setup.Environment;
public class TestApplication extends Application {
+ private GuiceBundle guiceBundle;
+
+ public GuiceBundle getGuiceBundle() {
+ return guiceBundle;
+ }
+
@Override
public void initialize(final Bootstrap bootstrap) {
- final GuiceBundle jersey2GuiceBundle = GuiceBundle
- .defaultBuilder(Configuration.class)
- .modules(new TestModule())
- .build();
- bootstrap.addBundle(jersey2GuiceBundle);
+ this.guiceBundle =
+ GuiceBundle.defaultBuilder(Configuration.class).modules(new TestModule()).build();
+ bootstrap.addBundle(guiceBundle);
}
@Override
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/TestModule.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestModule.java
index fc1f43c..dd1f965 100644
--- a/src/test/java/com/hubspot/dropwizard/guicier/objects/TestModule.java
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestModule.java
@@ -5,7 +5,7 @@
import com.google.inject.Scopes;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
-import javax.inject.Singleton;
+import jakarta.inject.Singleton;
public class TestModule extends AbstractModule {
@@ -29,6 +29,16 @@ protected void configure() {
bind(ExplicitResource.class);
bind(JerseyContextResource.class);
+
+ bind(TestValueParamFeature.class);
+
+ bind(StashedValueFeature.class);
+ install(new StashesTestModule());
+
+ bind(EmptyCtorGoogleInjectResource.class);
+
+ bind(ComponentInvocationCounter.class);
+ bind(ContextInjectedFilter.class);
}
@Provides
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParam.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParam.java
new file mode 100644
index 0000000..e90085d
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParam.java
@@ -0,0 +1,11 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface TestValueParam {
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParamFeature.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParamFeature.java
new file mode 100644
index 0000000..4b4d790
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParamFeature.java
@@ -0,0 +1,31 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import jakarta.ws.rs.core.Feature;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.ext.Provider;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.spi.internal.ValueParamProvider;
+
+@Provider
+public class TestValueParamFeature implements Feature {
+
+ @Inject
+ public TestValueParamFeature() {}
+
+ @Override
+ public boolean configure(FeatureContext context) {
+ context.register(
+ new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(TestValueParamProvider.class)
+ .to(ValueParamProvider.class)
+ .in(Singleton.class);
+ }
+ }
+ );
+ return true;
+ }
+}
diff --git a/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParamProvider.java b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParamProvider.java
new file mode 100644
index 0000000..c7cbd2d
--- /dev/null
+++ b/src/test/java/com/hubspot/dropwizard/guicier/objects/TestValueParamProvider.java
@@ -0,0 +1,29 @@
+package com.hubspot.dropwizard.guicier.objects;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import java.util.function.Function;
+import org.glassfish.jersey.model.Parameter.Source;
+import org.glassfish.jersey.server.ContainerRequest;
+import org.glassfish.jersey.server.internal.inject.AbstractValueParamProvider;
+import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
+import org.glassfish.jersey.server.model.Parameter;
+
+public class TestValueParamProvider extends AbstractValueParamProvider {
+
+ @Inject
+ TestValueParamProvider(
+ Provider extractorProvider
+ ) {
+ super(extractorProvider, Source.UNKNOWN);
+ }
+
+ @Override
+ protected Function createValueProvider(Parameter parameter) {
+ if (!parameter.isAnnotationPresent(TestValueParam.class)) {
+ return null;
+ }
+
+ return request -> "testparam";
+ }
+}
diff --git a/src/test/resources/test-config.yml b/src/test/resources/test-config.yml
index 001fe6f..de6facc 100644
--- a/src/test/resources/test-config.yml
+++ b/src/test/resources/test-config.yml
@@ -4,7 +4,7 @@ server:
adminContextPath: /admin
connector:
type: http
- port: 9999
+ port: 0
# default logging relies on logback JMXConfigurator
# which no longer exists