Skip to content

Commit 8502286

Browse files
committed
Enable to use @context in constructors of classes instantiated by CDI
Signed-off-by: jansupol <jan.supol@oracle.com>
1 parent d68be87 commit 8502286

File tree

10 files changed

+321
-4
lines changed

10 files changed

+321
-4
lines changed

core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -109,6 +109,17 @@ public interface InjectionManager {
109109
*/
110110
boolean isRegistrable(Class<?> clazz);
111111

112+
/**
113+
* Creates an object with the given class.
114+
* <p>
115+
* The object created is not managed by the injection manager.
116+
*
117+
* @param createMe The non-null class to create this object from;
118+
* @return An instance of the object that has been created.
119+
* @since 2.35
120+
*/
121+
<T> T create(Class<T> createMe);
122+
112123
/**
113124
* Creates, injects and post-constructs an object with the given class. This is equivalent to calling the
114125
* {@code create-class} method followed by the {@code inject-class} method followed by the {@code post-construct} method.

ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/AbstractCdiBeanSupplier.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public void preDestroy(final T instance) {
8585
@Override
8686
public T getInstance(final Class<T> clazz) {
8787
final CreationalContext<T> creationalContext = beanManager.createCreationalContext(null);
88-
final T instance = injectionTarget.produce(creationalContext);
88+
final T instance = produce(injectionTarget, creationalContext, injectionManager, clazz);
8989
final CdiComponentProvider cdiComponentProvider = beanManager.getExtension(CdiComponentProvider.class);
9090
final CdiComponentProvider.InjectionManagerInjectedCdiTarget hk2managedTarget =
9191
cdiComponentProvider.new InjectionManagerInjectedCdiTarget(injectionTarget) {
@@ -107,6 +107,18 @@ public void preDestroy(final T instance) {
107107
};
108108
}
109109

110+
/*
111+
* Let CDI produce the InjectionTarget. If the constructor contains @Context Args CDI won't be able to produce it.
112+
* Let the HK2 try to produce the target then.
113+
*/
114+
private static <T> T produce(InjectionTarget<T> target, CreationalContext<T> ctx, InjectionManager im, Class<T> clazz) {
115+
try {
116+
return target.produce(ctx);
117+
} catch (Exception e) {
118+
return im.create(clazz);
119+
}
120+
}
121+
110122
@SuppressWarnings(value = "unchecked")
111123
/* package */ T _provide() {
112124
final T instance = referenceProvider.getInstance(clazz);

inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManager.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -115,6 +115,23 @@ public <T> T createAndInitialize(Class<T> createMe) {
115115
}
116116
}
117117

118+
@Override
119+
public <T> T create(Class<T> createMe) {
120+
if (isInitialized()) {
121+
Unmanaged.UnmanagedInstance<T> unmanaged = new Unmanaged<>(createMe).newInstance();
122+
return unmanaged.produce().get();
123+
} else {
124+
// TODO: method is invoked before #completeRegistration - creates AutoDiscoverable, ForcedAutoDiscoverable.
125+
// Hack: creates an object with default constructor and without an injection.
126+
try {
127+
Constructor<T> constructor = createMe.getConstructor();
128+
return constructor.newInstance();
129+
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
130+
throw new RuntimeException("Cannot create an instance of a class: " + createMe, e);
131+
}
132+
}
133+
}
134+
118135
@Override
119136
@SuppressWarnings("unchecked")
120137
public <T> List<ServiceHolder<T>> getAllServiceHolders(Class<T> contractOrImpl, Annotation... qualifiers) {

inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/AbstractHk2InjectionManager.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -184,6 +184,11 @@ public void shutdown() {
184184
}
185185
}
186186

187+
@Override
188+
public <U> U create(Class<U> clazz) {
189+
return getServiceLocator().create(clazz);
190+
}
191+
187192
@Override
188193
public <U> U createAndInitialize(Class<U> clazz) {
189194
return getServiceLocator().createAndInitialize(clazz);
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
5+
6+
This program and the accompanying materials are made available under the
7+
terms of the Eclipse Public License v. 2.0, which is available at
8+
http://www.eclipse.org/legal/epl-2.0.
9+
10+
This Source Code may also be made available under the following Secondary
11+
Licenses when the conditions for such availability set forth in the
12+
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
13+
version 2 with the GNU Classpath Exception, which is available at
14+
https://www.gnu.org/software/classpath/license.html.
15+
16+
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
17+
18+
-->
19+
<project xmlns="http://maven.apache.org/POM/4.0.0"
20+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
22+
<parent>
23+
<groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
24+
<artifactId>cdi-integration-project</artifactId>
25+
<version>2.35-SNAPSHOT</version>
26+
</parent>
27+
<modelVersion>4.0.0</modelVersion>
28+
29+
<artifactId>cdi-resource-with-at-context</artifactId>
30+
31+
<name>jersey-tests-resource-with-at-context</name>
32+
33+
<description>CDI works for a resource class with constructor with @Context</description>
34+
35+
<dependencies>
36+
<dependency>
37+
<groupId>jakarta.ws.rs</groupId>
38+
<artifactId>jakarta.ws.rs-api</artifactId>
39+
<scope>provided</scope>
40+
</dependency>
41+
<dependency>
42+
<groupId>jakarta.annotation</groupId>
43+
<artifactId>jakarta.annotation-api</artifactId>
44+
<scope>provided</scope>
45+
</dependency>
46+
<dependency>
47+
<groupId>javax.enterprise</groupId>
48+
<artifactId>cdi-api</artifactId>
49+
<version>2.0</version>
50+
<scope>provided</scope>
51+
</dependency>
52+
<dependency>
53+
<groupId>jakarta.servlet</groupId>
54+
<artifactId>jakarta.servlet-api</artifactId>
55+
<version>${servlet4.version}</version>
56+
</dependency>
57+
<dependency>
58+
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
59+
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
60+
<scope>test</scope>
61+
</dependency>
62+
<dependency>
63+
<groupId>org.glassfish.jersey.ext.cdi</groupId>
64+
<artifactId>jersey-weld2-se</artifactId>
65+
<scope>test</scope>
66+
</dependency>
67+
<dependency>
68+
<groupId>org.jboss.weld.se</groupId>
69+
<artifactId>weld-se-core</artifactId>
70+
<scope>test</scope>
71+
</dependency>
72+
<dependency>
73+
<groupId>org.glassfish.jersey.ext.cdi</groupId>
74+
<artifactId>jersey-cdi1x</artifactId>
75+
</dependency>
76+
<dependency>
77+
<groupId>org.glassfish.jersey.ext.cdi</groupId>
78+
<artifactId>jersey-cdi-rs-inject</artifactId>
79+
</dependency>
80+
<dependency>
81+
<groupId>org.glassfish.jersey.media</groupId>
82+
<artifactId>jersey-media-sse</artifactId>
83+
</dependency>
84+
<dependency>
85+
<groupId>org.glassfish.jersey.containers</groupId>
86+
<artifactId>jersey-container-servlet-core</artifactId>
87+
</dependency>
88+
</dependencies>
89+
90+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
package org.glassfish.jersey.tests.cdi.resourceatcontext;
17+
18+
import org.glassfish.jersey.server.ResourceConfig;
19+
20+
public class App extends ResourceConfig {
21+
public App() {
22+
register(ResourceWithConstructor.class);
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
package org.glassfish.jersey.tests.cdi.resourceatcontext;
17+
18+
import javax.enterprise.inject.spi.BeanManager;
19+
import javax.inject.Inject;
20+
import javax.ws.rs.GET;
21+
import javax.ws.rs.Path;
22+
import javax.ws.rs.core.Context;
23+
import javax.ws.rs.core.HttpHeaders;
24+
25+
@Path("/")
26+
public class ResourceWithConstructor {
27+
HttpHeaders headers;
28+
29+
@Inject
30+
BeanManager beanManager;
31+
32+
public ResourceWithConstructor(@Context HttpHeaders headers) {
33+
this.headers = headers;
34+
}
35+
36+
@GET
37+
@Path("get")
38+
public String get() {
39+
return headers != null && beanManager != null ? "OK" : "NOK";
40+
}
41+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
5+
6+
This program and the accompanying materials are made available under the
7+
terms of the Eclipse Public License v. 2.0, which is available at
8+
http://www.eclipse.org/legal/epl-2.0.
9+
10+
This Source Code may also be made available under the following Secondary
11+
Licenses when the conditions for such availability set forth in the
12+
Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
13+
version 2 with the GNU Classpath Exception, which is available at
14+
https://www.gnu.org/software/classpath/license.html.
15+
16+
SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
17+
18+
-->
19+
20+
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
23+
http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
24+
bean-discovery-mode="none">
25+
</beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.jersey.tests.cdi.resourceatcontext;
18+
19+
import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory;
20+
import org.glassfish.jersey.server.ResourceConfig;
21+
import org.glassfish.jersey.servlet.ServletProperties;
22+
import org.glassfish.jersey.test.DeploymentContext;
23+
import org.glassfish.jersey.test.JerseyTest;
24+
import org.glassfish.jersey.test.ServletDeploymentContext;
25+
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
26+
import org.glassfish.jersey.test.spi.TestContainerException;
27+
import org.glassfish.jersey.test.spi.TestContainerFactory;
28+
import org.jboss.weld.environment.se.Weld;
29+
import org.junit.Assert;
30+
import org.junit.Assume;
31+
import org.junit.Before;
32+
import org.junit.Test;
33+
34+
import javax.enterprise.inject.spi.BeanManager;
35+
import javax.inject.Inject;
36+
import javax.ws.rs.GET;
37+
import javax.ws.rs.Path;
38+
import javax.ws.rs.core.Application;
39+
import javax.ws.rs.core.Context;
40+
import javax.ws.rs.core.HttpHeaders;
41+
import javax.ws.rs.core.Response;
42+
43+
public class ResourceWithConstructorTest extends JerseyTest {
44+
private Weld weld;
45+
46+
@Before
47+
public void setup() {
48+
Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy());
49+
}
50+
51+
@Override
52+
public void setUp() throws Exception {
53+
if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
54+
weld = new Weld();
55+
weld.initialize();
56+
super.setUp();
57+
}
58+
}
59+
60+
@Override
61+
public void tearDown() throws Exception {
62+
if (Hk2InjectionManagerFactory.isImmediateStrategy()) {
63+
weld.shutdown();
64+
super.tearDown();
65+
}
66+
}
67+
68+
@Override
69+
protected Application configure() {
70+
return new App();
71+
}
72+
73+
@Override
74+
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
75+
return new GrizzlyWebTestContainerFactory();
76+
}
77+
78+
@Override
79+
protected DeploymentContext configureDeployment() {
80+
return ServletDeploymentContext.builder(configure())
81+
.initParam(ServletProperties.JAXRS_APPLICATION_CLASS, App.class.getName())
82+
.build();
83+
}
84+
85+
@Test
86+
public void testContextInConstructorAndInjectInClass() throws InterruptedException {
87+
try (Response r = target().path("get").request().get()) {
88+
Assert.assertEquals("OK", r.readEntity(String.class));
89+
}
90+
}
91+
}

tests/integration/cdi-integration/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<module>cdi-log-check</module>
4242
<module>cdi-multimodule</module>
4343
<module>cdi-multipart-webapp</module>
44+
<module>cdi-resource-with-at-context</module>
4445
<module>cdi-test-webapp</module>
4546
<module>cdi-with-jersey-injection-custom-cfg-webapp</module>
4647
<module>cdi-with-jersey-injection-custom-hk2-banned-webapp</module>

0 commit comments

Comments
 (0)