Author: rmannibucau
Date: Thu Jun 26 17:14:54 2014
New Revision: 1605858
URL: http://svn.apache.org/r1605858
Log:
TOMEE-1260 cdi constructor injections for JAXRS CDI endpoints
Added:
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/cdi/
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/cdi/JAXRSContextExtension.java
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/resources/META-INF/services/
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiConstructorInjectionTest.java
Modified:
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBPerRequestPojoResourceProvider.java
Modified:
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBPerRequestPojoResourceProvider.java
URL:
http://svn.apache.org/viewvc/tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBPerRequestPojoResourceProvider.java?rev=1605858&r1=1605857&r2=1605858&view=diff
==============================================================================
---
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBPerRequestPojoResourceProvider.java
(original)
+++
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/OpenEJBPerRequestPojoResourceProvider.java
Thu Jun 26 17:14:54 2014
@@ -72,9 +72,7 @@ public class OpenEJBPerRequestPojoResour
context = (Context) Proxy.newProxyInstance(classLoader, new
Class<?>[]{Context.class}, new InitialContextWrapper(initialContext));
constructor = ResourceUtils.findResourceConstructor(clazz, true);
- if (constructor == null) {
- throw new RuntimeException("Resource class " + clazz + " has no
valid constructor");
- }
+
postConstructMethod = ResourceUtils.findPostConstructMethod(clazz);
preDestroyMethod = ResourceUtils.findPreDestroyMethod(clazz);
@@ -117,15 +115,24 @@ public class OpenEJBPerRequestPojoResour
normalScopeCreator = new
ProvidedInstanceBeanCreator(bm.getReference(bean, bean.getBeanClass(),
bm.createCreationalContext(bean)));
} else {
normalScopeCreator = null;
+ validateConstructorExists(clazz);
}
} else {
bean = null;
normalScopeCreator = null;
+ validateConstructorExists(clazz);
}
Contexts.findContextFields(clazz, contextTypes); // for the class
itself
}
+ private void validateConstructorExists(final Class<?> clazz) {
+ // only validate it here otherwise we'll fail for CDI injections
+ if (constructor == null) {
+ throw new RuntimeException("Resource class " + clazz + " has no
valid constructor");
+ }
+ }
+
@Override
public Object getInstance(final Message m) {
Contexts.bind(m.getExchange(), contextTypes);
Added:
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/cdi/JAXRSContextExtension.java
URL:
http://svn.apache.org/viewvc/tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/cdi/JAXRSContextExtension.java?rev=1605858&view=auto
==============================================================================
---
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/cdi/JAXRSContextExtension.java
(added)
+++
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/cdi/JAXRSContextExtension.java
Thu Jun 26 17:14:54 2014
@@ -0,0 +1,173 @@
+/*
+ * 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.openejb.server.cxf.rs.cdi;
+
+import static java.util.Arrays.asList;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.BeforeBeanDiscovery;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Context;
+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.openejb.rest.AbstractRestThreadLocalProxy;
+import org.apache.openejb.rest.ThreadLocalContextManager;
+import org.apache.webbeans.annotation.AnyLiteral;
+import org.apache.webbeans.annotation.EmptyAnnotationLiteral;
+
+public class JAXRSContextExtension implements Extension {
+ public static class ContextLiteral extends EmptyAnnotationLiteral<Context>
implements Context {
+ private static final long serialVersionUID = 1L;
+
+ public static final AnnotationLiteral<Context> INSTANCE = new
ContextLiteral();
+ }
+
+ void addContextAsQualifier(final @Observes BeforeBeanDiscovery bbd) {
+ bbd.addQualifier(Context.class);
+ }
+
+ void addContextInstances(final @Observes AfterBeanDiscovery abd, final
BeanManager bm) {
+ abd.addBean(new ContextBean<SecurityContext>(SecurityContext.class,
ThreadLocalContextManager.SECURITY_CONTEXT));
+ abd.addBean(new ContextBean<UriInfo>(UriInfo.class,
ThreadLocalContextManager.URI_INFO));
+ abd.addBean(new
ContextBean<HttpServletRequest>(HttpServletRequest.class,
ThreadLocalContextManager.HTTP_SERVLET_REQUEST));
+ abd.addBean(new
ContextBean<HttpServletResponse>(HttpServletResponse.class,
ThreadLocalContextManager.HTTP_SERVLET_RESPONSE));
+ abd.addBean(new ContextBean<HttpHeaders>(HttpHeaders.class,
ThreadLocalContextManager.HTTP_HEADERS));
+ abd.addBean(new ContextBean<Request>(Request.class,
ThreadLocalContextManager.REQUEST));
+ abd.addBean(new ContextBean<ServletRequest>(ServletRequest.class,
ThreadLocalContextManager.SERVLET_REQUEST));
+ abd.addBean(new ContextBean<ServletContext>(ServletContext.class,
ThreadLocalContextManager.SERVLET_CONTEXT));
+ abd.addBean(new ContextBean<ServletConfig>(ServletConfig.class,
ThreadLocalContextManager.SERVLET_CONFIG));
+ abd.addBean(new ContextBean<Providers>(Providers.class,
ThreadLocalContextManager.PROVIDERS));
+ abd.addBean(new ContextBean<ContextResolver>(ContextResolver.class,
ThreadLocalContextManager.CONTEXT_RESOLVER));
+ }
+
+ public static class ContextBean<T> implements Bean<T> {
+ private final Class<T> type;
+ private final Set<Type> types;
+ private final Set<Annotation> qualifiers;
+ private final T proxy;
+
+ public ContextBean(final Class<T> type, final
AbstractRestThreadLocalProxy<T> proxy) {
+ this.type = type;
+ this.proxy =
+ (T)
Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new
Class<?>[] { type, Serializable.class },
+ new DelegateHandler(proxy));
+ this.types = new HashSet<Type>(asList(Object.class, type));
+ this.qualifiers = new
HashSet<Annotation>(asList(ContextLiteral.INSTANCE, AnyLiteral.INSTANCE));
+ }
+
+ @Override
+ public Set<Type> getTypes() {
+ return types;
+ }
+
+ @Override
+ public Set<Annotation> getQualifiers() {
+ return qualifiers;
+ }
+
+ @Override
+ public Class<? extends Annotation> getScope() {
+ return ApplicationScoped.class;
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return Collections.<InjectionPoint>emptySet();
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return type;
+ }
+
+ @Override
+ public Set<Class<? extends Annotation>> getStereotypes() {
+ return Collections.<Class<? extends Annotation>>emptySet();
+ }
+
+ @Override
+ public boolean isAlternative() {
+ return false;
+ }
+
+ @Override
+ public T create(final CreationalContext<T> tCreationalContext) {
+ return proxy;
+ }
+
+ @Override
+ public void destroy(final T t, final CreationalContext<T>
tCreationalContext) {
+ // no-op
+ }
+ }
+
+ private static class DelegateHandler<T> implements InvocationHandler {
+ private final AbstractRestThreadLocalProxy<T> proxy;
+
+ public DelegateHandler(final AbstractRestThreadLocalProxy<T> proxy) {
+ this.proxy = proxy;
+ }
+
+ @Override
+ public Object invoke(final Object ignored, final Method method, final
Object[] args) throws Throwable {
+ try {
+ return method.invoke(proxy.get(), args);
+ }
+ catch (final InvocationTargetException ite) {
+ throw ite.getCause();
+ }
+ }
+ }
+}
Added:
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
URL:
http://svn.apache.org/viewvc/tomee/tomee/trunk/server/openejb-cxf-rs/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension?rev=1605858&view=auto
==============================================================================
---
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
(added)
+++
tomee/tomee/trunk/server/openejb-cxf-rs/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
Thu Jun 26 17:14:54 2014
@@ -0,0 +1 @@
+org.apache.openejb.server.cxf.rs.cdi.JAXRSContextExtension
Added:
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiConstructorInjectionTest.java
URL:
http://svn.apache.org/viewvc/tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiConstructorInjectionTest.java?rev=1605858&view=auto
==============================================================================
---
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiConstructorInjectionTest.java
(added)
+++
tomee/tomee/trunk/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/CdiConstructorInjectionTest.java
Thu Jun 26 17:14:54 2014
@@ -0,0 +1,113 @@
+/*
+ * 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.openejb.server.cxf.rs;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.Context;
+
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.openejb.jee.WebApp;
+import org.apache.openejb.junit.ApplicationComposer;
+import org.apache.openejb.testing.Classes;
+import org.apache.openejb.testing.EnableServices;
+import org.apache.openejb.testing.Module;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@EnableServices("jax-rs")
+@RunWith(ApplicationComposer.class)
+public class CdiConstructorInjectionTest {
+ @Module
+ @Classes(value = { FullCDI.class, Service.class, CDIAndContext.class },
cdi = true)
+ public WebApp war() {
+ return new WebApp()
+ .contextRoot("app")
+ .addServlet("REST Application", Application.class.getName())
+ .addInitParam("REST Application", "javax.ws.rs.Application",
ConstructorApplication.class.getName());
+ }
+
+ @Test
+ public void standardCDI() {
+ assertEquals("service",
WebClient.create("http://localhost:4204/app").path("/foo").get(String.class));
+ }
+
+ @Test
+ public void cdiAndContext() {
+ assertEquals("GET",
WebClient.create("http://localhost:4204/app").path("/bar").get(String.class));
+ }
+
+ public static class Service {
+ public String bar() {
+ return "service";
+ }
+ }
+
+ @Path("/bar")
+ public static class CDIAndContext {
+ private final HttpServletRequest request;
+
+ @Inject
+ public CDIAndContext(final @Context HttpServletRequest request) {
+ this.request = request;
+ }
+
+ @GET
+ public String servletPath() {
+ return request.getMethod();
+ }
+ }
+
+ @Path("/foo")
+ @ApplicationScoped
+ public static class FullCDI {
+ private final Service service;
+
+ public FullCDI() {
+ this(null);
+ }
+
+ @Inject
+ public FullCDI(final Service service) {
+ this.service = service;
+ }
+
+ @GET
+ public String bar() {
+ return service.bar();
+ }
+ }
+
+ public static class ConstructorApplication extends Application {
+ @Override
+ public Set<Class<?>> getClasses() {
+ final Set<Class<?>> classes = new HashSet<Class<?>>();
+ classes.add(FullCDI.class);
+ classes.add(CDIAndContext.class);
+ return classes;
+ }
+ }
+}