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:
[email protected]
With regards,
Apache Git Services