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 10e3e453c1..36fc6103b8 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 @@ -109,6 +109,17 @@ public interface InjectionManager { */ boolean isRegistrable(Class clazz); + /** + * Creates an object with the given class. + *

+ * 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 create(Class 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. 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 5bea827384..b681a2c3a2 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 @@ public void preDestroy(final T instance) { @Override public T getInstance(final Class clazz) { final CreationalContext 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 @@ public void preDestroy(final T instance) { }; } + /* + * 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 produce(InjectionTarget target, CreationalContext ctx, InjectionManager im, Class 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 7d1e88d7f7..309649077e 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 @@ -115,6 +115,23 @@ public T createAndInitialize(Class createMe) { } } + @Override + public T create(Class createMe) { + if (isInitialized()) { + Unmanaged.UnmanagedInstance 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 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 List> getAllServiceHolders(Class contractOrImpl, Annotation... qualifiers) { 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 543f6626fc..5a71084448 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 @@ -184,6 +184,11 @@ public void shutdown() { } } + @Override + public U create(Class clazz) { + return getServiceLocator().create(clazz); + } + @Override public U createAndInitialize(Class 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 0000000000..aaf101fab6 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml @@ -0,0 +1,90 @@ + + + + + org.glassfish.jersey.tests.integration.cdi + cdi-integration-project + 2.35-SNAPSHOT + + 4.0.0 + + cdi-resource-with-at-context + + jersey-tests-resource-with-at-context + + CDI works for a resource class with constructor with @Context + + + + jakarta.ws.rs + jakarta.ws.rs-api + provided + + + jakarta.annotation + jakarta.annotation-api + provided + + + javax.enterprise + cdi-api + 2.0 + provided + + + jakarta.servlet + jakarta.servlet-api + ${servlet4.version} + + + org.glassfish.jersey.test-framework.providers + jersey-test-framework-provider-grizzly2 + test + + + org.glassfish.jersey.ext.cdi + jersey-weld2-se + test + + + org.jboss.weld.se + weld-se-core + test + + + org.glassfish.jersey.ext.cdi + jersey-cdi1x + + + org.glassfish.jersey.ext.cdi + jersey-cdi-rs-inject + + + org.glassfish.jersey.media + jersey-media-sse + + + org.glassfish.jersey.containers + jersey-container-servlet-core + + + + \ 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 0000000000..c93cc61905 --- /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 0000000000..609b998fdb --- /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 0000000000..9ad6922dfd --- /dev/null +++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/src/main/resources/META-INF/beans.xml @@ -0,0 +1,25 @@ + + + + + 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 0000000000..ace3e0b028 --- /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 8de0c3ffcc..9f7719d0f5 100644 --- a/tests/integration/cdi-integration/pom.xml +++ b/tests/integration/cdi-integration/pom.xml @@ -41,6 +41,7 @@ cdi-log-check cdi-multimodule cdi-multipart-webapp + cdi-resource-with-at-context cdi-test-webapp cdi-with-jersey-injection-custom-cfg-webapp cdi-with-jersey-injection-custom-hk2-banned-webapp