Enable to use @Context in constructors of classes instantiated by CDI
Signed-off-by: jansupol <jan.supol@oracle.com>
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.java
index 10e3e45..36fc610 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -110,6 +110,17 @@
boolean isRegistrable(Class<?> clazz);
/**
+ * Creates an object with the given class.
+ * <p>
+ * The object created is not managed by the injection manager.
+ *
+ * @param createMe The non-null class to create this object from;
+ * @return An instance of the object that has been created.
+ * @since 2.35
+ */
+ <T> T create(Class<T> createMe);
+
+ /**
* Creates, injects and post-constructs an object with the given class. This is equivalent to calling the
* {@code create-class} method followed by the {@code inject-class} method followed by the {@code post-construct} method.
* <p>
diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java
index 5bea827..b681a2c 100644
--- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java
+++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java
@@ -85,7 +85,7 @@
@Override
public T getInstance(final Class<T> clazz) {
final CreationalContext<T> creationalContext = beanManager.createCreationalContext(null);
- final T instance = injectionTarget.produce(creationalContext);
+ final T instance = produce(injectionTarget, creationalContext, injectionManager, clazz);
final CdiComponentProvider cdiComponentProvider = beanManager.getExtension(CdiComponentProvider.class);
final CdiComponentProvider.InjectionManagerInjectedCdiTarget hk2managedTarget =
cdiComponentProvider.new InjectionManagerInjectedCdiTarget(injectionTarget) {
@@ -107,6 +107,18 @@
};
}
+ /*
+ * Let CDI produce the InjectionTarget. If the constructor contains @Context Args CDI won't be able to produce it.
+ * Let the HK2 try to produce the target then.
+ */
+ private static <T> T produce(InjectionTarget<T> target, CreationalContext<T> ctx, InjectionManager im, Class<T> clazz) {
+ try {
+ return target.produce(ctx);
+ } catch (Exception e) {
+ return im.create(clazz);
+ }
+ }
+
@SuppressWarnings(value = "unchecked")
/* package */ T _provide() {
final T instance = referenceProvider.getInstance(clazz);
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManager.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManager.java
index 7d1e88d..3096490 100644
--- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManager.java
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -116,6 +116,23 @@
}
@Override
+ public <T> T create(Class<T> createMe) {
+ if (isInitialized()) {
+ Unmanaged.UnmanagedInstance<T> unmanaged = new Unmanaged<>(createMe).newInstance();
+ return unmanaged.produce().get();
+ } else {
+ // TODO: method is invoked before #completeRegistration - creates AutoDiscoverable, ForcedAutoDiscoverable.
+ // Hack: creates an object with default constructor and without an injection.
+ try {
+ Constructor<T> constructor = createMe.getConstructor();
+ return constructor.newInstance();
+ } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
+ throw new RuntimeException("Cannot create an instance of a class: " + createMe, e);
+ }
+ }
+ }
+
+ @Override
@SuppressWarnings("unchecked")
public <T> List<ServiceHolder<T>> getAllServiceHolders(Class<T> contractOrImpl, Annotation... qualifiers) {
List<ServiceHolder<T>> result = new ArrayList<>();
diff --git a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/AbstractHk2InjectionManager.java b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/AbstractHk2InjectionManager.java
index 543f662..5a71084 100644
--- a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/AbstractHk2InjectionManager.java
+++ b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/AbstractHk2InjectionManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -185,6 +185,11 @@
}
@Override
+ public <U> U create(Class<U> clazz) {
+ return getServiceLocator().create(clazz);
+ }
+
+ @Override
public <U> U createAndInitialize(Class<U> clazz) {
return getServiceLocator().createAndInitialize(clazz);
}
diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml
new file mode 100644
index 0000000..aaf101f
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
+ <artifactId>cdi-integration-project</artifactId>
+ <version>2.35-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>cdi-resource-with-at-context</artifactId>
+
+ <name>jersey-tests-resource-with-at-context</name>
+
+ <description>CDI works for a resource class with constructor with @Context</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>jakarta.ws.rs</groupId>
+ <artifactId>jakarta.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.annotation</groupId>
+ <artifactId>jakarta.annotation-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.enterprise</groupId>
+ <artifactId>cdi-api</artifactId>
+ <version>2.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>jakarta.servlet</groupId>
+ <artifactId>jakarta.servlet-api</artifactId>
+ <version>${servlet4.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-weld2-se</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.weld.se</groupId>
+ <artifactId>weld-se-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi1x</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.ext.cdi</groupId>
+ <artifactId>jersey-cdi-rs-inject</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet-core</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/java/org/glassfish/jersey/tests/cdi/resourceatcontext/App.java b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/java/org/glassfish/jersey/tests/cdi/resourceatcontext/App.java
new file mode 100644
index 0000000..c93cc61
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/java/org/glassfish/jersey/tests/cdi/resourceatcontext/App.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package org.glassfish.jersey.tests.cdi.resourceatcontext;
+
+import org.glassfish.jersey.server.ResourceConfig;
+
+public class App extends ResourceConfig {
+ public App() {
+ register(ResourceWithConstructor.class);
+ }
+}
diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/java/org/glassfish/jersey/tests/cdi/resourceatcontext/ResourceWithConstructor.java b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/java/org/glassfish/jersey/tests/cdi/resourceatcontext/ResourceWithConstructor.java
new file mode 100644
index 0000000..609b998
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/java/org/glassfish/jersey/tests/cdi/resourceatcontext/ResourceWithConstructor.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package org.glassfish.jersey.tests.cdi.resourceatcontext;
+
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+
+@Path("/")
+public class ResourceWithConstructor {
+ HttpHeaders headers;
+
+ @Inject
+ BeanManager beanManager;
+
+ public ResourceWithConstructor(@Context HttpHeaders headers) {
+ this.headers = headers;
+ }
+
+ @GET
+ @Path("get")
+ public String get() {
+ return headers != null && beanManager != null ? "OK" : "NOK";
+ }
+}
diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..9ad6922
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v. 2.0, which is available at
+ http://www.eclipse.org/legal/epl-2.0.
+
+ This Source Code may also be made available under the following Secondary
+ Licenses when the conditions for such availability set forth in the
+ Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ version 2 with the GNU Classpath Exception, which is available at
+ https://www.gnu.org/software/classpath/license.html.
+
+ SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+
+-->
+
+<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+ http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
+ bean-discovery-mode="none">
+</beans>
diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/src/test/java/org/glassfish/jersey/tests/cdi/resourceatcontext/ResourceWithConstructorTest.java b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/test/java/org/glassfish/jersey/tests/cdi/resourceatcontext/ResourceWithConstructorTest.java
new file mode 100644
index 0000000..ace3e0b
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/test/java/org/glassfish/jersey/tests/cdi/resourceatcontext/ResourceWithConstructorTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.cdi.resourceatcontext;
+
+import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.test.DeploymentContext;
+import org.glassfish.jersey.test.JerseyTest;
+import org.glassfish.jersey.test.ServletDeploymentContext;
+import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.jboss.weld.environment.se.Weld;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Response;
+
+public class ResourceWithConstructorTest extends JerseyTest {
+ private Weld weld;
+
+ @Before
+ public void setup() {
+ Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ weld = new Weld();
+ weld.initialize();
+ super.setUp();
+ }
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
+ weld.shutdown();
+ super.tearDown();
+ }
+ }
+
+ @Override
+ protected Application configure() {
+ return new App();
+ }
+
+ @Override
+ protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+ return new GrizzlyWebTestContainerFactory();
+ }
+
+ @Override
+ protected DeploymentContext configureDeployment() {
+ return ServletDeploymentContext.builder(configure())
+ .initParam(ServletProperties.JAXRS_APPLICATION_CLASS, App.class.getName())
+ .build();
+ }
+
+ @Test
+ public void testContextInConstructorAndInjectInClass() throws InterruptedException {
+ try (Response r = target().path("get").request().get()) {
+ Assert.assertEquals("OK", r.readEntity(String.class));
+ }
+ }
+}
diff --git a/tests/integration/cdi-integration/pom.xml b/tests/integration/cdi-integration/pom.xml
index 8de0c3f..9f7719d 100644
--- a/tests/integration/cdi-integration/pom.xml
+++ b/tests/integration/cdi-integration/pom.xml
@@ -41,6 +41,7 @@
<module>cdi-log-check</module>
<module>cdi-multimodule</module>
<module>cdi-multipart-webapp</module>
+ <module>cdi-resource-with-at-context</module>
<module>cdi-test-webapp</module>
<module>cdi-with-jersey-injection-custom-cfg-webapp</module>
<module>cdi-with-jersey-injection-custom-hk2-banned-webapp</module>