From dc939d753a6b097da500b33e7cb615a32c629ff2 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 8 Aug 2019 04:04:07 +0200 Subject: [PATCH] Issue #3804 - Update Decorator integration for various CDI implementations (#3838) * Jetty Issue #3804 WELD-2587 Support CDI integration: + cdi2 module exposes jetty APIs + cdi module uses DecorationListener Signed-off-by: Greg Wilkins * Jetty Issue #3804 WELD-2587 Remove DecoratingListener tests from test-jetty-webapp Signed-off-by: Greg Wilkins * improve CDI test Signed-off-by: Greg Wilkins * Jetty Issue #3804 WELD-2587 Reverted test to use released CDI and cdi2 module for now. To test new mechanism, you need to build the weld snapshot locally, rebuild and switch to cdi module Signed-off-by: Greg Wilkins * remove cdi2 webapp references Signed-off-by: Greg Wilkins * document attribute Signed-off-by: Greg Wilkins * improved documentation Signed-off-by: Greg Wilkins * logging Signed-off-by: Greg Wilkins * improved javadoc Signed-off-by: Greg Wilkins * Fixed version Signed-off-by: Greg Wilkins * Reverted to also provide the DecoratingListener in the decorate module. Renamed cdi-demo to weld-cdi-demo Signed-off-by: Greg Wilkins * revert from Weld SNAPSHOT Signed-off-by: Greg Wilkins * test all 3 weld integrations Signed-off-by: Greg Wilkins * updated destory implementation to release creationalcontext Signed-off-by: Greg Wilkins * reverted to released Weld version Signed-off-by: Greg Wilkins * Issue #3804 CDI integration dispose and release context in destroy Signed-off-by: Greg Wilkins * Improved CDI module documentation Signed-off-by: Greg Wilkins * WIP on OWB Signed-off-by: Greg Wilkins * Updates from review Parameterised CDITests Signed-off-by: Greg Wilkins * share webapp resources for cdi webapp test Signed-off-by: olivier lamy * Initialize OWB with a SCI so that listeners can be decorated Signed-off-by: Greg Wilkins * Added OwbDecorator so that cdi2 module can be tested with OWB Signed-off-by: Greg Wilkins * Lookup attribute name Signed-off-by: Greg Wilkins * Cleanups Signed-off-by: Greg Wilkins * Cleanup from Review Don't do lazy bindings Signed-off-by: Greg Wilkins * Cleanup from Review Treat partial CDI same as no CDI Signed-off-by: Greg Wilkins * fix maven it test no more need of weld-servlet Signed-off-by: olivier lamy * cleanup it parent pom removing non needed weld servlet Signed-off-by: olivier lamy * upgraded to Weld 3.1.2.Final Signed-off-by: Greg Wilkins * Cleanup from Review Signed-off-by: Greg Wilkins * Cleanup from Review Signed-off-by: Greg Wilkins --- .../annotations/AnnotationConfiguration.java | 9 +- jetty-cdi/pom.xml | 28 ++- .../config/etc/{cdi2 => cdi}/jetty-cdi2.xml | 3 +- .../etc/{cdi2 => cdi}/jetty-web-cdi2.xml | 0 jetty-cdi/src/main/config/modules/cdi-spi.mod | 24 +++ jetty-cdi/src/main/config/modules/cdi.mod | 7 +- jetty-cdi/src/main/config/modules/cdi2.mod | 16 +- .../org/eclipse/jetty/cdi/CdiDecorator.java | 165 +++++++++++++++ .../cdi/CdiServletContainerInitializer.java | 60 ++++++ .../javax.servlet.ServletContainerInitializer | 1 + .../src/main/config/etc/jetty-decorate.xml | 18 ++ .../main/config/etc/jetty-web-decorate.xml | 16 ++ .../src/main/config/modules/decorate.mod | 19 ++ jetty-distribution/pom.xml | 19 +- .../demo-base/webapps/ROOT/index.html | 7 +- jetty-home/pom.xml | 4 +- .../src/it/it-parent-pom/pom.xml | 5 - .../src/it/jetty-cdi-run-forked/pom.xml | 4 - .../jetty/util/DecoratedObjectFactory.java | 8 +- .../jetty/webapp/DecoratingListener.java | 196 ++++++++++++++++++ .../eclipse/jetty/webapp/WebAppContext.java | 1 + pom.xml | 2 +- tests/test-distribution/pom.xml | 2 +- .../distribution/DistributionTester.java | 10 + .../jetty/tests/distribution/CDITests.java | 102 ++++----- .../src/test/resources/cdi/demo_context.xml | 23 -- tests/test-webapps/pom.xml | 6 +- .../test-cdi-common-webapp/pom.xml | 43 ++++ .../eclipse/jetty/test/FriendlyGreetings.java | 0 .../org/eclipse/jetty/test/Greetings.java | 0 .../eclipse/jetty/test/GreetingsServlet.java | 4 +- .../org/eclipse/jetty/test/InfoServlet.java | 9 +- .../eclipse/jetty/test/ManifestServerID.java | 0 .../eclipse/jetty/test/MyContextListener.java | 2 + .../org/eclipse/jetty/test/OldGreetings.java | 0 .../java/org/eclipse/jetty/test/ServerID.java | 0 .../eclipse/jetty/test/ServerIDFilter.java | 0 .../src/main/resources/META-INF/beans.xml | 0 .../src/main/webapp/index.html | 7 + .../test-webapps/test-owb-cdi-webapp/pom.xml | 71 +++++++ .../owb/OwbServletContainerInitializer.java | 55 +++++ .../javax.servlet.ServletContainerInitializer | 1 + .../src/main/webapp/WEB-INF/jetty-env.xml | 17 ++ .../src/main/webapp/WEB-INF/jetty-web.xml | 14 ++ .../src/main/webapp/WEB-INF/web.xml | 8 +- .../pom.xml | 21 +- .../src/main/webapp/WEB-INF/jetty-env.xml | 2 +- .../src/main/webapp/WEB-INF/web.xml | 17 ++ 48 files changed, 885 insertions(+), 141 deletions(-) rename jetty-cdi/src/main/config/etc/{cdi2 => cdi}/jetty-cdi2.xml (92%) rename jetty-cdi/src/main/config/etc/{cdi2 => cdi}/jetty-web-cdi2.xml (100%) create mode 100644 jetty-cdi/src/main/config/modules/cdi-spi.mod create mode 100644 jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiDecorator.java create mode 100644 jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiServletContainerInitializer.java create mode 100644 jetty-cdi/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer create mode 100644 jetty-deploy/src/main/config/etc/jetty-decorate.xml create mode 100644 jetty-deploy/src/main/config/etc/jetty-web-decorate.xml create mode 100644 jetty-deploy/src/main/config/modules/decorate.mod create mode 100644 jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DecoratingListener.java delete mode 100644 tests/test-distribution/src/test/resources/cdi/demo_context.xml create mode 100644 tests/test-webapps/test-cdi-common-webapp/pom.xml rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/FriendlyGreetings.java (100%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/Greetings.java (100%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/GreetingsServlet.java (88%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/InfoServlet.java (80%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/ManifestServerID.java (100%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/MyContextListener.java (93%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/OldGreetings.java (100%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/ServerID.java (100%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/java/org/eclipse/jetty/test/ServerIDFilter.java (100%) rename tests/test-webapps/{test-cdi2-webapp => test-cdi-common-webapp}/src/main/resources/META-INF/beans.xml (100%) create mode 100644 tests/test-webapps/test-cdi-common-webapp/src/main/webapp/index.html create mode 100644 tests/test-webapps/test-owb-cdi-webapp/pom.xml create mode 100644 tests/test-webapps/test-owb-cdi-webapp/src/main/java/org/eclipse/jetty/cdi/owb/OwbServletContainerInitializer.java create mode 100644 tests/test-webapps/test-owb-cdi-webapp/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer create mode 100644 tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml create mode 100644 tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-web.xml rename tests/test-webapps/{test-cdi2-webapp => test-owb-cdi-webapp}/src/main/webapp/WEB-INF/web.xml (76%) rename tests/test-webapps/{test-cdi2-webapp => test-weld-cdi-webapp}/pom.xml (61%) rename tests/test-webapps/{test-cdi2-webapp => test-weld-cdi-webapp}/src/main/webapp/WEB-INF/jetty-env.xml (97%) create mode 100644 tests/test-webapps/test-weld-cdi-webapp/src/main/webapp/WEB-INF/web.xml diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java index d3a7d0f11e6..deb4531b1ff 100644 --- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java +++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java @@ -175,11 +175,12 @@ public class AnnotationConfiguration extends AbstractConfiguration /** * ServletContainerInitializerOrdering - * - * A list of classnames of ServletContainerInitializers in the order in which - * they are to be called back. One name only in the list can be "*", which is a + *

