[ https://issues.apache.org/jira/browse/CXF-7643?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16408207#comment-16408207 ]
ASF GitHub Bot commented on CXF-7643: ------------------------------------- dkulp closed pull request #393: CXF-7643 ensure CDI extension defaults are CDI compliant URL: https://github.com/apache/cxf/pull/393 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/integration/cdi/src/main/java/org/apache/cxf/cdi/ContextProducerBean.java b/integration/cdi/src/main/java/org/apache/cxf/cdi/ContextProducerBean.java index 7fab97782d7..98bcca69ee6 100644 --- a/integration/cdi/src/main/java/org/apache/cxf/cdi/ContextProducerBean.java +++ b/integration/cdi/src/main/java/org/apache/cxf/cdi/ContextProducerBean.java @@ -34,16 +34,19 @@ public class ContextProducerBean extends AbstractCXFBean<Object> implements PassivationCapable { private final Type type; + private final Set<Annotation> qualifiers; - ContextProducerBean(Type type) { + ContextProducerBean(Type type, boolean defaultQualifier) { this.type = type; + this.qualifiers = new HashSet<>(defaultQualifier ? 2 : 1); + this.qualifiers.add(ContextResolved.LITERAL); + if (defaultQualifier) { + this.qualifiers.add(DEFAULT); + } } @Override public Set<Annotation> getQualifiers() { - Set<Annotation> qualifiers = new HashSet<>(2); - qualifiers.add(ContextResolved.LITERAL); - qualifiers.add(DEFAULT); return qualifiers; } diff --git a/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java b/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java index bc7a251cbb3..d2b76dbd5cd 100644 --- a/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java +++ b/integration/cdi/src/main/java/org/apache/cxf/cdi/JAXRSCdiResourceExtension.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; @@ -35,6 +36,7 @@ import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.BeforeBeanDiscovery; import javax.enterprise.inject.spi.BeforeShutdown; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.InjectionTarget; @@ -63,6 +65,10 @@ import org.apache.cxf.jaxrs.utils.JAXRSServerFactoryCustomizationUtils; import org.apache.cxf.jaxrs.utils.ResourceUtils; +import static java.util.Arrays.asList; +import static java.util.Optional.ofNullable; +import static org.apache.cxf.cdi.AbstractCXFBean.DEFAULT; + /** * Apache CXF portable CDI extension to support initialization of JAX-RS resources. */ @@ -78,6 +84,8 @@ new ArrayList< CreationalContext< ? > >(); private final Set< Type > contextTypes = new LinkedHashSet<>(); + private final Collection< String > existingStandardClasses = new HashSet<>(); + /** * Holder of the classified resource classes, converted to appropriate instance * representations. @@ -112,6 +120,46 @@ public void addResourceProvider(final CdiResourceProvider other) { } } + // observing JAXRSCdiResourceExtension a "container" can customize that value to prevent some instances + // to be added with the default qualifier + public Collection<String> getExistingStandardClasses() { + return existingStandardClasses; + } + + /** + * Fires itsels, allows other extensions to modify this one. + * Typical example can be to modify existingStandardClasses to prevent CXF + * to own some beans it shouldn't create with default classifier. + * + * @param beforeBeanDiscovery the corresponding cdi event. + * @param beanManager the cdi bean manager. + */ + void onStartup(@Observes final BeforeBeanDiscovery beforeBeanDiscovery, final BeanManager beanManager) { + final ClassLoader loader = ofNullable(Thread.currentThread().getContextClassLoader()) + .orElseGet(ClassLoader::getSystemClassLoader); + boolean webHandled = false; + try { // OWB + loader.loadClass("org.apache.webbeans.web.lifecycle.WebContainerLifecycle"); + webHandled = true; + } catch (final NoClassDefFoundError | ClassNotFoundException e) { + // ok to keep them all + } + if (!webHandled) { + try { // Weld + loader.loadClass("org.jboss.weld.module.web.WeldWebModule"); + webHandled = true; + } catch (final NoClassDefFoundError | ClassNotFoundException e) { + // ok to keep them all + } + } + if (webHandled) { + existingStandardClasses.addAll(asList( + "javax.servlet.http.HttpServletRequest", + "javax.servlet.ServletContext")); + } + beanManager.fireEvent(this); + } + /** * For any {@link AnnotatedType} that includes a {@link Context} injection point, this method replaces * the field with the following code: @@ -149,6 +197,11 @@ public void addResourceProvider(final CdiResourceProvider other) { } else if (CdiBusBean.CXF.equals(event.getBean().getName()) && Bus.class.isAssignableFrom(event.getBean().getBeanClass())) { hasBus = true; + } else if (event.getBean().getQualifiers().contains(DEFAULT)) { + event.getBean().getTypes().stream() + .filter(e -> Object.class != e && InjectionUtils.STANDARD_CONTEXT_CLASSES.contains(e.getTypeName())) + .findFirst() + .ifPresent(type -> existingStandardClasses.add(type.getTypeName())); } } @@ -211,11 +264,16 @@ public void injectBus(@Observes final AfterBeanDiscovery event, final BeanManage beanManager.createInjectionTarget(busAnnotatedType); event.addBean(new CdiBusBean(busInjectionTarget)); } + if (applicationBeans.isEmpty() && !serviceBeans.isEmpty()) { final DefaultApplicationBean applicationBean = new DefaultApplicationBean(); applicationBeans.add(applicationBean); event.addBean(applicationBean); + } else { + // otherwise will be ambiguous since we scanned it with default qualifier already + existingStandardClasses.add(Application.class.getName()); } + // always add the standard context classes InjectionUtils.STANDARD_CONTEXT_CLASSES.stream() .map(this::toClass) @@ -224,7 +282,8 @@ public void injectBus(@Observes final AfterBeanDiscovery event, final BeanManage // add custom contexts contextTypes.addAll(getCustomContextClasses()); // register all of the context types - contextTypes.forEach(t -> event.addBean(new ContextProducerBean(t))); + contextTypes.forEach( + t -> event.addBean(new ContextProducerBean(t, !existingStandardClasses.contains(t.getTypeName())))); } /** @@ -281,8 +340,7 @@ private JAXRSServerFactoryBean createFactoryInstance(final Application applicati * @return JAXRSServerFactoryBean instance */ private JAXRSServerFactoryBean createFactoryInstance(final Application application, final BeanManager beanManager) { - - final JAXRSServerFactoryBean instance = + final JAXRSServerFactoryBean instance = ResourceUtils.createApplication(application, false, false, false, bus); final ClassifiedClasses classified = classes2singletons(application, beanManager); diff --git a/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/AbstractCdiSingleAppTest.java b/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/AbstractCdiSingleAppTest.java index 36eb0dce14a..edc0c5467a8 100644 --- a/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/AbstractCdiSingleAppTest.java +++ b/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/AbstractCdiSingleAppTest.java @@ -35,6 +35,35 @@ import org.junit.Test; public abstract class AbstractCdiSingleAppTest extends AbstractBusClientServerTestBase { + @Test + public void testAvailableInjections() { + assertEquals("configuration=Configuration/" + + "contextResolver=ContextResolver/" + + "cxfApplication=Application/" + + "cxfConfiguration=Configuration/" + + "cxfContextResolver=ContextResolver/" + + "cxfHttpHeaders=HttpHeaders/" + + "cxfHttpServletRequest=HttpServletRequest/" + + "cxfProviders=Providers/" + + "cxfRequest=Request/" + + "cxfResourceContext=ResourceContext/" + + "cxfResourceInfo=ResourceInfo/" + + "cxfSecurityContext=SecurityContext/" + + "cxfServletContext=ServletContext/" + + "cxfUriInfo=UriInfo/" + + "cxfhttpServletResponse=HttpServletRequest/" + + "httpHeaders=HttpHeaders/" + + "httpServletRequest=HttpServletRequest/" + + "httpServletResponse=HttpServletResponse/" + + "providers=Providers/request=Request/" + + "resourceContext=ResourceContext/" + + "resourceInfo=ResourceInfo/" + + "securityContext=SecurityContext/" + + "servletContext=ServletContext/" + + "uriInfo=UriInfo", + createWebClient(getBasePath() + "/injections", MediaType.TEXT_PLAIN).get(String.class).trim()); + } + @Test public void testInjectedVersionIsProperlyReturned() { Response r = createWebClient(getBasePath() + "/version", MediaType.TEXT_PLAIN).get(); diff --git a/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/BookStore.java b/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/BookStore.java index bb458af7e4e..63cbc3ad615 100644 --- a/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/BookStore.java +++ b/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/BookStore.java @@ -39,15 +39,24 @@ private BookStoreService service; private BookStoreVersion bookStoreVersion; private UriInfo uriInfo; + private Injections injections; public BookStore() { } @Inject - public BookStore(BookStoreService service, BookStoreVersion bookStoreVersion, UriInfo uriInfo) { + public BookStore(BookStoreService service, BookStoreVersion bookStoreVersion, UriInfo uriInfo, + Injections injections) { this.service = service; this.bookStoreVersion = bookStoreVersion; this.uriInfo = uriInfo; + this.injections = injections; + } + + @GET + @Path("injections") + public String injections() { + return injections.state(); } @Path("/version") diff --git a/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/Injections.java b/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/Injections.java new file mode 100644 index 00000000000..7e2391cd789 --- /dev/null +++ b/systests/cdi/base/src/main/java/org/apache/cxf/systests/cdi/base/Injections.java @@ -0,0 +1,154 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.systests.cdi.base; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.container.ResourceContext; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Configuration; +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.ContextResolver; +import javax.ws.rs.ext.Providers; + +import org.apache.cxf.cdi.ContextResolved; + +@ApplicationScoped +public class Injections { + /* this one is not supposed to work in the systests + @Inject + private Application application; + */ + + @Inject + @ContextResolved + private Application cxfApplication; //NOPMD + + @Inject + private UriInfo uriInfo; //NOPMD + + @Inject + @ContextResolved + private UriInfo cxfUriInfo; //NOPMD + + @Inject + private HttpHeaders httpHeaders; //NOPMD + + @Inject + @ContextResolved + private HttpHeaders cxfHttpHeaders; //NOPMD + + @Inject + private Request request; //NOPMD + + @Inject + @ContextResolved + private Request cxfRequest; //NOPMD + + @Inject + private SecurityContext securityContext; //NOPMD + + @Inject + @ContextResolved + private SecurityContext cxfSecurityContext; //NOPMD + + @Inject + private Providers providers; //NOPMD + + @Inject + @ContextResolved + private Providers cxfProviders; //NOPMD + + @Inject + private ContextResolver contextResolver; //NOPMD + + @Inject + @ContextResolved + private ContextResolver cxfContextResolver; //NOPMD + + @Inject + private HttpServletRequest httpServletRequest; //NOPMD + + @Inject + @ContextResolved + private HttpServletRequest cxfHttpServletRequest; //NOPMD + + @Inject + private HttpServletResponse httpServletResponse; //NOPMD + + @Inject + @ContextResolved + private HttpServletRequest cxfhttpServletResponse; //NOPMD + + @Inject + private ServletContext servletContext; //NOPMD + + @Inject + @ContextResolved + private ServletContext cxfServletContext; //NOPMD + + @Inject + private ResourceContext resourceContext; //NOPMD + + @Inject + @ContextResolved + private ResourceContext cxfResourceContext; //NOPMD + + @Inject + private ResourceInfo resourceInfo; //NOPMD + + @Inject + @ContextResolved + private ResourceInfo cxfResourceInfo; //NOPMD + + @Inject + private Configuration configuration; //NOPMD + + @Inject + @ContextResolved + private Configuration cxfConfiguration; //NOPMD + + public String state() { + return Stream.of(Injections.class.getDeclaredFields()) + .filter(f -> f.isAnnotationPresent(Inject.class)) + .map(f -> { + if (!f.isAccessible()) { + f.setAccessible(true); + } + try { + // the standard name otherwise not portable + return f.get(Injections.this) != null ? f.getName() + "=" + f.getType().getSimpleName() : ""; + } catch (final IllegalAccessException e) { + return ""; + } + }) + .sorted() // be deterministic in the test, java reflection is no more since java7 + .collect(Collectors.joining("/")); + } +} ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org > Ability to disable certain ContextResolved CDI Beans > ---------------------------------------------------- > > Key: CXF-7643 > URL: https://issues.apache.org/jira/browse/CXF-7643 > Project: CXF > Issue Type: Bug > Components: JAX-RS > Affects Versions: 3.2.2 > Reporter: Romain Manni-Bucau > Priority: Trivial > > ContextProducerBeans are added for all @Context fields. > This is not in the spec so it must use a custom qualifier only and not leak > @Default support for all context types. > Currently it fails with servlet beans which are supported by any CDI@servlet > container and already provided as required by the spec which leads to 1. an > inconsistent bean being deployed 2. an ambiguous resolution. > Side note: this feature can stay as an activable thing but not as a default > for the mentionned reasons. -- This message was sent by Atlassian JIRA (v7.6.3#76005)