Author: rmannibucau
Date: Tue Jun 6 21:20:51 2017
New Revision: 1797826
URL: http://svn.apache.org/viewvc?rev=1797826&view=rev
Log:
MEECROWAVE-37 fixing @Context for fields in cdi proxies
Added:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXRSFieldInjectionInterceptor.java
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java
- copied, changed from r1797825,
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveBeansExtension.java
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/ContextInProxiedInstancesTest.java
Removed:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveBeansExtension.java
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/InstanceCustomizerTest.java
Added:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXRSFieldInjectionInterceptor.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXRSFieldInjectionInterceptor.java?rev=1797826&view=auto
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXRSFieldInjectionInterceptor.java
(added)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/cxf/JAXRSFieldInjectionInterceptor.java
Tue Jun 6 21:20:51 2017
@@ -0,0 +1,108 @@
+/**
+ * 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.meecrowave.cxf;
+
+import org.apache.cxf.jaxrs.model.ApplicationInfo;
+import org.apache.cxf.jaxrs.model.OperationResourceInfoStack;
+import org.apache.cxf.jaxrs.utils.InjectionUtils;
+import org.apache.cxf.jaxrs.utils.JAXRSUtils;
+import org.apache.cxf.message.Message;
+import org.apache.webbeans.annotation.EmptyAnnotationLiteral;
+import org.apache.webbeans.intercept.ConstructorInterceptorInvocationContext;
+
+import javax.annotation.Priority;
+import javax.interceptor.AroundConstruct;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InterceptorBinding;
+import javax.interceptor.InvocationContext;
+import javax.ws.rs.core.Application;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Interceptor
+@Priority(Interceptor.Priority.PLATFORM_BEFORE)
[email protected]
+public class JAXRSFieldInjectionInterceptor implements Serializable {
+ private final AtomicBoolean injected = new AtomicBoolean();
+
+ @AroundConstruct
+ public Object injectContexts(final InvocationContext ic) throws Exception {
+ doInject(ic);
+ return ic.proceed();
+ }
+
+ @AroundInvoke
+ public Object lazyInjectContexts(final InvocationContext ic) throws
Exception {
+ if (!injected.get()) {
+ doInject(ic);
+ }
+ return ic.proceed();
+ }
+
+ private void doInject(final InvocationContext ic) throws Exception {
+ final Message current = JAXRSUtils.getCurrentMessage();
+ if (current != null) {
+ final OperationResourceInfoStack stack =
OperationResourceInfoStack.class.cast(current.get(OperationResourceInfoStack.class.getName()));
+ if (stack != null && !stack.isEmpty()) {
+ final Object instance;
+ if
(ConstructorInterceptorInvocationContext.class.isInstance(ic)) {
+ final ConstructorInterceptorInvocationContext
constructorInterceptorInvocationContext =
ConstructorInterceptorInvocationContext.class.cast(ic);
+ constructorInterceptorInvocationContext.directProceed();
+ instance =
constructorInterceptorInvocationContext.getNewInstance();
+ } else {
+ instance = ic.getTarget();
+ }
+ Application application = null;
+ final Object appInfo =
current.getExchange().getEndpoint().get(Application.class.getName());
+ if (ApplicationInfo.class.isInstance(appInfo)) {
+ application =
ApplicationInfo.class.cast(appInfo).getProvider();
+ }
+ synchronized (this) {
+ if (injected.get()) {
+ return;
+ }
+ InjectionUtils.injectContextProxiesAndApplication(
+
stack.lastElement().getMethodInfo().getClassResourceInfo(),
+ instance,
+ application);
+ injected.compareAndSet(false, true);
+ }
+ }
+ }
+ }
+
+ @Target(TYPE)
+ @Retention(RUNTIME)
+ @InterceptorBinding
+ public @interface Binding {
+ Annotation INSTANCE = new EmptyAnnotationLiteral<Binding>() {
+ @Override
+ public Class<? extends Annotation> annotationType() {
+ return Binding.class;
+ }
+ };
+ }
+}
Copied:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java
(from r1797825,
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveBeansExtension.java)
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java?p2=openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java&p1=openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveBeansExtension.java&r1=1797825&r2=1797826&rev=1797826&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveBeansExtension.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/MeecrowaveExtension.java
Tue Jun 6 21:20:51 2017
@@ -18,17 +18,59 @@
*/
package org.apache.meecrowave.openwebbeans;
+import org.apache.meecrowave.cxf.JAXRSFieldInjectionInterceptor;
import org.apache.meecrowave.cxf.MeecrowaveBus;
+import org.apache.webbeans.container.AnnotatedTypeWrapper;
import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.ws.rs.Path;
+import java.lang.annotation.Annotation;
+import java.util.HashSet;
+import java.util.Set;
import java.util.stream.Stream;
-public class MeecrowaveBeansExtension implements Extension {
+public class MeecrowaveExtension implements Extension {
void addBeansFromJava(@Observes final BeforeBeanDiscovery bbd, final
BeanManager bm) {
// stream not really needed but here for the pattern in case we need
other beans
Stream.of(MeecrowaveBus.class).forEach(type ->
bbd.addAnnotatedType(bm.createAnnotatedType(type)));
}
+
+ void enableContextFieldInjectionWorks(@Observes final
ProcessAnnotatedType<?> pat, final BeanManager bm) {
+ final AnnotatedType<?> at = pat.getAnnotatedType();
+ if (at.isAnnotationPresent(Path.class) &&
!at.isAnnotationPresent(JAXRSFieldInjectionInterceptor.Binding.class)
+ && at.getAnnotations().stream().anyMatch(a ->
bm.isNormalScope(a.annotationType()))) {
+ pat.setAnnotatedType(new JAXRSFIeldInjectionAT(this, at));
+ }
+ }
+
+ private static class JAXRSFIeldInjectionAT<T> extends
AnnotatedTypeWrapper<T> {
+ private final Set<Annotation> annotations;
+
+ private JAXRSFIeldInjectionAT(final Extension extension, final
AnnotatedType<T> original) {
+ super(extension, original);
+ this.annotations = new HashSet<>(original.getAnnotations().size()
+ 1);
+ this.annotations.addAll(original.getAnnotations());
+
this.annotations.add(JAXRSFieldInjectionInterceptor.Binding.INSTANCE);
+ }
+
+ @Override
+ public Set<Annotation> getAnnotations() {
+ return annotations;
+ }
+
+ @Override
+ public <T1 extends Annotation> T1 getAnnotation(final Class<T1>
t1Class) {
+ return t1Class == JAXRSFieldInjectionInterceptor.Binding.class ?
t1Class.cast(JAXRSFieldInjectionInterceptor.Binding.INSTANCE) :
super.getAnnotation(t1Class);
+ }
+
+ @Override
+ public boolean isAnnotationPresent(final Class<? extends Annotation>
aClass) {
+ return JAXRSFieldInjectionInterceptor.Binding.class == aClass ||
super.isAnnotationPresent(aClass);
+ }
+ }
}
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java?rev=1797826&r1=1797825&r2=1797826&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/java/org/apache/meecrowave/openwebbeans/OWBAutoSetup.java
Tue Jun 6 21:20:51 2017
@@ -19,15 +19,19 @@
package org.apache.meecrowave.openwebbeans;
import org.apache.meecrowave.Meecrowave;
+import org.apache.meecrowave.cxf.JAXRSFieldInjectionInterceptor;
import org.apache.webbeans.annotation.AnyLiteral;
import org.apache.webbeans.annotation.DefaultLiteral;
import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.container.BeanManagerImpl;
+import org.apache.webbeans.intercept.InterceptorsManager;
import org.apache.webbeans.servlet.WebBeansConfigurationListener;
import org.apache.webbeans.web.context.WebConversationFilter;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
@@ -59,7 +63,7 @@ public class OWBAutoSetup implements Ser
ctx.addListener(bootListener);
}
- public static class EagerBootListener extends
WebBeansConfigurationListener {
+ public static class EagerBootListener extends
WebBeansConfigurationListener implements Extension {
private final Meecrowave.Builder config;
private EagerBootListener(final Meecrowave.Builder builder) {
@@ -73,13 +77,24 @@ public class OWBAutoSetup implements Ser
private void doContextInitialized(final ServletContextEvent event) {
try {
-
WebBeansContext.getInstance().getBeanManagerImpl().addInternalBean(new
ConfigBean(config));
+ final WebBeansContext instance = WebBeansContext.getInstance();
+ customizeContext(instance);
} catch (final IllegalStateException ise) {
// lifecycle not supporting it
}
super.contextInitialized(event);
}
+ private void customizeContext(final WebBeansContext instance) {
+ final BeanManagerImpl beanManager = instance.getBeanManagerImpl();
+ final InterceptorsManager interceptorsManager =
instance.getInterceptorsManager();
+
+ beanManager.addInternalBean(new ConfigBean(config));
+
+
interceptorsManager.addInterceptorBindingType(JAXRSFieldInjectionInterceptor.Binding.class);
+ beanManager.addAdditionalAnnotatedType(this,
beanManager.createAnnotatedType(JAXRSFieldInjectionInterceptor.class));
+ }
+
private static class ConfigBean implements Bean<Meecrowave.Builder> {
private final Meecrowave.Builder value;
private final Set<Type> types = new
HashSet<>(asList(Meecrowave.Builder.class, Object.class));
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension?rev=1797826&r1=1797825&r2=1797826&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
Tue Jun 6 21:20:51 2017
@@ -1 +1 @@
-org.apache.meecrowave.openwebbeans.MeecrowaveBeansExtension
+org.apache.meecrowave.openwebbeans.MeecrowaveExtension
Added:
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/ContextInProxiedInstancesTest.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/ContextInProxiedInstancesTest.java?rev=1797826&view=auto
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/ContextInProxiedInstancesTest.java
(added)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/ContextInProxiedInstancesTest.java
Tue Jun 6 21:20:51 2017
@@ -0,0 +1,101 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.meecrowave;
+
+import org.apache.tomcat.util.http.fileupload.util.Streams;
+import org.junit.Test;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.Initialized;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.CDI;
+import javax.servlet.ServletContext;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import static org.junit.Assert.assertEquals;
+
+public class ContextInProxiedInstancesTest {
+ @Test
+ public void fields() throws IOException {
+ try (final Meecrowave meecrowave = new Meecrowave(new
Meecrowave.Builder()
+ .randomHttpPort()
+
.includePackages(ContextInProxiedInstancesTest.class.getName())).bake()) {
+ // proxies can use @Context
+ try (final InputStream stream = new URL("http://localhost:" +
meecrowave.getConfiguration().getHttpPort() + "/app").openStream()) {
+ assertEquals("app", Streams.asString(stream, "UTF-8"));
+ }
+ try (final InputStream stream = new URL("http://localhost:" +
meecrowave.getConfiguration().getHttpPort() + "/req").openStream()) {
+ assertEquals("req", Streams.asString(stream, "UTF-8"));
+ }
+ // not proxied can also
+ try (final InputStream stream = new URL("http://localhost:" +
meecrowave.getConfiguration().getHttpPort() + "/dep").openStream()) {
+ assertEquals("dep", Streams.asString(stream, "UTF-8"));
+ }
+ assertEquals(Dep.class,
CDI.current().select(Dep.class).get().getClass()); // ensure it is not proxied
but injection works (thanks CXF)
+ }
+ }
+
+ @Path("app")
+ @ApplicationScoped
+ public static class App {
+ @Context
+ private UriInfo uri;
+
+ public void init(@Observes @Initialized(ApplicationScoped.class) final
ServletContext sc) {
+ // init without a Message
+ }
+
+ @GET
+ public String get() {
+ return uri.getPath();
+ }
+ }
+
+ @Path("req")
+ @RequestScoped
+ public static class Req {
+ @Context
+ private UriInfo uri;
+
+ @GET
+ public String get() {
+ return uri.getPath();
+ }
+ }
+
+ @Path("dep")
+ @Dependent
+ public static class Dep {
+ @Context
+ private UriInfo uri;
+
+ @GET
+ public String get() {
+ return uri.getPath();
+ }
+ }
+}
Modified:
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/InstanceCustomizerTest.java
URL:
http://svn.apache.org/viewvc/openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/InstanceCustomizerTest.java?rev=1797826&r1=1797825&r2=1797826&view=diff
==============================================================================
---
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/InstanceCustomizerTest.java
(original)
+++
openwebbeans/meecrowave/trunk/meecrowave-core/src/test/java/org/apache/meecrowave/InstanceCustomizerTest.java
Tue Jun 6 21:20:51 2017
@@ -35,6 +35,7 @@ public class InstanceCustomizerTest {
@Test
public void instanceCustomizer() throws IOException {
try (final Meecrowave meecrowave = new Meecrowave(new
Meecrowave.Builder()
+ .randomHttpPort()
.instanceCustomizer(t ->
t.getHost().getPipeline().addValve(new ValveBase() {
@Override
public void invoke(final Request request, final Response
response) throws IOException, ServletException {