From 81a94296b53f3e5d2c5e7e3335e905e1362732bd Mon Sep 17 00:00:00 2001 From: jansupol Date: Wed, 20 Jan 2021 15:57:55 +0100 Subject: [PATCH 1/2] Allow for having CDI on pure Jersey Client without Jersey Server jars dependencies Signed-off-by: jansupol --- .../jersey/client/ClientBootstrapBag.java | 27 +- .../client/ClientComponentConfigurator.java | 63 +++ .../glassfish/jersey/client/ClientConfig.java | 13 +- .../internal/inject/ProviderBinder.java | 31 +- .../jersey/spi/ComponentProvider.java | 92 ++++ .../server/ResourceModelConfigurator.java | 5 +- .../jersey/server/spi/ComponentProvider.java | 42 +- ext/cdi/jersey-cdi1x/pom.xml | 3 +- .../cdi1x/internal/CdiComponentProvider.java | 422 ++++++------------ ...mponentProviderClientRuntimeSpecifics.java | 62 +++ .../CdiComponentProviderRuntimeSpecifics.java | 37 ++ ...mponentProviderServerRuntimeSpecifics.java | 233 ++++++++++ .../internal/CdiServerComponentProvider.java | 53 +++ .../jersey/ext/cdi1x/internal/CdiUtil.java | 10 + ...ssfish.jersey.server.spi.ComponentProvider | 2 +- ...org.glassfish.jersey.spi.ComponentProvider | 1 + ext/microprofile/mp-rest-client/pom.xml | 7 +- .../cdi-client-on-server/pom.xml | 110 +++++ .../tests/cdi/client/CdiClientFilter.java | 35 ++ .../CdiEnabledClientOnServerApplication.java | 9 + .../CdiEnabledClientOnServerResource.java | 45 ++ .../src/main/resources/META-INF/beans.xml | 27 ++ .../BeanManagerInjectedOnClientTest.java | 72 +++ .../cdi-integration/cdi-client/pom.xml | 81 ++++ .../tests/cdi/client/CdiClientFilter.java | 41 ++ .../src/main/resources/META-INF/beans.xml | 26 ++ .../BeanManagerInjectedOnClientTest.java | 63 +++ tests/integration/cdi-integration/pom.xml | 4 +- 28 files changed, 1272 insertions(+), 344 deletions(-) create mode 100644 core-client/src/main/java/org/glassfish/jersey/client/ClientComponentConfigurator.java create mode 100644 core-common/src/main/java/org/glassfish/jersey/spi/ComponentProvider.java create mode 100644 ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderClientRuntimeSpecifics.java create mode 100644 ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderRuntimeSpecifics.java create mode 100644 ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProviderServerRuntimeSpecifics.java create mode 100644 ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiServerComponentProvider.java create mode 100644 ext/cdi/jersey-cdi1x/src/main/resources/META-INF/services/org.glassfish.jersey.spi.ComponentProvider create mode 100644 tests/integration/cdi-integration/cdi-client-on-server/pom.xml create mode 100644 tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiClientFilter.java create mode 100644 tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiEnabledClientOnServerApplication.java create mode 100644 tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiEnabledClientOnServerResource.java create mode 100644 tests/integration/cdi-integration/cdi-client-on-server/src/main/resources/META-INF/beans.xml create mode 100644 tests/integration/cdi-integration/cdi-client-on-server/src/test/java/org/glassfish/jersey/tests/cdi/client/BeanManagerInjectedOnClientTest.java create mode 100644 tests/integration/cdi-integration/cdi-client/pom.xml create mode 100644 tests/integration/cdi-integration/cdi-client/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiClientFilter.java create mode 100644 tests/integration/cdi-integration/cdi-client/src/main/resources/META-INF/beans.xml create mode 100644 tests/integration/cdi-integration/cdi-client/src/test/java/org/glassfish/jersey/tests/cdi/client/BeanManagerInjectedOnClientTest.java diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientBootstrapBag.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientBootstrapBag.java index ced406a7d2..9ec6d9908b 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/ClientBootstrapBag.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientBootstrapBag.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 Payara Foundation and/or its affiliates. All rights reserved. - * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -19,6 +19,11 @@ import org.glassfish.jersey.internal.BootstrapBag; import org.glassfish.jersey.client.inject.ParameterUpdaterProvider; +import org.glassfish.jersey.internal.util.collection.LazyValue; +import org.glassfish.jersey.spi.ComponentProvider; + +import javax.ws.rs.core.GenericType; +import java.util.Collection; /** * {@inheritDoc} @@ -30,6 +35,7 @@ public class ClientBootstrapBag extends BootstrapBag { private ParameterUpdaterProvider parameterUpdaterProvider; + private LazyValue> componentProviders; public ParameterUpdaterProvider getParameterUpdaterProvider() { requireNonNull(parameterUpdaterProvider, ParameterUpdaterProvider.class); @@ -39,4 +45,23 @@ public ParameterUpdaterProvider getParameterUpdaterProvider() { public void setParameterUpdaterProvider(ParameterUpdaterProvider provider) { this.parameterUpdaterProvider = provider; } + + /** + * Gets a lazy initialized collection of {@link ComponentProvider}s. + * + * @return A lazy initialized collection of {@code ComponentProvider}s. + */ + LazyValue> getComponentProviders() { + requireNonNull(componentProviders, new GenericType>>() {}.getType()); + return componentProviders; + } + + /** + * Sets a lazy initialized collection of {@link ComponentProvider}s. + * + * @param componentProviders A lazy initialized collection of {@code ComponentProvider}s. + */ + void setComponentProviders(LazyValue> componentProviders) { + this.componentProviders = componentProviders; + } } diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientComponentConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientComponentConfigurator.java new file mode 100644 index 0000000000..943acc838a --- /dev/null +++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientComponentConfigurator.java @@ -0,0 +1,63 @@ +/* + * 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.client; + +import org.glassfish.jersey.internal.BootstrapBag; +import org.glassfish.jersey.internal.BootstrapConfigurator; +import org.glassfish.jersey.internal.ServiceConfigurationError; +import org.glassfish.jersey.internal.ServiceFinder; +import org.glassfish.jersey.internal.inject.InjectionManager; +import org.glassfish.jersey.internal.util.collection.LazyValue; +import org.glassfish.jersey.internal.util.collection.Value; +import org.glassfish.jersey.internal.util.collection.Values; +import org.glassfish.jersey.model.internal.RankedComparator; +import org.glassfish.jersey.model.internal.RankedProvider; +import org.glassfish.jersey.spi.ComponentProvider; + +import java.util.Collection; +import java.util.Comparator; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +class ClientComponentConfigurator implements BootstrapConfigurator { + private static final Comparator> RANKED_COMPARATOR = + new RankedComparator<>(RankedComparator.Order.DESCENDING); + + @Override + public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) { + // There are situation in which ComponentProviders are not needed therefore their entire initialization is wrapped + // into a lazy block. + LazyValue> componentProviders = + Values.lazy((Value>) () -> getRankedComponentProviders().stream() + .map(RankedProvider::getProvider) + .peek(provider -> provider.initialize(injectionManager)) + .collect(Collectors.toList())); + ((ClientBootstrapBag) bootstrapBag).setComponentProviders(componentProviders); + } + + @Override + public void postInit(InjectionManager injectionManager, BootstrapBag bootstrapBag) { + ((ClientBootstrapBag) bootstrapBag).getComponentProviders().get().forEach(ComponentProvider::done); + } + + private static Collection> getRankedComponentProviders() throws ServiceConfigurationError { + return StreamSupport.stream(ServiceFinder.find(ComponentProvider.class).spliterator(), false) + .map(RankedProvider::new) + .sorted(RANKED_COMPARATOR) + .collect(Collectors.toList()); + } +} diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java index d444788aa4..0979ec6915 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018 Payara Foundation and/or its affiliates. * * This program and the accompanying materials are made available under the @@ -59,6 +59,7 @@ import org.glassfish.jersey.model.internal.ManagedObjectsFinalizer; import org.glassfish.jersey.process.internal.RequestScope; import org.glassfish.jersey.internal.inject.ParamConverterConfigurator; +import org.glassfish.jersey.spi.ComponentProvider; /** * Jersey externalized implementation of client-side JAX-RS {@link javax.ws.rs.core.Configurable @@ -412,7 +413,7 @@ private ClientRuntime initRuntime() { InjectionManager injectionManager = Injections.createInjectionManager(); injectionManager.register(new ClientBinder(runtimeCfgState.getProperties())); - BootstrapBag bootstrapBag = new ClientBootstrapBag(); + final ClientBootstrapBag bootstrapBag = new ClientBootstrapBag(); bootstrapBag.setManagedObjectsFinalizer(new ManagedObjectsFinalizer(injectionManager)); final ClientMessageBodyFactory.MessageBodyWorkersConfigurator messageBodyWorkersConfigurator = @@ -427,7 +428,8 @@ private ClientRuntime initRuntime() { messageBodyWorkersConfigurator, new ExceptionMapperFactory.ExceptionMappersConfigurator(), new JaxrsProviders.ProvidersConfigurator(), - new AutoDiscoverableConfigurator(RuntimeType.CLIENT)); + new AutoDiscoverableConfigurator(RuntimeType.CLIENT), + new ClientComponentConfigurator()); bootstrapConfigurators.forEach(configurator -> configurator.init(injectionManager, bootstrapBag)); // AutoDiscoverable. @@ -442,7 +444,10 @@ private ClientRuntime initRuntime() { runtimeCfgState.configureMetaProviders(injectionManager, bootstrapBag.getManagedObjectsFinalizer()); // Bind providers. - ProviderBinder.bindProviders(runtimeCfgState.getComponentBag(), RuntimeType.CLIENT, null, injectionManager); + final Collection componentProviders = bootstrapBag.getComponentProviders().get(); + ProviderBinder.bindProviders( + runtimeCfgState.getComponentBag(), RuntimeType.CLIENT, null, injectionManager, componentProviders + ); ClientExecutorProvidersConfigurator executorProvidersConfigurator = new ClientExecutorProvidersConfigurator(runtimeCfgState.getComponentBag(), diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ProviderBinder.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ProviderBinder.java index bc7e01e099..3d4c7f6d86 100644 --- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ProviderBinder.java +++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ProviderBinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -34,6 +34,7 @@ import org.glassfish.jersey.model.ContractProvider; import org.glassfish.jersey.model.internal.ComponentBag; +import org.glassfish.jersey.spi.ComponentProvider; /** * Class used for registration of the custom providers into injection manager. @@ -189,22 +190,24 @@ protected void configure() { * @param injectionManager injection manager the binder will use to bind the providers into. */ public static void bindProviders(final ComponentBag componentBag, final InjectionManager injectionManager) { - bindProviders(componentBag, null, Collections.emptySet(), injectionManager); + bindProviders(componentBag, null, null, injectionManager, null); } /** * Bind all providers contained in {@code providerBag} (classes and instances) using injection manager. Configuration is * also committed. * - * @param componentBag bag of provider classes and instances. - * @param constrainedTo current runtime (client or server). - * @param registeredClasses classes which are manually registered by the user (not found by the classpath scanning). - * @param injectionManager injection manager the binder will use to bind the providers into. + * @param componentBag bag of provider classes and instances. + * @param constrainedTo current runtime (client or server). + * @param registeredClasses classes which are manually registered by the user (not found by the classpath scanning). + * @param injectionManager injection manager the binder will use to bind the providers into. + * @param componentProviders available component providers capable of registering the classes */ public static void bindProviders(ComponentBag componentBag, RuntimeType constrainedTo, Set> registeredClasses, - InjectionManager injectionManager) { + InjectionManager injectionManager, + Collection componentProviders) { Predicate filter = ComponentBag.EXCLUDE_EMPTY .and(ComponentBag.excludeMetaProviders(injectionManager)); @@ -234,7 +237,9 @@ public static void bindProviders(ComponentBag componentBag, } for (final Class providerClass : classes) { final ContractProvider model = componentBag.getModel(providerClass); - binderToRegister.addAll(createProviderBinders(providerClass, model)); + if (componentProviders == null || !bindWithComponentProvider(providerClass, model, componentProviders)) { + binderToRegister.addAll(createProviderBinders(providerClass, model)); + } } // Bind provider instances except for pure meta-providers and providers with empty contract models (e.g. resources) @@ -252,6 +257,16 @@ public static void bindProviders(ComponentBag componentBag, injectionManager.register(CompositeBinder.wrap(binderToRegister)); } + private static boolean bindWithComponentProvider( + Class component, ContractProvider providerModel, Iterable componentProviders) { + for (ComponentProvider provider : componentProviders) { + if (provider.bind(component, providerModel)) { + return true; + } + } + return false; + } + @SuppressWarnings("unchecked") private static Collection createInstanceBinders(T instance) { Function binderFunction = contract -> diff --git a/core-common/src/main/java/org/glassfish/jersey/spi/ComponentProvider.java b/core-common/src/main/java/org/glassfish/jersey/spi/ComponentProvider.java new file mode 100644 index 0000000000..61d963a90a --- /dev/null +++ b/core-common/src/main/java/org/glassfish/jersey/spi/ComponentProvider.java @@ -0,0 +1,92 @@ +/* + * 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.spi; + +import java.util.Collections; +import java.util.Set; + +import org.glassfish.jersey.internal.inject.InjectionManager; +import org.glassfish.jersey.model.ContractProvider; + +/** + * Component provider interface to allow custom management of 3rd party + * components life-cycle and dependency injection. + *

+ * An implementation (a component-provider) identifies itself by placing a provider-configuration + * file (if not already present), {@code org.glassfish.jersey.spi.ComponentProvider} + * in the resource directory META-INF/services, and adding the fully + * qualified service-provider-class of the implementation in the file. + * + * Jersey will not even try to inject component provider instances with Jersey artifacts. + * The SPI providers should be designed so that no dependency injection is needed at the bind time phase. + + * @author Jakub Podlesak + */ +public interface ComponentProvider { + + + /** + * Initializes the component provider with a reference to a injection manager + * instance, which will get used in the application to manage individual components. + * Providers should keep a reference to the injection manager for later use. + * This method will be invoked prior to any bind method calls. + * The injection manager parameter will not be fully initialized at the time of invocation + * and should be used as a reference only. + * + * @param injectionManager an injection manager. + */ + void initialize(final InjectionManager injectionManager); + + /** + * Jersey will invoke this method before binding of each component class internally + * during initialization of it's injection manager. + * + * If the component provider wants to bind the component class + * itself, it must do so and return true. In that case, Jersey will not + * bind the component and rely on the component provider in this regard. + * + * @param component a component (resource/provider) class. + * @param providerContracts provider contracts implemented by given component. + * @return true if the component class has been bound by the provider, false otherwise + */ + boolean bind(final Class component, Set> providerContracts); + + /** + * Jersey will invoke this method before binding of each component class internally + * during initialization of it's injection manager. + * + * If the component provider wants to bind the component class + * itself, it must do so and return true. In that case, Jersey will not + * bind the component and rely on the component provider in this regard. + * + * @param component a component (resource/provider) class. + * @param contractProvider optional registered {@link ContractProvider} of the component. + * @return true if the component class has been bound by the provider, false otherwise + */ + default boolean bind(final Class component, ContractProvider contractProvider) { + final Set> contracts = contractProvider == null ? Collections.emptySet() : contractProvider.getContracts(); + return bind(component, contracts); + } + + /** + * Jersey will invoke this method after all component classes have been bound. + * + * If the component provider wants to do some actions after it has seen all component classes + * registered with the application, this is the right place for the corresponding code. + */ + void done(); +} diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ResourceModelConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/ResourceModelConfigurator.java index 8bd2cc8046..5f0cd98689 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/ResourceModelConfigurator.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/ResourceModelConfigurator.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 @@ -189,9 +189,8 @@ private void bindProvidersAndResources( private boolean bindWithComponentProvider( Class component, ContractProvider providerModel, Iterable componentProviders) { - Set> contracts = providerModel == null ? Collections.emptySet() : providerModel.getContracts(); for (ComponentProvider provider : componentProviders) { - if (provider.bind(component, contracts)) { + if (provider.bind(component, providerModel)) { return true; } } diff --git a/core-server/src/main/java/org/glassfish/jersey/server/spi/ComponentProvider.java b/core-server/src/main/java/org/glassfish/jersey/server/spi/ComponentProvider.java index 05dcbe13b6..d09aa83de4 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/spi/ComponentProvider.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/spi/ComponentProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -16,10 +16,6 @@ package org.glassfish.jersey.server.spi; -import java.util.Set; - -import org.glassfish.jersey.internal.inject.InjectionManager; - /** * Component provider interface to allow custom management of 3rd party * components life-cycle and dependency injection. @@ -34,40 +30,6 @@ * @author Jakub Podlesak */ -public interface ComponentProvider { - - - /** - * Initializes the component provider with a reference to a injection manager - * instance, which will get used in the application to manage individual components. - * Providers should keep a reference to the injection manager for later use. - * This method will be invoked prior to any bind method calls. - * The injection manager parameter will not be fully initialized at the time of invocation - * and should be used as a reference only. - * - * @param injectionManager an injection manager. - */ - void initialize(final InjectionManager injectionManager); - - /** - * Jersey will invoke this method before binding of each component class internally - * during initialization of it's injection manager. - * - * If the component provider wants to bind the component class - * itself, it must do so and return true. In that case, Jersey will not - * bind the component and rely on the component provider in this regard. - * - * @param component a component (resource/provider) class. - * @param providerContracts provider contracts implemented by given component. - * @return true if the component class has been bound by the provider, false otherwise - */ - boolean bind(final Class component, Set> providerContracts); +public interface ComponentProvider extends org.glassfish.jersey.spi.ComponentProvider { - /** - * Jersey will invoke this method after all component classes have been bound. - * - * If the component provider wants to do some actions after it has seen all component classes - * registered with the application, this is the right place for the corresponding code. - */ - void done(); } diff --git a/ext/cdi/jersey-cdi1x/pom.xml b/ext/cdi/jersey-cdi1x/pom.xml index ad540f6e2a..d5b9742104 100644 --- a/ext/cdi/jersey-cdi1x/pom.xml +++ b/ext/cdi/jersey-cdi1x/pom.xml @@ -1,7 +1,7 @@ + + + 4.0.0 + + org.glassfish.jersey.tests.integration.cdi + cdi-integration-project + 2.34-SNAPSHOT + + + cdi-client-on-server + jersey-tests-cdi-client-on-server + war + + CDI works on a client on a server resource + + + + jakarta.ws.rs + jakarta.ws.rs-api + provided + + + jakarta.annotation + jakarta.annotation-api + provided + + + javax.enterprise + cdi-api + provided + + + jakarta.interceptor + jakarta.interceptor-api + ${javax.interceptor.version} + provided + + + org.glassfish.jersey.test-framework.providers + jersey-test-framework-provider-bundle + pom + test + + + org.glassfish.jersey.test-framework + jersey-test-framework-util + provided + + + org.glassfish.jersey.ext.cdi + jersey-weld2-se + test + + + org.jboss.weld.se + weld-se-core + test + + + org.glassfish.jersey.ext.cdi + jersey-cdi1x + ${project.version} + provided + + + + + + run-external-tests + + + + org.apache.maven.plugins + maven-surefire-plugin + + + ${external.container.factory} + ${external.container.port} + + + + + + + + org.glassfish.jersey.test.external.ExternalTestContainerFactory + 8080 + false + + + + diff --git a/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiClientFilter.java b/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiClientFilter.java new file mode 100644 index 0000000000..5921135d0e --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiClientFilter.java @@ -0,0 +1,35 @@ +/* + * 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.client; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.core.Response; +import java.io.IOException; + +@ApplicationScoped +public class CdiClientFilter implements ClientRequestFilter { + @Inject + BeanManager beanManager; + + public void filter(ClientRequestContext requestContext) throws IOException { + final Response.Status status = beanManager == null ? Response.Status.INTERNAL_SERVER_ERROR : Response.Status.OK; + requestContext.abortWith(Response.status(status).build()); + } +} diff --git a/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiEnabledClientOnServerApplication.java b/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiEnabledClientOnServerApplication.java new file mode 100644 index 0000000000..5282bdefdf --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiEnabledClientOnServerApplication.java @@ -0,0 +1,9 @@ +package org.glassfish.jersey.tests.cdi.client; + +import org.glassfish.jersey.server.ResourceConfig; + +class CdiEnabledClientOnServerApplication extends ResourceConfig { + CdiEnabledClientOnServerApplication() { + register(CdiEnabledClientOnServerResource.class); + } +} diff --git a/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiEnabledClientOnServerResource.java b/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiEnabledClientOnServerResource.java new file mode 100644 index 0000000000..e076d3c5fa --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client-on-server/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiEnabledClientOnServerResource.java @@ -0,0 +1,45 @@ +/* + * 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.client; + +import javax.enterprise.context.RequestScoped; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +@RequestScoped +@Path("/resource") +public class CdiEnabledClientOnServerResource { + @Inject + BeanManager beanManager; + + @Context + UriInfo uriInfo; + + @Path("main") + @GET + public Response getResponse() { + try (Response r = ClientBuilder.newBuilder().register(CdiClientFilter.class).build() + .target(uriInfo.getBaseUri()).path("/resource/nomain").request().get()) { + return Response.status(r.getStatus()).build(); + } + } +} diff --git a/tests/integration/cdi-integration/cdi-client-on-server/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-integration/cdi-client-on-server/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000..532cfcaff8 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client-on-server/src/main/resources/META-INF/beans.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/tests/integration/cdi-integration/cdi-client-on-server/src/test/java/org/glassfish/jersey/tests/cdi/client/BeanManagerInjectedOnClientTest.java b/tests/integration/cdi-integration/cdi-client-on-server/src/test/java/org/glassfish/jersey/tests/cdi/client/BeanManagerInjectedOnClientTest.java new file mode 100644 index 0000000000..6eb906452d --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client-on-server/src/test/java/org/glassfish/jersey/tests/cdi/client/BeanManagerInjectedOnClientTest.java @@ -0,0 +1,72 @@ +/* + * 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.client; + +import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.external.ExternalTestContainerFactory; +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.ws.rs.core.Application; +import javax.ws.rs.core.Response; + +public class BeanManagerInjectedOnClientTest extends JerseyTest { + private Weld weld; + + @Before + public void setup() { + Assume.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy()); + } + + @Override + public void setUp() throws Exception { + if (Hk2InjectionManagerFactory.isImmediateStrategy()) { + if (!ExternalTestContainerFactory.class.isAssignableFrom(getTestContainerFactory().getClass())) { + weld = new Weld(); + weld.initialize(); + } + super.setUp(); + } + } + + @Override + public void tearDown() throws Exception { + if (Hk2InjectionManagerFactory.isImmediateStrategy()) { + if (!ExternalTestContainerFactory.class.isAssignableFrom(getTestContainerFactory().getClass())) { + weld.shutdown(); + } + super.tearDown(); + } + } + + @Override + protected Application configure() { + return new CdiEnabledClientOnServerApplication(); + } + + @Test + public void testBeanManagerIsInjected() { + try (Response r = target("resource").path("main").request().get()) { + Assert.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); + System.out.println(r.readEntity(String.class)); + } + } +} diff --git a/tests/integration/cdi-integration/cdi-client/pom.xml b/tests/integration/cdi-integration/cdi-client/pom.xml new file mode 100644 index 0000000000..2653bfa895 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client/pom.xml @@ -0,0 +1,81 @@ + + + + + 4.0.0 + + org.glassfish.jersey.tests.integration.cdi + cdi-integration-project + 2.34-SNAPSHOT + + + cdi-client + jersey-tests-cdi-client + + CDI works on a client when no Jersey server dependencies + + + + jakarta.ws.rs + jakarta.ws.rs-api + provided + + + jakarta.annotation + jakarta.annotation-api + provided + + + javax.enterprise + cdi-api + provided + + + org.jboss.weld.se + weld-se-core + test + + + org.glassfish.jersey.core + jersey-client + test + + + org.glassfish.jersey.ext.cdi + jersey-cdi1x + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${skip.tests} + + + + + diff --git a/tests/integration/cdi-integration/cdi-client/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiClientFilter.java b/tests/integration/cdi-integration/cdi-client/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiClientFilter.java new file mode 100644 index 0000000000..d52d3032d9 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client/src/main/java/org/glassfish/jersey/tests/cdi/client/CdiClientFilter.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.client; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.inject.spi.BeanManager; +import javax.inject.Inject; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import java.io.IOException; + +@ApplicationScoped +public class CdiClientFilter implements ClientRequestFilter { + @Inject + BeanManager beanManager; + + @Context + HttpHeaders headers; + + public void filter(ClientRequestContext requestContext) throws IOException { + final Response.Status status = beanManager == null ? Response.Status.INTERNAL_SERVER_ERROR : Response.Status.OK; + requestContext.abortWith(Response.status(status).build()); + } +} diff --git a/tests/integration/cdi-integration/cdi-client/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-integration/cdi-client/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000000..27909adeba --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client/src/main/resources/META-INF/beans.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/tests/integration/cdi-integration/cdi-client/src/test/java/org/glassfish/jersey/tests/cdi/client/BeanManagerInjectedOnClientTest.java b/tests/integration/cdi-integration/cdi-client/src/test/java/org/glassfish/jersey/tests/cdi/client/BeanManagerInjectedOnClientTest.java new file mode 100644 index 0000000000..26c7ceac16 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-client/src/test/java/org/glassfish/jersey/tests/cdi/client/BeanManagerInjectedOnClientTest.java @@ -0,0 +1,63 @@ +/* + * 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.client; + +import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory; +import org.glassfish.jersey.internal.util.ReflectionHelper; +import org.jboss.weld.environment.se.Weld; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; +import java.security.AccessController; + +public class BeanManagerInjectedOnClientTest { + private static Weld weld; + + @BeforeAll + public static void setup() { + Assumptions.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy()); + weld = new Weld(); + weld.initialize(); + } + + @AfterAll + public static void tearDown() throws Exception { + if (Hk2InjectionManagerFactory.isImmediateStrategy()) { + weld.shutdown(); + } + } + + @Test + public void testBeanManagerIsInjected() { + // test that there is no server is available + + final String serverComponentProvider = "org.glassfish.jersey.server.spi.ComponentProvider"; + final Class aClass = AccessController.doPrivileged(ReflectionHelper.classForNamePA(serverComponentProvider)); + Assertions.assertNull(aClass); + + // test CDI injection + try (Response r = ClientBuilder.newClient().register(CdiClientFilter.class) + .target("http://localhost:8080/abort").request().get()) { + Assertions.assertEquals(Response.Status.OK.getStatusCode(), r.getStatus()); + } + } +} diff --git a/tests/integration/cdi-integration/pom.xml b/tests/integration/cdi-integration/pom.xml index 18b9b0044f..135f6ebbe2 100644 --- a/tests/integration/cdi-integration/pom.xml +++ b/tests/integration/cdi-integration/pom.xml @@ -1,7 +1,7 @@