From 7ecf42e3f8b99a18ca87cc2894effaeb7552b627 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 7 Sep 2020 14:00:20 +0200 Subject: [PATCH] Issue #5162 CDI embedded integration improvements (#5177) * Issue #5162 CDI embedded integration improvements Clean up CDI integration and documentation to better support embedded usage. + made listener public + added utility class for SCIs * Issue #5162 CDI embedded integration improvements Clean up CDI integration and documentation to better support embedded usage. + moved EmbeddedWeldTest to jetty-embedded * fix javadoc Signed-off-by: Greg Wilkins * Issue #5162 CDI embedded integration improvements ventilated text * fix test pom Signed-off-by: Greg Wilkins * Fixed javadoc * Fixed javadoc * Issue #5162 CDI embedded integration improvements Moved tests to jetty-cdi to avoid consequences to other tests in embedded * trailing new line Signed-off-by: Greg Wilkins * updates from review Signed-off-by: Greg Wilkins * Feedback from review --- jetty-cdi/pom.xml | 6 + .../jetty/cdi/CdiDecoratingListener.java | 3 +- .../cdi/CdiServletContainerInitializer.java | 2 - .../eclipse/jetty/cdi/CdiSpiDecorator.java | 59 +++- .../jetty/embedded/EmbeddedWeldTest.java | 332 ++++++++++++++++++ .../src/test/resources/META-INF/beans.xml | 4 + .../asciidoc/development/frameworks/cdi.adoc | 119 +++++++ .../development/frameworks/chapter.adoc | 3 +- .../asciidoc/development/frameworks/weld.adoc | 225 +++++++----- .../plus/annotation/ContainerInitializer.java | 4 - .../jetty/servlet/ServletContextHandler.java | 65 +++- .../jetty/util/component/Container.java | 10 +- .../util/component/ContainerLifeCycle.java | 10 - .../jetty/tests/distribution/CDITests.java | 2 +- .../src/main/resources/META-INF/beans.xml | 2 +- 15 files changed, 716 insertions(+), 130 deletions(-) create mode 100644 jetty-cdi/src/test/java/org/eclipse/jetty/embedded/EmbeddedWeldTest.java create mode 100644 jetty-cdi/src/test/resources/META-INF/beans.xml create mode 100644 jetty-documentation/src/main/asciidoc/development/frameworks/cdi.adoc diff --git a/jetty-cdi/pom.xml b/jetty-cdi/pom.xml index c06cc91e72a9..f1dd8a4b8a19 100644 --- a/jetty-cdi/pom.xml +++ b/jetty-cdi/pom.xml @@ -32,6 +32,12 @@ ${project.version} compile + + org.jboss.weld.servlet + weld-servlet-core + ${weld.version} + test + diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiDecoratingListener.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiDecoratingListener.java index 674591b8d80e..dbdafb889275 100644 --- a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiDecoratingListener.java +++ b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiDecoratingListener.java @@ -24,7 +24,7 @@ /** * A DecoratingListener that listens for "org.eclipse.jetty.cdi.decorator" */ -class CdiDecoratingListener extends DecoratingListener +public class CdiDecoratingListener extends DecoratingListener { public static final String MODE = "CdiDecoratingListener"; public static final String ATTRIBUTE = "org.eclipse.jetty.cdi.decorator"; @@ -32,5 +32,6 @@ class CdiDecoratingListener extends DecoratingListener public CdiDecoratingListener(ServletContextHandler contextHandler) { super(contextHandler, ATTRIBUTE); + contextHandler.setAttribute(CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, MODE); } } 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 index ef99c3aa3587..3a72a740525e 100644 --- a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiServletContainerInitializer.java +++ b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiServletContainerInitializer.java @@ -86,8 +86,6 @@ public void onStartup(Set> c, ServletContext ctx) default: throw new IllegalStateException(mode); } - - context.setAttribute(CDI_INTEGRATION_ATTRIBUTE, mode); LOG.info(mode + " enabled in " + ctx); } catch (UnsupportedOperationException | ClassNotFoundException e) diff --git a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiSpiDecorator.java b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiSpiDecorator.java index 4198a49407d8..413eacaf50bd 100644 --- a/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiSpiDecorator.java +++ b/jetty-cdi/src/main/java/org/eclipse/jetty/cdi/CdiSpiDecorator.java @@ -21,8 +21,12 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.util.Decorator; @@ -61,11 +65,15 @@ public class CdiSpiDecorator implements Decorator private final MethodHandle _inject; private final MethodHandle _dispose; private final MethodHandle _release; + private final Set _undecorated = new HashSet<>(Collections.singletonList("org.jboss.weld.environment.servlet.Listener")); public CdiSpiDecorator(ServletContextHandler context) throws UnsupportedOperationException { _context = context; + context.setAttribute(CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, MODE); ClassLoader classLoader = _context.getClassLoader(); + if (classLoader == null) + classLoader = this.getClass().getClassLoader(); try { @@ -92,6 +100,54 @@ public CdiSpiDecorator(ServletContextHandler context) throws UnsupportedOperatio } } + /** + * Test if a class can be decorated. + * The default implementation checks the set from {@link #getUndecoratable()} + * on the class and all it's super classes. + * @param clazz The class to check + * @return True if the class and all it's super classes can be decorated + */ + protected boolean isDecoratable(Class clazz) + { + if (Object.class == clazz) + return true; + if (getUndecoratable().contains(clazz.getName())) + return false; + return isDecoratable(clazz.getSuperclass()); + } + + /** + * Get the set of classes that will not be decorated. The default set includes the listener from Weld that will itself + * setup decoration. + * @return The modifiable set of class names that will not be decorated (ie {@link #isDecoratable(Class)} will return false. + * @see #isDecoratable(Class) + */ + public Set getUndecoratable() + { + return _undecorated; + } + + /** + * @param classnames The set of class names that will not be decorated. + * @see #isDecoratable(Class) + */ + public void setUndecoratable(Set classnames) + { + _undecorated.clear(); + if (classnames != null) + _undecorated.addAll(classnames); + } + + /** + * @param classname A class name that will be added to the undecoratable classes set. + * @see #getUndecoratable() + * @see #isDecoratable(Class) + */ + public void addUndecoratable(String... classname) + { + _undecorated.addAll(Arrays.asList()); + } + /** * Decorate an object. *