Applies an ordering to the {@link ServletContainerInitializer}s for the context, using + * the value of the "org.eclipse.jetty.containerInitializerOrder" context attribute. + * The attribute value is a list of classnames of ServletContainerInitializers in the order in which + * they are to be called. One name only in the list can be "*", which is a * wildcard which matches any other ServletContainerInitializer name not already - * matched. + * matched.

*/ public class ServletContainerInitializerOrdering { diff --git a/jetty-cdi/pom.xml b/jetty-cdi/pom.xml index 1459c105665..243de5e8b75 100644 --- a/jetty-cdi/pom.xml +++ b/jetty-cdi/pom.xml @@ -5,14 +5,34 @@ 9.4.20-SNAPSHOT 4.0.0 - org.eclipse.jetty.cdi - cdi-2 - Jetty :: CDI 2 + org.eclipse.jetty + jetty-cdi + Jetty :: CDI http://www.eclipse.org/jetty jar - ${project.groupId}.cdi2 + ${project.groupId}.cdi + + + org.eclipse.jetty + jetty-util + ${project.version} + compile + + + org.eclipse.jetty + jetty-webapp + ${project.version} + compile + + + org.eclipse.jetty + jetty-annotations + ${project.version} + compile + + diff --git a/jetty-cdi/src/main/config/etc/cdi2/jetty-cdi2.xml b/jetty-cdi/src/main/config/etc/cdi/jetty-cdi2.xml similarity index 92% rename from jetty-cdi/src/main/config/etc/cdi2/jetty-cdi2.xml rename to jetty-cdi/src/main/config/etc/cdi/jetty-cdi2.xml index c427fb1b184..3dfde45c87a 100644 --- a/jetty-cdi/src/main/config/etc/cdi2/jetty-cdi2.xml +++ b/jetty-cdi/src/main/config/etc/cdi/jetty-cdi2.xml @@ -7,7 +7,8 @@ - /etc/cdi2/jetty-web-cdi2.xml + /etc/cdi/jetty-web-cdi2.xml + diff --git a/jetty-cdi/src/main/config/etc/cdi2/jetty-web-cdi2.xml b/jetty-cdi/src/main/config/etc/cdi/jetty-web-cdi2.xml similarity index 100% rename from jetty-cdi/src/main/config/etc/cdi2/jetty-web-cdi2.xml rename to jetty-cdi/src/main/config/etc/cdi/jetty-web-cdi2.xml diff --git a/jetty-cdi/src/main/config/modules/cdi-spi.mod b/jetty-cdi/src/main/config/modules/cdi-spi.mod new file mode 100644 index 00000000000..437b4f2fcc1 --- /dev/null +++ b/jetty-cdi/src/main/config/modules/cdi-spi.mod @@ -0,0 +1,24 @@ +# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html + +[description] +CDI SPI integration for CDI inside the webapp. +This module does not provide CDI, but configures jetty to look for the CDI SPI within +a webapp. If the CDI SPI is found, then a CdiDecorator will be registered to +decorate Listeners, Filters and Servlets using the standard CDI SPI. +The module indicates to the webapp that this mechanism is available by setting the +"org.eclipse.jetty.cdi" context attribute to "CdiDecorator". +This is the preferred integration for OWB. + +[tag] +cdi + +[depend] +deploy + +[lib] +lib/jetty-cdi-${jetty.version}.jar +lib/apache-jsp/org.mortbay.jasper.apache-el-*.jar + +[ini] +jetty.webapp.addSystemClasses+=,org.eclipse.jetty.cdi.CdiServletContainerInitializer +jetty.webapp.addServerClasses+=,-org.eclipse.jetty.cdi.CdiServletContainerInitializer \ No newline at end of file diff --git a/jetty-cdi/src/main/config/modules/cdi.mod b/jetty-cdi/src/main/config/modules/cdi.mod index 749aafe4ff6..94264564a95 100644 --- a/jetty-cdi/src/main/config/modules/cdi.mod +++ b/jetty-cdi/src/main/config/modules/cdi.mod @@ -1,7 +1,10 @@ # DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html [description] -Jetty setup to support Weld/CDI2 with WELD inside the webapp +Deprecated CDI module. Current depends on cdi-spi. + +[tag] +cdi [depend] -cdi2 +cdi-spi \ No newline at end of file diff --git a/jetty-cdi/src/main/config/modules/cdi2.mod b/jetty-cdi/src/main/config/modules/cdi2.mod index 2284de8abec..48defeb252b 100644 --- a/jetty-cdi/src/main/config/modules/cdi2.mod +++ b/jetty-cdi/src/main/config/modules/cdi2.mod @@ -1,7 +1,14 @@ # DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html [description] -Jetty setup to support Weld/CDI2 with WELD inside the webapp +Deprecated support for CDI integrations inside the webapp. +This module does not provide CDI, but configures jetty so that a CDI implementation +can enable itself as a decorator for Filters, Servlets and Listeners. +This modules uses the deprecated technique of exposing private Jetty decorate APIs to the CDI +implementation in the webapp. + +[tag] +cdi [depend] deploy @@ -10,9 +17,4 @@ deploy lib/apache-jsp/org.mortbay.jasper.apache-el-*.jar [xml] -etc/cdi2/jetty-cdi2.xml - -[license] -Weld is an open source project hosted on Github and released under the Apache 2.0 license. -http://weld.cdi-spec.org/ -http://www.apache.org/licenses/LICENSE-2.0.html +etc/cdi/jetty-cdi2.xml diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiDecorator.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiDecorator.java new file mode 100644 index 00000000000..80f07f8bf42 --- /dev/null +++ b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiDecorator.java @@ -0,0 +1,165 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.cdi; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.Decorator; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/** + * A Decorator invokes a CDI provider within + * a webapplication to decorate objects created by the contexts {@link org.eclipse.jetty.util.DecoratedObjectFactory} + * (typically Listeners, Filters and Servlets). + * The CDI provide is invoked using {@link MethodHandle}s to avoid any CDI instance or dependencies within the server scope. + * The code invoked is equivalent to: + *
+ * public <T> T decorate(T o)
+ * {
+ *   BeanManager manager = CDI.current().getBeanManager();
+ *   manager.createInjectionTarget(manager.createAnnotatedType((Class<T>)o.getClass()))
+ *     .inject(o,manager.createCreationalContext(null));
+ *   return o;
+ * }
+ * 
+ */ +public class CdiDecorator implements Decorator +{ + private static final Logger LOG = Log.getLogger(CdiServletContainerInitializer.class); + + private final ServletContextHandler _context; + private final Map _decorated = new HashMap<>(); + + private final MethodHandle _current; + private final MethodHandle _getBeanManager; + private final MethodHandle _createAnnotatedType; + private final MethodHandle _createInjectionTarget; + private final MethodHandle _createCreationalContext; + private final MethodHandle _inject; + private final MethodHandle _dispose; + private final MethodHandle _release; + + public CdiDecorator(ServletContextHandler context) throws UnsupportedOperationException + { + _context = context; + ClassLoader classLoader = _context.getClassLoader(); + + try + { + Class cdiClass = classLoader.loadClass("javax.enterprise.inject.spi.CDI"); + Class beanManagerClass = classLoader.loadClass("javax.enterprise.inject.spi.BeanManager"); + Class annotatedTypeClass = classLoader.loadClass("javax.enterprise.inject.spi.AnnotatedType"); + Class injectionTargetClass = classLoader.loadClass("javax.enterprise.inject.spi.InjectionTarget"); + Class creationalContextClass = classLoader.loadClass("javax.enterprise.context.spi.CreationalContext"); + Class contextualClass = classLoader.loadClass("javax.enterprise.context.spi.Contextual"); + + MethodHandles.Lookup lookup = MethodHandles.lookup(); + _current = lookup.findStatic(cdiClass, "current", MethodType.methodType(cdiClass)); + _getBeanManager = lookup.findVirtual(cdiClass, "getBeanManager", MethodType.methodType(beanManagerClass)); + _createAnnotatedType = lookup.findVirtual(beanManagerClass, "createAnnotatedType", MethodType.methodType(annotatedTypeClass, Class.class)); + _createInjectionTarget = lookup.findVirtual(beanManagerClass, "createInjectionTarget", MethodType.methodType(injectionTargetClass, annotatedTypeClass)); + _createCreationalContext = lookup.findVirtual(beanManagerClass, "createCreationalContext", MethodType.methodType(creationalContextClass, contextualClass)); + _inject = lookup.findVirtual(injectionTargetClass, "inject", MethodType.methodType(Void.TYPE, Object.class, creationalContextClass)); + _dispose = lookup.findVirtual(injectionTargetClass, "dispose", MethodType.methodType(Void.TYPE, Object.class)); + _release = lookup.findVirtual(creationalContextClass, "release", MethodType.methodType(Void.TYPE)); + } + catch (Exception e) + { + throw new UnsupportedOperationException(e); + } + } + + /** + * Decorate an object. + *

The signature of this method must match what is introspected for by the + * Jetty DecoratingListener class. It is invoked dynamically.

+ * + * @param o The object to be decorated + * @param The type of the object to be decorated + * @return The decorated object + */ + public T decorate(T o) + { + try + { + if (LOG.isDebugEnabled()) + LOG.debug("decorate {} in {}", o, _context); + + _decorated.put(o, new Decorated(o)); + } + catch (Throwable th) + { + LOG.warn("Unable to decorate " + o, th); + } + return o; + } + + /** + * Destroy a decorated object. + *

The signature of this method must match what is introspected for by the + * Jetty DecoratingListener class. It is invoked dynamically.

+ * + * @param o The object to be destroyed + */ + public void destroy(Object o) + { + try + { + Decorated decorated = _decorated.remove(o); + if (decorated != null) + decorated.destroy(o); + } + catch (Throwable th) + { + LOG.warn("Unable to destroy " + o, th); + } + } + + private class Decorated + { + private final Object _injectionTarget; + private final Object _creationalContext; + + Decorated(Object o) throws Throwable + { + // BeanManager manager = CDI.current().getBeanManager(); + Object manager = _getBeanManager.invoke(_current.invoke()); + // AnnotatedType annotatedType = manager.createAnnotatedType((Class)o.getClass()); + Object annotatedType = _createAnnotatedType.invoke(manager, o.getClass()); + // CreationalContext creationalContext = manager.createCreationalContext(null); + _creationalContext = _createCreationalContext.invoke(manager, null); + // InjectionTarget injectionTarget = manager.createInjectionTarget(); + _injectionTarget = _createInjectionTarget.invoke(manager, annotatedType); + // injectionTarget.inject(o, creationalContext); + _inject.invoke(_injectionTarget, o, _creationalContext); + } + + public void destroy(Object o) throws Throwable + { + _dispose.invoke(_injectionTarget, o); + _release.invoke(_creationalContext); + } + } +} diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiServletContainerInitializer.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiServletContainerInitializer.java new file mode 100644 index 00000000000..acf3846a60d --- /dev/null +++ b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiServletContainerInitializer.java @@ -0,0 +1,60 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.cdi; + +import java.util.Objects; +import java.util.Set; +import javax.servlet.ServletContainerInitializer; +import javax.servlet.ServletContext; + +import org.eclipse.jetty.annotations.AnnotationConfiguration; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/** + * A {@link ServletContainerInitializer} that introspects for a CDI API + * implementation within a web application. If the CDI API is found, then + * a {@link CdiDecorator} is registered as a {@link org.eclipse.jetty.util.Decorator} + * for the context. + * @see AnnotationConfiguration.ServletContainerInitializerOrdering + */ +public class CdiServletContainerInitializer implements ServletContainerInitializer +{ + public static final String CDI_INTEGRATION_ATTRIBUTE = "org.eclipse.jetty.cdi"; + private static final Logger LOG = Log.getLogger(CdiServletContainerInitializer.class); + + @Override + public void onStartup(Set> c, ServletContext ctx) + { + try + { + ServletContextHandler context = ServletContextHandler.getServletContextHandler(ctx); + Objects.requireNonNull(context); + context.getObjectFactory().addDecorator(new CdiDecorator(context)); + context.setAttribute(CDI_INTEGRATION_ATTRIBUTE, "CdiDecorator"); + LOG.info("CdiDecorator enabled in " + ctx); + } + catch (UnsupportedOperationException e) + { + if (LOG.isDebugEnabled()) + LOG.debug("CDI not found in " + ctx, e); + } + } +} diff --git a/jetty-cdi/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer b/jetty-cdi/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer new file mode 100644 index 00000000000..4e6d2237721 --- /dev/null +++ b/jetty-cdi/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer @@ -0,0 +1 @@ +org.eclipse.jetty.cdi.CdiServletContainerInitializer diff --git a/jetty-deploy/src/main/config/etc/jetty-decorate.xml b/jetty-deploy/src/main/config/etc/jetty-decorate.xml new file mode 100644 index 00000000000..9bbeba9f394 --- /dev/null +++ b/jetty-deploy/src/main/config/etc/jetty-decorate.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + /etc/jetty-web-decorate.xml + + + + + + + diff --git a/jetty-deploy/src/main/config/etc/jetty-web-decorate.xml b/jetty-deploy/src/main/config/etc/jetty-web-decorate.xml new file mode 100644 index 00000000000..f91048c4b73 --- /dev/null +++ b/jetty-deploy/src/main/config/etc/jetty-web-decorate.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/jetty-deploy/src/main/config/modules/decorate.mod b/jetty-deploy/src/main/config/modules/decorate.mod new file mode 100644 index 00000000000..c24bc28ed9a --- /dev/null +++ b/jetty-deploy/src/main/config/modules/decorate.mod @@ -0,0 +1,19 @@ +# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html + +[description] +Jetty setup to support Decoration of Listeners, Filters and Servlets within a deployed +webapp (as used by some CDI integrations). +This module uses the DecoratingListener to register an object set as a context attribute +as a dynamic decorator. This module sets the "org.eclipse.jetty.webapp.DecoratingListener" +context attribute with the name of the context attribute that will be listened to. +By default the attribute is "org.eclipse.jetty.webapp.decorator". +This is the preferred integration for Weld >= 3.1.2 + +[tag] +cdi + +[depend] +deploy + +[xml] +etc/jetty-decorate.xml diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml index ca10fe789c7..9fb86a50673 100644 --- a/jetty-distribution/pom.xml +++ b/jetty-distribution/pom.xml @@ -140,6 +140,16 @@ ${assembly-directory}/demo-base/webapps async-rest.war + + org.eclipse.jetty.tests + test-weld-cdi-webapp + ${project.version} + war + true + ** + ${assembly-directory}/demo-base/webapps + test-weld-cdi.war + @@ -348,7 +358,7 @@ jetty.home=${assembly-directory} jetty.base=${assembly-directory}/demo-base - --add-to-startd=server,continuation,deploy,websocket,ext,resources,client,annotations,jndi,servlets,jsp,jstl,http,https,threadpool + --add-to-startd=server,continuation,deploy,websocket,ext,resources,client,annotations,cdi2,decorate,jndi,servlets,jsp,jstl,http,https,threadpool @@ -449,6 +459,13 @@ war true + + org.eclipse.jetty.tests + test-weld-cdi-webapp + ${project.version} + war + true + org.eclipse.jetty jetty-documentation diff --git a/jetty-distribution/src/main/resources/demo-base/webapps/ROOT/index.html b/jetty-distribution/src/main/resources/demo-base/webapps/ROOT/index.html index 1091c20b040..8d7d4254a71 100644 --- a/jetty-distribution/src/main/resources/demo-base/webapps/ROOT/index.html +++ b/jetty-distribution/src/main/resources/demo-base/webapps/ROOT/index.html @@ -30,13 +30,14 @@ diff --git a/jetty-home/pom.xml b/jetty-home/pom.xml index 471e67c431b..a1052962b2b 100644 --- a/jetty-home/pom.xml +++ b/jetty-home/pom.xml @@ -677,8 +677,8 @@ jboss-logging - org.eclipse.jetty.cdi - cdi-2 + org.eclipse.jetty + jetty-cdi ${project.version} diff --git a/jetty-maven-plugin/src/it/it-parent-pom/pom.xml b/jetty-maven-plugin/src/it/it-parent-pom/pom.xml index e18e1028903..06bf3d62cdd 100644 --- a/jetty-maven-plugin/src/it/it-parent-pom/pom.xml +++ b/jetty-maven-plugin/src/it/it-parent-pom/pom.xml @@ -30,11 +30,6 @@ @javax.servlet.api.version@ provided - - org.jboss.weld.servlet - weld-servlet - @weld.version@ - org.eclipse.jetty.toolchain jetty-perf-helper diff --git a/jetty-maven-plugin/src/it/jetty-cdi-run-forked/pom.xml b/jetty-maven-plugin/src/it/jetty-cdi-run-forked/pom.xml index f7ab4a128e6..77a6976ca96 100644 --- a/jetty-maven-plugin/src/it/jetty-cdi-run-forked/pom.xml +++ b/jetty-maven-plugin/src/it/jetty-cdi-run-forked/pom.xml @@ -18,10 +18,6 @@ - - org.jboss.weld.servlet - weld-servlet - javax.servlet javax.servlet-api diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/DecoratedObjectFactory.java b/jetty-util/src/main/java/org/eclipse/jetty/util/DecoratedObjectFactory.java index d2c0db2b2b6..ef4f326005a 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/DecoratedObjectFactory.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/DecoratedObjectFactory.java @@ -51,7 +51,13 @@ public class DecoratedObjectFactory implements Iterable public void addDecorator(Decorator decorator) { LOG.debug("Adding Decorator: {}", decorator); - this.decorators.add(decorator); + decorators.add(decorator); + } + + public boolean removeDecorator(Decorator decorator) + { + LOG.debug("Remove Decorator: {}", decorator); + return decorators.remove(decorator); } public void clear() diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DecoratingListener.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DecoratingListener.java new file mode 100644 index 00000000000..4b2bb1c21cf --- /dev/null +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DecoratingListener.java @@ -0,0 +1,196 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.webapp; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Objects; +import javax.servlet.ServletContextAttributeEvent; +import javax.servlet.ServletContextAttributeListener; + +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.Decorator; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/** + * A ServletContextAttributeListener that listens for a specific context + * attribute (default "org.eclipse.jetty.webapp.decorator") to obtain a + * decorator instance from the webapp. The instance is then either coerced + * to a Decorator or reflected for decorator compatible methods so it can + * be added to the {@link WebAppContext#getObjectFactory()} as a + * {@link Decorator}. + * The context attribute "org.eclipse.jetty.webapp.DecoratingListener" if + * not set, is set to the name of the attribute this listener listens for. + */ +public class DecoratingListener implements ServletContextAttributeListener +{ + public static final String DECORATOR_ATTRIBUTE = "org.eclipse.jetty.webapp.decorator"; + private static final Logger LOG = Log.getLogger(DecoratingListener.class); + private static final MethodType DECORATE_TYPE; + private static final MethodType DESTROY_TYPE; + + static + { + try + { + DECORATE_TYPE = MethodType.methodType(Object.class, Object.class); + DESTROY_TYPE = MethodType.methodType(Void.TYPE, Object.class); + + // Check we have the right MethodTypes for the current Decorator signatures + MethodHandles.Lookup lookup = MethodHandles.lookup(); + lookup.findVirtual(Decorator.class, "decorate", DECORATE_TYPE); + lookup.findVirtual(Decorator.class, "destroy", DESTROY_TYPE); + } + catch (Exception e) + { + throw new IllegalStateException(e); + } + } + + private final ServletContextHandler _context; + private final String _attributeName; + private Decorator _decorator; + + public DecoratingListener() + { + this((String)null); + } + + public DecoratingListener(String attributeName) + { + this(WebAppContext.getCurrentWebAppContext(), attributeName); + } + + public DecoratingListener(ServletContextHandler context) + { + this(context, null); + } + + public DecoratingListener(ServletContextHandler context, String attributeName) + { + _context = context; + Objects.requireNonNull(_context); + _attributeName = attributeName == null ? DECORATOR_ATTRIBUTE : attributeName; + checkAndSetAttribute(); + Object decorator = _context.getAttribute(_attributeName); + if (decorator != null) + _context.getObjectFactory().addDecorator(asDecorator(decorator)); + } + + protected void checkAndSetAttribute() + { + // If not set (by another DecoratingListener), flag the attribute that are + // listening for. If more than one DecoratingListener is used then this + // attribute reflects only the first. + if (_context.getAttribute(getClass().getName()) != null) + throw new IllegalStateException("Multiple DecoratingListeners detected"); + _context.setAttribute(getClass().getName(), _attributeName); + } + + private Decorator asDecorator(Object object) + { + if (object == null) + return null; + if (object instanceof Decorator) + return (Decorator)object; + + try + { + Class clazz = object.getClass(); + + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodHandle decorate = lookup.findVirtual(clazz, "decorate", DECORATE_TYPE); + MethodHandle destroy = lookup.findVirtual(clazz, "destroy", DESTROY_TYPE); + return new DynamicDecorator(decorate, destroy, object); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + + @Override + public void attributeAdded(ServletContextAttributeEvent event) + { + if (_attributeName.equals(event.getName())) + { + _decorator = asDecorator(event.getValue()); + _context.getObjectFactory().addDecorator(_decorator); + } + } + + @Override + public void attributeRemoved(ServletContextAttributeEvent event) + { + if (_attributeName.equals(event.getName()) && _decorator != null) + { + _context.getObjectFactory().removeDecorator(_decorator); + _decorator = null; + } + } + + @Override + public void attributeReplaced(ServletContextAttributeEvent event) + { + attributeRemoved(event); + attributeAdded(event); + } + + private static class DynamicDecorator implements Decorator + { + private final MethodHandle _decorate; + private final MethodHandle _destroy; + private final Object _object; + + private DynamicDecorator(MethodHandle decorate, MethodHandle destroy, Object object) + { + _decorate = decorate; + _destroy = destroy; + _object = object; + } + + @Override + public T decorate(T o) + { + try + { + return (T)_decorate.invoke(_object, o); + } + catch (Throwable t) + { + throw new RuntimeException(t); + } + } + + @Override + public void destroy(Object o) + { + try + { + _destroy.invoke(_object, o); + } + catch (Throwable t) + { + throw new RuntimeException(t); + } + } + } +} diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java index 81ba215386f..a0189a01906 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java @@ -1040,6 +1040,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL new DumpableCollection("Configurations " + name, _configurations), new DumpableCollection("Handler attributes " + name, ((AttributesMap)getAttributes()).getAttributeEntrySet()), new DumpableCollection("Context attributes " + name, getServletContext().getAttributeEntrySet()), + new DumpableCollection("EventListeners " + this, Arrays.asList(getEventListeners())), new DumpableCollection("Initparams " + name, getInitParams().entrySet()) ); } diff --git a/pom.xml b/pom.xml index 84b8f1ba903..b314c0e6916 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ 3.6.0 1.3.1 3.1.0 - 2.4.5.Final + 3.1.2.Final 1.0.5 diff --git a/tests/test-distribution/pom.xml b/tests/test-distribution/pom.xml index 1340f5dc3ca..a59812bccd5 100644 --- a/tests/test-distribution/pom.xml +++ b/tests/test-distribution/pom.xml @@ -76,7 +76,7 @@ org.eclipse.jetty.tests - test-cdi2-webapp + test-weld-cdi-webapp ${project.version} war test diff --git a/tests/test-distribution/src/main/java/org/eclipse/jetty/tests/distribution/DistributionTester.java b/tests/test-distribution/src/main/java/org/eclipse/jetty/tests/distribution/DistributionTester.java index c7c4c84a537..2b9178e20b1 100644 --- a/tests/test-distribution/src/main/java/org/eclipse/jetty/tests/distribution/DistributionTester.java +++ b/tests/test-distribution/src/main/java/org/eclipse/jetty/tests/distribution/DistributionTester.java @@ -127,6 +127,16 @@ public class DistributionTester return start(Arrays.asList(args)); } + public Path getJettyBase() + { + return config.jettyBase; + } + + public Path getJettyHome() + { + return config.jettyHome; + } + /** * Start the distribution with the arguments * diff --git a/tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/CDITests.java b/tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/CDITests.java index 7a2c594d8dd..2e73f8a0230 100644 --- a/tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/CDITests.java +++ b/tests/test-distribution/src/test/java/org/eclipse/jetty/tests/distribution/CDITests.java @@ -19,11 +19,20 @@ package org.eclipse.jetty.tests.distribution; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.stream.Stream; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.http.HttpStatus; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -32,70 +41,40 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class CDITests extends AbstractDistributionTest { - /** - * Tests a WAR file that is CDI complete as it includes the weld - * library in its WEB-INF/lib directory. - */ - @Test - public void testCDI2_IncludedInWebapp() throws Exception + // Tests from here use these parameters + public static Stream tests() { - String jettyVersion = System.getProperty("jettyVersion"); - DistributionTester distribution = DistributionTester.Builder.newInstance() - .jettyVersion(jettyVersion) - .mavenLocalRepository(System.getProperty("mavenRepoPath")) - .build(); - - String[] args1 = { - "--create-startd", - "--approve-all-licenses", - "--add-to-start=http,deploy,annotations,jsp" - }; - try (DistributionTester.Run run1 = distribution.start(args1)) + Consumer removeJettyWebXml = d -> { - assertTrue(run1.awaitFor(5, TimeUnit.SECONDS)); - assertEquals(0, run1.getExitValue()); - - File war = distribution.resolveArtifact("org.eclipse.jetty.tests:test-cdi2-webapp:war:" + jettyVersion); - distribution.installWarFile(war, "demo"); - - distribution.installBaseResource("cdi/demo_context.xml", "webapps/demo.xml"); - - int port = distribution.freePort(); - try (DistributionTester.Run run2 = distribution.start("jetty.http.port=" + port)) + try { - assertTrue(run2.awaitConsoleLogsFor("Started @", 10, TimeUnit.SECONDS)); - - startHttpClient(); - ContentResponse response = client.GET("http://localhost:" + port + "/demo/greetings"); - assertEquals(HttpStatus.OK_200, response.getStatus()); - // Confirm Servlet based CDI - assertThat(response.getContentAsString(), containsString("Hello GreetingsServlet")); - // Confirm Listener based CDI (this has been a problem in the past, keep this for regression testing!) - assertThat(response.getHeaders().get("Server"), containsString("CDI-Demo-org.eclipse.jetty.test")); - - run2.stop(); - assertTrue(run2.awaitFor(5, TimeUnit.SECONDS)); + Path jettyWebXml = d.getJettyBase().resolve("webapps/demo/WEB-INF/jetty-web.xml"); + Files.deleteIfExists(jettyWebXml); } - } + catch(IOException e) + { + throw new RuntimeException(e); + } + }; + + List tests = new ArrayList<>(); + + tests.add(new Object[]{"weld", "cdi-spi", null}); // Requires Weld >= 3.1.2 + tests.add(new Object[]{"weld", "cdi2", null}); + tests.add(new Object[]{"weld", "decorate", null}); // Requires Weld >= 3.1.2 + tests.add(new Object[]{"owb", "cdi-spi", removeJettyWebXml}); + tests.add(new Object[]{"owb", "cdi2", null}); + // tests.add(new Object[]{"owb", "decorate", null}); // Will not be supported + return tests.stream().map(Arguments::of); } /** - * Tests a WAR file that is expects CDI to be configured by the server. - * - *

- * This means the WAR has the weld libs in its - * WEB-INF/lib directory. - *

- * - *

- * The expectation is that a context xml deployable file is not - * required when using this `cdi2` module, and the appropriate - * server side libs are made available to allow weld to function. - * (the required server side javax.el support comes from the cdi2 module) - *

+ * Tests a WAR file that includes the CDI + * library in its WEB-INF/lib directory. */ - @Test - public void testCDI2_ConfiguredByServer() throws Exception + @ParameterizedTest + @MethodSource("tests") + public void testCDIIncludedInWebapp(String implementation, String integration, Consumer configure) throws Exception { String jettyVersion = System.getProperty("jettyVersion"); DistributionTester distribution = DistributionTester.Builder.newInstance() @@ -106,18 +85,17 @@ public class CDITests extends AbstractDistributionTest String[] args1 = { "--create-startd", "--approve-all-licenses", - // standard entries - "--add-to-start=http,deploy,annotations", - // cdi2 specific entry (should transitively pull in what it needs, the user should not be expected to know the transitive entries) - "--add-to-start=cdi2" + "--add-to-start=http,deploy,annotations,jsp,"+integration }; try (DistributionTester.Run run1 = distribution.start(args1)) { assertTrue(run1.awaitFor(5, TimeUnit.SECONDS)); assertEquals(0, run1.getExitValue()); - File war = distribution.resolveArtifact("org.eclipse.jetty.tests:test-cdi2-webapp:war:" + jettyVersion); + File war = distribution.resolveArtifact("org.eclipse.jetty.tests:test-" + implementation + "-cdi-webapp:war:" + jettyVersion); distribution.installWarFile(war, "demo"); + if (configure != null) + configure.accept(distribution); int port = distribution.freePort(); try (DistributionTester.Run run2 = distribution.start("jetty.http.port=" + port)) diff --git a/tests/test-distribution/src/test/resources/cdi/demo_context.xml b/tests/test-distribution/src/test/resources/cdi/demo_context.xml deleted file mode 100644 index 342daf0b5ca..00000000000 --- a/tests/test-distribution/src/test/resources/cdi/demo_context.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - /demo - /demo/ - - - -org.eclipse.jetty.util.Decorator - - - -org.eclipse.jetty.util.DecoratedObjectFactory - - - -org.eclipse.jetty.server.handler.ContextHandler. - - - -org.eclipse.jetty.server.handler.ContextHandler - - - -org.eclipse.jetty.servlet.ServletContextHandler - - - diff --git a/tests/test-webapps/pom.xml b/tests/test-webapps/pom.xml index e43bc6c6e44..64ed61d165c 100644 --- a/tests/test-webapps/pom.xml +++ b/tests/test-webapps/pom.xml @@ -41,6 +41,8 @@ test-http2-webapp test-simple-webapp test-felix-webapp - test-cdi2-webapp + test-cdi-common-webapp + test-weld-cdi-webapp + test-owb-cdi-webapp - \ No newline at end of file + diff --git a/tests/test-webapps/test-cdi-common-webapp/pom.xml b/tests/test-webapps/test-cdi-common-webapp/pom.xml new file mode 100644 index 00000000000..227d6da57e1 --- /dev/null +++ b/tests/test-webapps/test-cdi-common-webapp/pom.xml @@ -0,0 +1,43 @@ + + + + org.eclipse.jetty.tests + test-webapps-parent + 9.4.20-SNAPSHOT + + + 4.0.0 + test-cdi-common-webapp + Test :: CDI :: Common Demo Webapp + war + + + ${project.groupId}.cdi.common + + + + + + + javax.servlet + javax.servlet-api + provided + + + + javax.inject + javax.inject + 1 + provided + + + + javax.enterprise + cdi-api + 1.2 + provided + + + + + diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/FriendlyGreetings.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/FriendlyGreetings.java similarity index 100% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/FriendlyGreetings.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/FriendlyGreetings.java diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/Greetings.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/Greetings.java similarity index 100% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/Greetings.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/Greetings.java diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/GreetingsServlet.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/GreetingsServlet.java similarity index 88% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/GreetingsServlet.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/GreetingsServlet.java index 773ea5092d1..aac21e78783 100644 --- a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/GreetingsServlet.java +++ b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/GreetingsServlet.java @@ -37,6 +37,8 @@ public class GreetingsServlet extends HttpServlet protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/plain"); - resp.getWriter().println("[" + greetings.getGreeting() + "]"); + resp.getWriter().print(greetings.getGreeting()); + resp.getWriter().print(" from "); + resp.getWriter().println(getServletContext().getAttribute("ServerID")); } } diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/InfoServlet.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/InfoServlet.java similarity index 80% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/InfoServlet.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/InfoServlet.java index 7809857744e..98b7a527487 100644 --- a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/InfoServlet.java +++ b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/InfoServlet.java @@ -21,8 +21,11 @@ package org.eclipse.jetty.test; import java.io.IOException; import java.io.PrintWriter; import java.util.Set; +import javax.enterprise.inject.Any; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.enterprise.util.AnnotationLiteral; import javax.inject.Inject; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; @@ -43,10 +46,12 @@ public class InfoServlet extends HttpServlet PrintWriter out = resp.getWriter(); out.println("Bean Manager: " + beanManager); - Set> beans = beanManager.getBeans(""); + Set> beans = beanManager.getBeans(Object.class, new AnnotationLiteral() {}); for (Bean bean : beans) { - out.println(" " + bean); + out.printf("%16s => %s%n", bean.getName(), bean); + for (InjectionPoint ij : bean.getInjectionPoints()) + out.printf("%16s -> %s%n", "", ij); } } } diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/ManifestServerID.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/ManifestServerID.java similarity index 100% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/ManifestServerID.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/ManifestServerID.java diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/MyContextListener.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/MyContextListener.java similarity index 93% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/MyContextListener.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/MyContextListener.java index ead2931610f..7ba9973ad2d 100644 --- a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/MyContextListener.java +++ b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/MyContextListener.java @@ -32,6 +32,8 @@ public class MyContextListener implements ServletContextListener @Override public void contextInitialized(ServletContextEvent sce) { + if (serverId == null) + throw new IllegalStateException("CDI did not inject!"); sce.getServletContext().setAttribute("ServerID", serverId.get()); } diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/OldGreetings.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/OldGreetings.java similarity index 100% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/OldGreetings.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/OldGreetings.java diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/ServerID.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/ServerID.java similarity index 100% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/ServerID.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/ServerID.java diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/ServerIDFilter.java b/tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/ServerIDFilter.java similarity index 100% rename from tests/test-webapps/test-cdi2-webapp/src/main/java/org/eclipse/jetty/test/ServerIDFilter.java rename to tests/test-webapps/test-cdi-common-webapp/src/main/java/org/eclipse/jetty/test/ServerIDFilter.java diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/resources/META-INF/beans.xml b/tests/test-webapps/test-cdi-common-webapp/src/main/resources/META-INF/beans.xml similarity index 100% rename from tests/test-webapps/test-cdi2-webapp/src/main/resources/META-INF/beans.xml rename to tests/test-webapps/test-cdi-common-webapp/src/main/resources/META-INF/beans.xml diff --git a/tests/test-webapps/test-cdi-common-webapp/src/main/webapp/index.html b/tests/test-webapps/test-cdi-common-webapp/src/main/webapp/index.html new file mode 100644 index 00000000000..9beca9836d8 --- /dev/null +++ b/tests/test-webapps/test-cdi-common-webapp/src/main/webapp/index.html @@ -0,0 +1,7 @@ +

OWB CDI Test Webapp

+ +

CDI Info

+ + +

Greetings test

+ \ No newline at end of file diff --git a/tests/test-webapps/test-owb-cdi-webapp/pom.xml b/tests/test-webapps/test-owb-cdi-webapp/pom.xml new file mode 100644 index 00000000000..c81c088d78c --- /dev/null +++ b/tests/test-webapps/test-owb-cdi-webapp/pom.xml @@ -0,0 +1,71 @@ + + + + org.eclipse.jetty.tests + test-webapps-parent + 9.4.20-SNAPSHOT + + + 4.0.0 + test-owb-cdi-webapp + Test :: CDI On Jetty :: OWB Demo Webapp + war + + + ${project.groupId}.cdi.owb + + + + weld-owb-demo + + + + + + javax.servlet + javax.servlet-api + provided + + + + org.eclipse.jetty.tests + test-cdi-common-webapp + ${project.version} + war + runtime + + + + + org.apache.geronimo.specs + geronimo-annotation_1.3_spec + 1.1 + + + org.apache.geronimo.specs + geronimo-jcdi_2.0_spec + 1.1 + + + org.apache.geronimo.specs + geronimo-atinject_1.0_spec + 1.1 + + + org.apache.geronimo.specs + geronimo-interceptor_1.2_spec + 1.1 + + + org.apache.openwebbeans + openwebbeans-web + + 2.0.11 + + + org.apache.openwebbeans + openwebbeans-jetty9 + 2.0.11 + + + diff --git a/tests/test-webapps/test-owb-cdi-webapp/src/main/java/org/eclipse/jetty/cdi/owb/OwbServletContainerInitializer.java b/tests/test-webapps/test-owb-cdi-webapp/src/main/java/org/eclipse/jetty/cdi/owb/OwbServletContainerInitializer.java new file mode 100644 index 00000000000..03081b79f6e --- /dev/null +++ b/tests/test-webapps/test-owb-cdi-webapp/src/main/java/org/eclipse/jetty/cdi/owb/OwbServletContainerInitializer.java @@ -0,0 +1,55 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.cdi.owb; + +import java.util.Set; +import javax.servlet.ServletContainerInitializer; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletException; + +import org.apache.webbeans.servlet.WebBeansConfigurationListener; + +/** + * @deprecated This class will not be required once https://issues.apache.org/jira/browse/OWB-1296 is available + */ +@Deprecated +public class OwbServletContainerInitializer implements ServletContainerInitializer +{ + @Override + public void onStartup(Set> c, ServletContext ctx) throws ServletException + { + Listener listener = new Listener(); + listener.preInitialize(new ServletContextEvent(ctx)); + ctx.addListener(listener); + } + + public static class Listener extends WebBeansConfigurationListener + { + void preInitialize(ServletContextEvent event) + { + super.contextInitialized(event); + } + + @Override + public void contextInitialized(ServletContextEvent event) + { + } + } +} diff --git a/tests/test-webapps/test-owb-cdi-webapp/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer b/tests/test-webapps/test-owb-cdi-webapp/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer new file mode 100644 index 00000000000..f164a18c5a8 --- /dev/null +++ b/tests/test-webapps/test-owb-cdi-webapp/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer @@ -0,0 +1 @@ +org.eclipse.jetty.cdi.owb.OwbServletContainerInitializer \ No newline at end of file diff --git a/tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml b/tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml new file mode 100644 index 00000000000..d852f0d887f --- /dev/null +++ b/tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml @@ -0,0 +1,17 @@ + + + + + + + + BeanManager + + + javax.enterprise.inject.spi.BeanManager + org.apache.webbeans.container.ManagerObjectFactory + + + + + \ No newline at end of file diff --git a/tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-web.xml b/tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-web.xml new file mode 100644 index 00000000000..404e1bc09dc --- /dev/null +++ b/tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/jetty-web.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/webapp/WEB-INF/web.xml b/tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/web.xml similarity index 76% rename from tests/test-webapps/test-cdi2-webapp/src/main/webapp/WEB-INF/web.xml rename to tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/web.xml index 1665f2146c7..79a39c5b9d4 100644 --- a/tests/test-webapps/test-cdi2-webapp/src/main/webapp/WEB-INF/web.xml +++ b/tests/test-webapps/test-owb-cdi-webapp/src/main/webapp/WEB-INF/web.xml @@ -3,11 +3,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> - CDI Integration Test WebApp - - - org.jboss.weld.environment.servlet.Listener - + OWB CDI Integration Test WebApp + + Object factory for the CDI Bean Manager diff --git a/tests/test-webapps/test-cdi2-webapp/pom.xml b/tests/test-webapps/test-weld-cdi-webapp/pom.xml similarity index 61% rename from tests/test-webapps/test-cdi2-webapp/pom.xml rename to tests/test-webapps/test-weld-cdi-webapp/pom.xml index 4c8decbd2bf..e6098fac1d5 100644 --- a/tests/test-webapps/test-cdi2-webapp/pom.xml +++ b/tests/test-webapps/test-weld-cdi-webapp/pom.xml @@ -7,29 +7,32 @@ 4.0.0 - test-cdi2-webapp - Test :: CDI2 On Jetty :: Included in WebApp + test-weld-cdi-webapp + Test :: CDI On Jetty :: Weld Demo Webapp war - ${project.groupId}.cdi2.webapp + ${project.groupId}.cdi.weld - cdi2-demo + weld-cdi-demo - + - javax.servlet - javax.servlet-api - provided + org.eclipse.jetty.tests + test-cdi-common-webapp + ${project.version} + war + runtime + org.jboss.weld.servlet - weld-servlet + weld-servlet-core ${weld.version} diff --git a/tests/test-webapps/test-cdi2-webapp/src/main/webapp/WEB-INF/jetty-env.xml b/tests/test-webapps/test-weld-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml similarity index 97% rename from tests/test-webapps/test-cdi2-webapp/src/main/webapp/WEB-INF/jetty-env.xml rename to tests/test-webapps/test-weld-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml index 2add52456a7..052d8458189 100644 --- a/tests/test-webapps/test-cdi2-webapp/src/main/webapp/WEB-INF/jetty-env.xml +++ b/tests/test-webapps/test-weld-cdi-webapp/src/main/webapp/WEB-INF/jetty-env.xml @@ -14,4 +14,4 @@ - \ No newline at end of file + diff --git a/tests/test-webapps/test-weld-cdi-webapp/src/main/webapp/WEB-INF/web.xml b/tests/test-webapps/test-weld-cdi-webapp/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..f622db81989 --- /dev/null +++ b/tests/test-webapps/test-weld-cdi-webapp/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,17 @@ + + + Weld CDI Integration Test WebApp + + + org.jboss.weld.environment.servlet.Listener + + + + Object factory for the CDI Bean Manager + BeanManager + javax.enterprise.inject.spi.BeanManager + +
-

examples ...

+

tests ...