The signature of this method must match what is introspected for by the @@ -108,7 +164,8 @@ public T decorate(T o) if (LOG.isDebugEnabled()) LOG.debug("decorate {} in {}", o, _context); - _decorated.put(o, new Decorated(o)); + if (isDecoratable(o.getClass())) + _decorated.put(o, new Decorated(o)); } catch (Throwable th) { diff --git a/jetty-cdi/src/test/java/org/eclipse/jetty/embedded/EmbeddedWeldTest.java b/jetty-cdi/src/test/java/org/eclipse/jetty/embedded/EmbeddedWeldTest.java new file mode 100644 index 000000000000..5c2dc1a1ba22 --- /dev/null +++ b/jetty-cdi/src/test/java/org/eclipse/jetty/embedded/EmbeddedWeldTest.java @@ -0,0 +1,332 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// ------------------------------------------------------------------------ +// 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.embedded; + +import java.io.IOException; +import java.util.EnumSet; +import javax.enterprise.inject.Produces; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.InjectionPoint; +import javax.inject.Inject; +import javax.inject.Named; +import javax.servlet.DispatcherType; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.annotations.AnnotationConfiguration; +import org.eclipse.jetty.cdi.CdiServletContainerInitializer; +import org.eclipse.jetty.server.LocalConnector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ListenerHolder; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.webapp.Configuration; +import org.eclipse.jetty.webapp.JettyWebXmlConfiguration; +import org.eclipse.jetty.webapp.WebAppContext; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; + +public class EmbeddedWeldTest +{ + public static Server createServerWithServletContext(String mode) + { + Server server = new Server(); + server.addConnector(new LocalConnector(server)); + ServletContextHandler context = new ServletContextHandler(); + context.setContextPath("/"); + context.setResourceBase("src/test/resources/weldtest"); + server.setHandler(context); + + // Setup context + context.addFilter(MyFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + context.addServlet(GreetingsServlet.class, "/"); + context.getServletHandler().addListener(new ListenerHolder(MyContextListener.class)); + + // Setup Jetty weld integration + switch (mode) + { + case "none" : // Do nothing, let weld work it out. + // Expect:INFO: WELD-ENV-001201: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported. + context.getServletHandler().addListener(new ListenerHolder(org.jboss.weld.environment.servlet.Listener.class)); + break; + + case "DecoratingListener+Listener": + // Expect:INFO: WELD-ENV-001212: Jetty CdiDecoratingListener support detected, CDI injection will be available in Listeners, Servlets and Filters. + context.addEventListener(new org.eclipse.jetty.webapp.DecoratingListener(context)); + context.getServletHandler().addListener(new ListenerHolder(org.jboss.weld.environment.servlet.Listener.class)); + break; + + case "CdiDecoratingListener+Listener": + // Expect:INFO: WELD-ENV-001212: Jetty CdiDecoratingListener support detected, CDI injection will be available in Listeners, Servlets and Filters. + context.addEventListener(new org.eclipse.jetty.cdi.CdiDecoratingListener(context)); + context.addEventListener(new org.jboss.weld.environment.servlet.Listener()); + break; + + case "CdiSpiDecorator+Listener": + // Expect:INFO: WELD-ENV-001213: Jetty CDI SPI support detected, CDI injection will be available in Listeners, Servlets and Filters. + context.getObjectFactory().addDecorator(new org.eclipse.jetty.cdi.CdiSpiDecorator(context)); + context.getServletHandler().addListener(new ListenerHolder(org.jboss.weld.environment.servlet.Listener.class)); + break; + + case "CdiServletContainerInitializer+Listener": + // Expect:INFO: WELD-ENV-001213: Jetty CDI SPI support detected, CDI injection will be available in Listeners, Servlets and Filters. + context.addBean(new ServletContextHandler.Initializer(context, new org.eclipse.jetty.cdi.CdiServletContainerInitializer())); + context.addEventListener(new org.jboss.weld.environment.servlet.Listener()); + break; + + case "CdiServletContainerInitializer(CdiDecoratingListener)+Listener": + // Expect:INFO: WELD-ENV-001212: Jetty CdiDecoratingListener support detected, CDI injection will be available in Listeners, Servlets and Filters + context.setInitParameter(org.eclipse.jetty.cdi.CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, org.eclipse.jetty.cdi.CdiDecoratingListener.MODE); + context.addBean(new ServletContextHandler.Initializer(context, new org.eclipse.jetty.cdi.CdiServletContainerInitializer())); + context.addEventListener(new org.jboss.weld.environment.servlet.Listener()); + break; + + case "CdiServletContainerInitializer+EnhancedListener": + // Expect:INFO: WELD-ENV-001213: Jetty CDI SPI support detected, CDI injection will be available in Listeners, Servlets and Filters. + context.addBean(new ServletContextHandler.Initializer(context, new org.eclipse.jetty.cdi.CdiServletContainerInitializer())); + context.addBean(new ServletContextHandler.Initializer(context, new org.jboss.weld.environment.servlet.EnhancedListener())); + break; + + case "CdiServletContainerInitializer(CdiDecoratingListener)+EnhancedListener": + // Expect:INFO: WELD-ENV-001212: Jetty CdiDecoratingListener support detected, CDI injection will be available in Listeners, Servlets and Filters + context.setInitParameter(org.eclipse.jetty.cdi.CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, org.eclipse.jetty.cdi.CdiDecoratingListener.MODE); + context.addBean(new ServletContextHandler.Initializer(context, new org.eclipse.jetty.cdi.CdiServletContainerInitializer())); + context.addBean(new ServletContextHandler.Initializer(context, new org.jboss.weld.environment.servlet.EnhancedListener())); + break; + + case "EnhancedListener+CdiServletContainerInitializer(CdiDecoratingListener)": + // Expect:INFO: WELD-ENV-001212: Jetty CdiDecoratingListener support detected, CDI injection will be available in Listeners, Servlets and Filters + context.setInitParameter(org.eclipse.jetty.cdi.CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, org.eclipse.jetty.cdi.CdiDecoratingListener.MODE); + context.addBean(new ServletContextHandler.Initializer(context, new org.jboss.weld.environment.servlet.EnhancedListener())); + context.addBean(new ServletContextHandler.Initializer(context, new org.eclipse.jetty.cdi.CdiServletContainerInitializer())); + break; + } + + return server; + } + + @ParameterizedTest() + @ValueSource(strings = + { + "none", + "DecoratingListener+Listener", + "CdiDecoratingListener+Listener", + "CdiSpiDecorator+Listener", + "CdiServletContainerInitializer+Listener", + "CdiServletContainerInitializer(CdiDecoratingListener)+Listener", + "CdiServletContainerInitializer+EnhancedListener", + "CdiServletContainerInitializer(CdiDecoratingListener)+EnhancedListener" + }) + public void testServletContext(String mode) throws Exception + { + Server server = createServerWithServletContext(mode); + server.start(); + LocalConnector connector = server.getBean(LocalConnector.class); + String response = connector.getResponse("GET / HTTP/1.0\r\n\r\n"); + assertThat(response, containsString("HTTP/1.1 200 OK")); + assertThat(response, containsString("Hello GreetingsServlet filtered by Weld BeanManager ")); + assertThat(response, containsString("Beans from Weld BeanManager ")); + if (mode.contains("EnhancedListener")) + assertThat(response, containsString("Listener saw Weld BeanManager")); + else + assertThat(response, containsString("Listener saw null")); + + assertThat(response, containsString("Beans from Weld BeanManager for ")); + + server.stop(); + } + + @Test + public void testWebappContext() throws Exception + { + Server server = new Server(8080); + server.addConnector(new LocalConnector(server)); + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setResourceBase("src/test/resources/weldtest"); + server.setHandler(webapp); + + webapp.setInitParameter(org.eclipse.jetty.cdi.CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, org.eclipse.jetty.cdi.CdiDecoratingListener.MODE); + webapp.addBean(new ServletContextHandler.Initializer(webapp, new org.eclipse.jetty.cdi.CdiServletContainerInitializer())); + webapp.addBean(new ServletContextHandler.Initializer(webapp, new org.jboss.weld.environment.servlet.EnhancedListener())); + + webapp.getServerClasspathPattern().add("-org.eclipse.jetty.embedded."); + webapp.getSystemClasspathPattern().add("org.eclipse.jetty.embedded."); + + webapp.addServlet(GreetingsServlet.class, "/"); + webapp.addFilter(MyFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + webapp.getServletHandler().addListener(new ListenerHolder(MyContextListener.class)); + + server.start(); + + LocalConnector connector = server.getBean(LocalConnector.class); + String response = connector.getResponse("GET / HTTP/1.0\r\n\r\n"); + assertThat(response, containsString("HTTP/1.1 200 OK")); + assertThat(response, containsString("Hello GreetingsServlet filtered by Weld BeanManager ")); + assertThat(response, containsString("Beans from Weld BeanManager ")); + assertThat(response, containsString("Listener saw Weld BeanManager")); + server.stop(); + } + + @Test + public void testWebappContextDiscovered() throws Exception + { + Server server = new Server(8080); + server.addConnector(new LocalConnector(server)); + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setResourceBase("src/test/resources/weldtest"); + server.setHandler(webapp); + + // Need the AnnotationConfiguration to detect SCIs + Configuration.ClassList.setServerDefault(server).addBefore(JettyWebXmlConfiguration.class.getName(), + AnnotationConfiguration.class.getName()); + + // Need to expose our SCI. This is ugly could be made better in jetty-10 with a CdiConfiguration + webapp.getServerClasspathPattern().add("-" + CdiServletContainerInitializer.class.getName()); + webapp.getSystemClasspathPattern().add(CdiServletContainerInitializer.class.getName()); + + // This is ugly but needed for maven for testing in a overlaid war pom + webapp.getServerClasspathPattern().add("-org.eclipse.jetty.embedded."); + webapp.getSystemClasspathPattern().add("org.eclipse.jetty.embedded."); + + webapp.getServletHandler().addListener(new ListenerHolder(MyContextListener.class)); + webapp.addFilter(MyFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); + webapp.addServlet(GreetingsServlet.class, "/"); + + server.start(); + + LocalConnector connector = server.getBean(LocalConnector.class); + String response = connector.getResponse("GET / HTTP/1.0\r\n\r\n"); + System.err.println(response); + assertThat(response, containsString("HTTP/1.1 200 OK")); + assertThat(response, containsString("Hello GreetingsServlet filtered by Weld BeanManager ")); + assertThat(response, containsString("Beans from Weld BeanManager ")); + assertThat(response, containsString("Listener saw Weld BeanManager")); + server.stop(); + + } + + public static class MyContextListener implements ServletContextListener + { + @Inject + BeanManager manager; + + @Override + public void contextInitialized(ServletContextEvent sce) + { + sce.getServletContext().setAttribute("listener", manager); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) + { + + } + } + + public static class MyFilter implements Filter + { + @Inject + BeanManager manager; + + @Override + public void init(FilterConfig filterConfig) throws ServletException + { + if (manager == null) + throw new IllegalStateException(); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException + { + // copy attribute from MyListener to see if it was decorated. + request.setAttribute("filter", manager); + chain.doFilter(request, response); + } + + @Override + public void destroy() + { + + } + } + + public static class GreetingsServlet extends HttpServlet + { + @Inject + @Named("friendly") + public Greetings greetings; + + @Inject + BeanManager manager; + + @Override + public void init() + { + if (manager == null) + throw new IllegalStateException(); + } + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + { + resp.setContentType("text/plain"); + resp.getWriter().print(greetings == null ? "NULL" : greetings.getGreeting()); + resp.getWriter().print(" filtered by "); + resp.getWriter().println(req.getAttribute("filter")); + resp.getWriter().println("Beans from " + manager); + resp.getWriter().println("Listener saw " + req.getServletContext().getAttribute("listener")); + } + } + + public interface Greetings + { + String getGreeting(); + } + + public static class FriendlyGreetings + { + @Produces + @Named("friendly") + public Greetings friendly(InjectionPoint ip) + { + return () -> "Hello " + ip.getMember().getDeclaringClass().getSimpleName(); + } + + @Produces + @Named("old") + public Greetings old() + { + return () -> "Salutations!"; + } + } + +} diff --git a/jetty-cdi/src/test/resources/META-INF/beans.xml b/jetty-cdi/src/test/resources/META-INF/beans.xml new file mode 100644 index 000000000000..f85327832c60 --- /dev/null +++ b/jetty-cdi/src/test/resources/META-INF/beans.xml @@ -0,0 +1,4 @@ + + diff --git a/jetty-documentation/src/main/asciidoc/development/frameworks/cdi.adoc b/jetty-documentation/src/main/asciidoc/development/frameworks/cdi.adoc new file mode 100644 index 000000000000..a47bac65216b --- /dev/null +++ b/jetty-documentation/src/main/asciidoc/development/frameworks/cdi.adoc @@ -0,0 +1,119 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// ======================================================================== +// 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. +// ======================================================================== +// + +[[framework-cdi]] +=== CDI + +Contexts and Dependency Injection for Java EE (http://www.cdi-spec.org/[CDI]) is a standard implemented by frameworks such as http://seamframework.org/Weld[Weld] and https://openwebbeans.apache.org/[Apache OpenWebBeans]. +This is a common way to assemble and configure webapplications by a process often referred to as 'decoration'. + +Jetty integration of CDI frameworks allows CDI to be used to inject the Filters, Servlets and Listeners created within a Servlet Context. +There are two approaches to integration: + + * CDI implementation can integrate with Jetty. + This requires the CDI implementation to have Jetty specific code. + Since Jetty-9.4.20 a loosely bound mechanism has been available for CDI implementations to extends the Jetty `DecoratedObjectFactory` without hard API dependencies. + Prior to that, CDI implementations directly called jetty APIs that need to be explicitly exposed to the webapp. + + * Alternately, Jetty can integrate with CDI implementations by using standard CDI SPIs. + +==== Jetty CDI Modules + +The Jetty distribution come with several CDI modules. +These modules do not provide CDI, but instead enable one of more integration mechanisms. + +===== Jetty `cdi` Module +The `cdi` module supports either two modes of CDI integration which can be selected either by the "org.eclipse.jetty.cdi" context init parameter or the "org.eclipse.jetty.cdi" server attribute (which is initialised from the "jetty.cdi.mode" start property). +Supported modes are: + + * `CdiSpiDecorator` Jetty will call the CDI SPI within the webapp to decorate objects (default). + + * `CdiDecoratingLister` The webapp may register a decorator on the context attribute "org.eclipse.jetty.cdi.decorator". +------------------------- +cd $JETTY_BASE +java -jar $JETTY_HOME/start.jar --add-to-start=cdi +------------------------- + +===== Jetty `cdi-decorate` Module +This module depends on the `cdi` module and sets the default mode to `CdiDecoratingListener`. +This is the preferred mode for Weld integration. +------------------------- +cd $JETTY_BASE +java -jar $JETTY_HOME/start.jar --add-to-start=cdi-decorate +------------------------- + +===== Jetty `cdi-spi` Module +This module depends on the `cdi` module and sets the default mode to `CdiSpiDecorator`. +This is the preferred mode for Open Web Beans integration. +------------------------- +cd $JETTY_BASE +java -jar $JETTY_HOME/start.jar --add-to-start=cdi-spi +------------------------- + +===== Jetty `cdi2` Module +This module supports the *deprecated* technique of exposing private Jetty decorate APIs to the CDI implementation in the webapp. + +------------------------- +cd $JETTY_BASE +java -jar $JETTY_HOME/start.jar --add-to-start=cdi2 +------------------------- + +This module is equivalent to directly modifying the class path configuration with a `jetty-web.xml` like: + +[source.XML, xml] +------------------------------------------------------------- + + + + + -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 + + +------------------------------------------------------------- + +____ +[TIP] +The `cdi2` module or directly modifying the web application classpath will not work for Jetty 10.0.0 and later. +It should only be used for versions prior to Jetty 9.4.20 and/or Weld 3.1.2.Final +____ + + +[[cdi-embedded]] +==== Embedded Jetty with CDI +When starting embedded Jetty programmatically from the `main` method, to use CDI it may be +necessary: + + * enable a Jetty CDI integration mode + + * and/or enable a CDI frame integration. + +However, depending on the exact configuration of the embedded server, either or both steps may not be required as `ServletContainerInitializer`s may be discovered. + +The details for embedding CDI is explained in the link:#weld-embedded[Embedded Jetty with Weld] section, which can also be adapted to other CDI frameworks. diff --git a/jetty-documentation/src/main/asciidoc/development/frameworks/chapter.adoc b/jetty-documentation/src/main/asciidoc/development/frameworks/chapter.adoc index 0f21a388b3ff..65565050b5f0 100644 --- a/jetty-documentation/src/main/asciidoc/development/frameworks/chapter.adoc +++ b/jetty-documentation/src/main/asciidoc/development/frameworks/chapter.adoc @@ -19,7 +19,8 @@ [[frameworks]] == Frameworks +include::cdi.adoc[] +include::weld.adoc[] include::spring-usage.adoc[] include::osgi.adoc[] -include::weld.adoc[] include::metro.adoc[] diff --git a/jetty-documentation/src/main/asciidoc/development/frameworks/weld.adoc b/jetty-documentation/src/main/asciidoc/development/frameworks/weld.adoc index bd937ab78746..19c68531adab 100644 --- a/jetty-documentation/src/main/asciidoc/development/frameworks/weld.adoc +++ b/jetty-documentation/src/main/asciidoc/development/frameworks/weld.adoc @@ -26,124 +26,64 @@ It is easily configured with Jetty 9. ==== Weld Setup The easiest way to configure weld is within the Jetty distribution itself. -This can be accomplished either by enabling one of the startup link:#startup-modules[modules] for Weld, or by creating/editing a `jetty-web.xml` descriptor (see also https://www.eclipse.org/jetty/documentation/current/jetty-web-xml-config.html[Jetty XML Reference]). +This can be accomplished either by enabling one of the startup link:#startup-modules[modules] described in link:#framework-cdi[CDI Framework]: -===== Jetty Weld Modules - -====== Jetty `cdi-decorate` Module - -Since Jetty 9.4.20 and Weld 3.1.2.Final, the Weld/Jetty integration uses the jetty `cdi-decorate` module. -To activate this module in Jetty the `cdi-decorate` module needs activated on the command line, which can be done as follows: + * the `cdi-decorate` module is the preferred Weld integration. + The activation of this module by Weld can be confirmed by the following Weld log: +[source, screen, subs="{sub-order}"] +.... +INFO: WELD-ENV-001212: Jetty CdiDecoratingListener support detected, CDI injection will be available in Listeners, Servlets and Filters. +.... + * the `cdi-spi` module works with Weld, but may restrict some non standard features. + The activation of this module by Weld can be confirmed by the following Weld log: +[source, screen, subs="{sub-order}"] +.... +INFO: WELD-ENV-001213: Jetty CDI SPI support detected, CDI injection will be available in Listeners, Servlets and Filters. +.... + * the deprecated `cdi2` module works with Weld prior to 3.1.2.Final. + The activation of this module by Weld can be confirmed by the following Weld log: +[source, screen, subs="{sub-order}"] +.... +INFO: WELD-ENV-001201: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported. +.... +To activate the preferred `cdi-decorate` module use: ------------------------- cd $JETTY_BASE java -jar $JETTY_HOME/start.jar --add-to-start=cdi-decorate ------------------------- -====== Jetty `cdi2` Module - -For versions prior to Jetty 9.4.20 and Weld 3.1.2, the Weld/Jetty integration required some internal Jetty APIs to be made visible to the web application. -This can be done using the deprecated `cdi2` module either by activating the `cdi2` module: - -------------------------- -cd $JETTY_BASE -java -jar $JETTY_HOME/start.jar --add-to-start=cdi2 -------------------------- - - -===== Jetty-Web XML - - -[source.XML, xml] -------------------------------------------------------------- - - - - - -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 - - -------------------------------------------------------------- - ____ [TIP] -Directly modifying the web application classpath via `jetty-web.xml` will not work for Jetty 10.0.0 and later. +For use with the jetty-maven-plugin, the best idea is to make the org.jboss.weld.servlet:weld-servlet and jetty-cdi artifacts _plugin_ dependencies (__not__ a webapp dependency). ____ -===== Jetty `cdi-spi` Module -Since Jetty 9.4.20 the Jetty `cdi-spi` module has been available that integrates any compliant CDI implementation by directly calling the CDI SPI. -Since Weld support specific Jetty integration, it is not recommended to use this module with Weld. - -When you start up your Jetty distribution with the webapp you should see output similar to the following (providing your logging is the default configuration): +[[weld-embedded]] +==== Weld with Embedded Jetty -[source, screen, subs="{sub-order}"] -.... -2015-06-18 12:13:54.924:INFO::main: Logging initialized @485ms -2015-06-18 12:13:55.231:INFO:oejs.Server:main: jetty-{VERSION} -2015-06-18 12:13:55.264:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///tmp/cdi-demo/webapps/] at interval 1 -2015-06-18 12:13:55.607:WARN:oeja.AnnotationConfiguration:main: ServletContainerInitializers: detected. Class hierarchy: empty -Jun 18, 2015 12:13:55 PM org.jboss.weld.environment.servlet.EnhancedListener onStartup -INFO: WELD-ENV-001008: Initialize Weld using ServletContainerInitializer -Jun 18, 2015 12:13:55 PM org.jboss.weld.bootstrap.WeldStartup -INFO: WELD-000900: 2.2.9 (Final) -Jun 18, 2015 12:13:55 PM org.jboss.weld.environment.servlet.deployment.WebAppBeanArchiveScanner scan -WARN: WELD-ENV-001004: Found both WEB-INF/beans.xml and WEB-INF/classes/META-INF/beans.xml. It's not portable to use both locations at the same time. Weld is going to use file:/tmp/jetty-0.0.0.0-8080-cdi-webapp.war-_cdi-webapp-any-8161614308407422636.dir/webapp/WEB-INF/beans.xml. -Jun 18, 2015 12:13:55 PM org.jboss.weld.bootstrap.WeldStartup startContainer -INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously. -Jun 18, 2015 12:13:55 PM org.jboss.weld.interceptor.util.InterceptionTypeRegistry -WARN: WELD-001700: Interceptor annotation class javax.ejb.PostActivate not found, interception based on it is not enabled -Jun 18, 2015 12:13:55 PM org.jboss.weld.interceptor.util.InterceptionTypeRegistry -WARN: WELD-001700: Interceptor annotation class javax.ejb.PrePassivate not found, interception based on it is not enabled -Jun 18, 2015 12:13:56 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException -Jun 18, 2015 12:13:56 PM org.jboss.weld.environment.servlet.WeldServletLifecycle findContainer -INFO: WELD-ENV-001002: Container detection skipped - custom container class loaded: org.jboss.weld.environment.jetty.JettyContainer. -Jun 18, 2015 12:13:56 PM org.jboss.weld.environment.jetty.JettyContainer initialize -INFO: WELD-ENV-001200: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners should work on Jetty 9.1.1 and newer. -Jun 18, 2015 12:13:56 PM org.jboss.weld.environment.servlet.Listener contextInitialized -INFO: WELD-ENV-001006: org.jboss.weld.environment.servlet.EnhancedListener used for ServletContext notifications -Jun 18, 2015 12:13:56 PM org.jboss.weld.environment.servlet.EnhancedListener contextInitialized -INFO: WELD-ENV-001009: org.jboss.weld.environment.servlet.Listener used for ServletRequest and HttpSession notifications -2015-06-18 12:13:56.535:INFO:oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext@6574b225{/cdi-webapp,file:///tmp/jetty-0.0.0.0-8080-cdi-webapp.war-_cdi-webapp-any-8161614308407422636.dir/webapp/,AVAILABLE}{/cdi-webapp.war} -2015-06-18 12:13:56.554:INFO:oejs.ServerConnector:main: Started ServerConnector@7112f81c{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} -2015-06-18 12:13:56.587:INFO:oejus.SslContextFactory:main: x509={jetty.eclipse.org=jetty} wild={} alias=null for SslContextFactory@3214ee6(file:///tmp/cdi-demo/etc/keystore,file:///tmp/cdi-demo/etc/keystore) -2015-06-18 12:13:56.821:INFO:oejs.ServerConnector:main: Started ServerConnector@69176a9b{SSL,[ssl, http/1.1]}{0.0.0.0:8443} -2015-06-18 12:13:56.822:INFO:oejs.Server:main: Started @2383ms +When starting embedded Jetty programmatically from the `main` method it is necessary to: -.... + * enable a jetty CDI integration mode by registering a `Listener` or `ServletContainerInitializer` -For use with the jetty-maven-plugin, the best idea is to make the org.jboss.weld.servlet:weld-servlet artifact a _plugin_ dependency (__not__ a webapp dependency). + * enable Weld by registering either its `Listener` or `ServletContainerInitializer` -[[weld-embedded]] -==== Embedded Jetty +===== Using a `ServletContextHandler` -When starting embedded Jetty programmatically from the `main` method it is necessary to register Weld's listener: +Embedded usage often uses a `ServletContextHandler` which is the base class of `WebappContext` and lacks the features of "web.xml" configuration and must be configured directly. +The examples in this section based on a server and context set up as follows: [source.JAVA, java] ---- public class Main { - public static void main(String[] args) throws Exception { Server jetty = new Server(8080); - WebAppContext context = new WebAppContext(); + ServletContextHandler context = new ServletContextHandler(); context.setContextPath("/"); - context.setResourceBase("src/main/resources"); - jetty.setHandler(context); + server.setHandler(context); + context.addServlet(HelloWorldServlet.class, "/*"); - context.addEventListener(new DecoratingListener()); # <1> - context.addEventListener(new Listener()); # <2> + /* CDI enabling goes here. See options below */ jetty.start(); jetty.join(); @@ -159,7 +99,102 @@ public class Main { } } } +---- + +====== Initialize Weld with `ServletContainerInitializers` +The best way to initialize both Jetty Weld integration is to use their respective `ServletContainerInitializers`: +[source.JAVA, java] +---- + import org.eclipse.jetty.cdi.CdiServletContainerInitializer; + import org.eclipse.jetty.cdi.CdiDecoratingListener; + import org.jboss.weld.environment.servlet.EnhancedListener; + // ... + context.setInitParameter( + CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, + CdiDecoratingListener.MODE); + context.addBean(new ServletContextHandler.Initializer(context, + new EnhancedListener())); + context.addBean(new ServletContextHandler.Initializer(context, + new CdiServletContainerInitializer())); +---- +This code uses the `ServletContextHandler.Initializer` utility class added in Jetty-9.4.30. +Prior to that the same effect can be achieved with a custom implementation of `ServletContextHandler.ServletContainerInitializerCaller`. -<1> Jetty's `org.eclipse.jetty.webapp.DecoratingListener` registered programmatically (since Jetty-9.4.20) -<2> Weld's `org.jboss.weld.environment.servlet.Listener` registered programmatically +====== Initialize Weld with Listeners +Jetty Weld integration can also be initialized by directly adding the listeners required: +[source.JAVA, java] +---- + import org.eclipse.jetty.cdi.CdiDecoratingListener; + import org.jboss.weld.environment.servlet.Listener; + // ... + context.addEventListener(new CdiDecoratingListener(context)); + context.addEventListener(new Listener()); +---- + +====== Other Weld initializations +When running embedded without a context classloader, it is not actually required to initialize Jetty at all. +If just Weld is initialized then it will disover the Jetty APIs and use the deprecated integration: +[source.JAVA, java] +---- + import org.jboss.weld.environment.servlet.Listener; + // ... + context.addEventListener(new Listener()); +---- +However, this results in only a partially functional integration and the following warning: +---- +INFO: WELD-ENV-001201: Jetty 7.2+ detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported. +---- + +Jetty can also be initialized by adding the `org.eclipse.jetty.webapp.DecoratingListener` listener instead of the `org.eclipse.jetty.cdi.CdiDecoratingListener`. +However, this introduces a needless dependency on `jetty-webapp` and is not the preferred method. + +====== Initialize Weld with `WebappContext` +Some embedded usage still makes use of the `WebappContext` class for the convention-over-configuration benefits. +The methods described for `ServletContextHandler` will work for `WebappContext`: + +[source.JAVA, java] +---- + import org.eclipse.jetty.cdi.CdiServletContainerInitializer; + import org.eclipse.jetty.cdi.CdiDecoratingListener; + import org.jboss.weld.environment.servlet.EnhancedListener; + // ... + Server server = new Server(8080); + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + server.setHandler(webapp); + + webapp.setInitParameter( + CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, + CdiDecoratingListener.MODE); + webapp.addBean(new ServletContextHandler.Initializer(webapp, + new CdiServletContainerInitializer())); + webapp.addBean(new ServletContextHandler.Initializer(webapp, + new EnhancedListener())); + + // ... +---- + +Alternately the webapp can be configured to discover the SCIs: + +[source.JAVA, java] ---- + Server server = new Server(8080); + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + server.setHandler(webapp); + + webapp.setInitParameter( + CdiServletContainerInitializer.CDI_INTEGRATION_ATTRIBUTE, + CdiDecoratingListener.MODE); + + // Need the AnnotationConfiguration to detect SCIs + Configuration.ClassList.setServerDefault(server).addBefore( + JettyWebXmlConfiguration.class.getName(), + AnnotationConfiguration.class.getName()); + + // Need to expose our SCI class. + webapp.getServerClasspathPattern().add("-" + CdiServletContainerInitializer.class.getName()); + webapp.getSystemClasspathPattern().add(CdiServletContainerInitializer.class.getName()); + + // ... +---- \ No newline at end of file diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java index 75c858eebba3..91acd211eba5 100644 --- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java +++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java @@ -124,9 +124,6 @@ public void callStartup(WebAppContext context) { Set> classes = new HashSet>(); - ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(context.getClassLoader()); - try { for (String s : _applicableTypeNames) @@ -147,7 +144,6 @@ public void callStartup(WebAppContext context) finally { context.getServletContext().setExtendedListenerTypes(false); - Thread.currentThread().setContextClassLoader(oldLoader); } } } diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java index 8d4ac4c6dd43..2793b5cc7712 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java @@ -34,6 +34,7 @@ import javax.servlet.FilterRegistration; import javax.servlet.RequestDispatcher; import javax.servlet.Servlet; +import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; @@ -68,6 +69,7 @@ import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; +import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -336,9 +338,15 @@ protected ServletHandler newServletHandler() @Override protected void startContext() throws Exception { - ServletContainerInitializerCaller sciBean = getBean(ServletContainerInitializerCaller.class); - if (sciBean != null) - sciBean.start(); + for (ServletContainerInitializerCaller sci : getBeans(ServletContainerInitializerCaller.class)) + { + if (sci.isStopped()) + { + sci.start(); + if (isAuto(sci)) + manage(sci); + } + } if (_servletHandler != null) { @@ -749,13 +757,13 @@ public static ServletContextHandler getServletContextHandler(ServletContext cont public static class JspPropertyGroup implements JspPropertyGroupDescriptor { - private List _urlPatterns = new ArrayList<>(); + private final List _urlPatterns = new ArrayList<>(); private String _elIgnored; private String _pageEncoding; private String _scriptingInvalid; private String _isXml; - private List _includePreludes = new ArrayList<>(); - private List _includeCodas = new ArrayList<>(); + private final List _includePreludes = new ArrayList<>(); + private final List _includeCodas = new ArrayList<>(); private String _deferredSyntaxAllowedAsLiteral; private String _trimDirectiveWhitespaces; private String _defaultContentType; @@ -1001,8 +1009,8 @@ public String toString() public static class JspConfig implements JspConfigDescriptor { - private List _taglibs = new ArrayList<>(); - private List _jspPropertyGroups = new ArrayList<>(); + private final List _taglibs = new ArrayList<>(); + private final List _jspPropertyGroups = new ArrayList<>(); public JspConfig() { @@ -1474,7 +1482,7 @@ public interface Decorator extends org.eclipse.jetty.util.Decorator */ private static class LegacyDecorator implements Decorator { - private org.eclipse.jetty.util.Decorator decorator; + private final org.eclipse.jetty.util.Decorator decorator; public LegacyDecorator(org.eclipse.jetty.util.Decorator decorator) { @@ -1493,4 +1501,43 @@ public void destroy(Object o) decorator.destroy(o); } } + + /** + * A utility class to hold a {@link ServletContainerInitializer} and implement the + * {@link ServletContainerInitializerCaller} interface so that the SCI is correctly + * started if an instance of this class is added as a bean to a {@link ServletContextHandler}. + */ + public static class Initializer extends AbstractLifeCycle implements ServletContainerInitializerCaller + { + private final ServletContextHandler _context; + private final ServletContainerInitializer _sci; + private final Set> _classes; + + public Initializer(ServletContextHandler context, ServletContainerInitializer sci, Set> classes) + { + _context = context; + _sci = sci; + _classes = classes; + } + + public Initializer(ServletContextHandler context, ServletContainerInitializer sci) + { + this(context, sci, Collections.emptySet()); + } + + @Override + protected void doStart() throws Exception + { + boolean oldExtended = _context.getServletContext().isExtendedListenerTypes(); + try + { + _context.getServletContext().setExtendedListenerTypes(true); + _sci.onStartup(_classes, _context.getServletContext()); + } + finally + { + _context.getServletContext().setExtendedListenerTypes(oldExtended); + } + } + } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java index 16936d43cef5..130afe4c4115 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java @@ -25,7 +25,6 @@ */ public interface Container { - /** * Add a bean. If the bean is-a {@link Listener}, then also do an implicit {@link #addEventListener(Listener)}. * @@ -35,7 +34,7 @@ public interface Container boolean addBean(Object o); /** - * @return the list of beans known to this aggregate + * @return the collection of beans known to this aggregate, in the order they were added. * @see #getBean(Class) */ Collection getBeans(); @@ -43,7 +42,7 @@ public interface Container /** * @param clazz the class of the beans * @param the Bean type - * @return a list of beans of the given class (or subclass) + * @return a list of beans of the given class (or subclass), in the order they were added. * @see #getBeans() * @see #getContainedBeans(Class) */ @@ -52,7 +51,7 @@ public interface Container /** * @param clazz the class of the bean * @param the Bean type - * @return the first bean of a specific class (or subclass), or null if no such bean exist + * @return the first bean (in order added) of a specific class (or subclass), or null if no such bean exist */ T getBean(Class clazz); @@ -138,7 +137,8 @@ interface InheritedListener extends Listener /** * @param clazz the class of the beans * @param the Bean type - * @return the list of beans of the given class from the entire Container hierarchy + * @return the list of beans of the given class from the entire Container hierarchy. The order is primarily depth first + * and secondarily added order. */ Collection getContainedBeans(Class clazz); } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java index 3051a0a7dce8..5e80d437cce4 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java @@ -915,11 +915,6 @@ public void updateBeans(Object[] oldBeans, final Object[] newBeans) } } - /** - * @param clazz the class of the beans - * @param the Bean type - * @return the list of beans of the given class from the entire Container hierarchy - */ @Override public Collection getContainedBeans(Class clazz) { @@ -928,11 +923,6 @@ public Collection getContainedBeans(Class clazz) return beans; } - /** - * @param clazz the class of the beans - * @param the Bean type - * @param beans the collection to add beans of the given class from the entire Container hierarchy - */ protected void getContainedBeans(Class clazz, Collection beans) { beans.addAll(getBeans(clazz)); 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 fd5ef687a16f..ebdac3c9d836 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 @@ -61,7 +61,7 @@ public static Stream tests() Arguments.of("weld", "cdi2", null), Arguments.of("weld", "cdi-spi", null), // Weld >= 3.1.2 Arguments.of("weld", "decorate", null), // Weld >= 3.1.2 - // TODO Arguments.of("weld", "cdi-decorate", null), // Weld >= 3.1.3 + Arguments.of("weld", "cdi-decorate", null), // Weld >= 3.1.3 // -- Apache OpenWebBeans -- Arguments.of("owb", "cdi-spi", null), diff --git a/tests/test-webapps/test-cdi-common-webapp/src/main/resources/META-INF/beans.xml b/tests/test-webapps/test-cdi-common-webapp/src/main/resources/META-INF/beans.xml index abb1108351b5..f85327832c60 100644 --- a/tests/test-webapps/test-cdi-common-webapp/src/main/resources/META-INF/beans.xml +++ b/tests/test-webapps/test-cdi-common-webapp/src/main/resources/META-INF/beans.xml @@ -1,4 +1,4 @@ - \ No newline at end of file +