javaguiceembedded-jettyvaadin-flowvaadin24

Vaadin 24 with Embedded Jetty and Google Guice


I need to use Vaadin framework in an application that already uses Google Guice as DI together with an embedded Jetty as webserver. The main issue is that Vaadin components must use some services bound by Google Guice.

For that Jetty is configured with WebAppContext:

protected void configureServletHandler(final Server server, final ServletContextHandler handler, final Map<String, Servlet> servlets, final StatisticsHandler statisticsHandler) {
        statisticsHandler.setHandler(handler);
        server.setHandler(statisticsHandler);

        try {
            final WebAppContext context = createWebAppContext(servlets);
            handler.setHandler(context);
        } catch (IOException e) {
            logger.error("Cannot create WebAppContext: ", e);
            throw new RuntimeException(e);
        }
        logger.info("WebAppContext is created");

        handler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
        handler.addFilter(CrossOriginFilter.class, "/*", EnumSet.allOf(DispatcherType.class));
    }

    
private static WebAppContext createWebAppContext(final Map<String, Servlet> servlets) throws IOException {

        final WebAppContext context = new WebAppContext();

        context.setBaseResource(Resource.newResource("../../webapp/"));

        for (final var e : servlets.entrySet()) {
            context.addServlet(new ServletHolder(e.getValue()), e.getKey());
        }

        // this will properly scan the classpath for all @WebListeners,
        // including the most important
        // com.vaadin.flow.server.startup.ServletContextListeners.
        // See also https://mvysny.github.io/vaadin-lookup-vs-instantiator/
        context.setAttribute(
                "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                ".*\\.jar|.*/classes/.*");
        context.setConfigurationDiscovered(true);
        context.getServletContext().setExtendedListenerTypes(true);

        return context;
    }   

I tried to adhere an approach describe in Vaadin documentation, customising vaadin Instatiator: https://vaadin.com/docs/latest/advanced/custom-instantiators

For the servlet customisation com.vaadin.cdi.util.BeanManagerProvider is used:

@WebServlet(urlPatterns = "/*", asyncSupported = true)
public class CustomServlet extends VaadinServlet {

  @Override
  protected VaadinServletService createServletService(DeploymentConfiguration deploymentConfiguration) throws ServiceException {
      BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager();
      CustomVaadinServletService service = new CustomVaadinServletService(this, deploymentConfiguration, beanManager);
      service.init();
      return service;
  }
}

But it fails with Exception:

Caused by: java.lang.IllegalStateException: No com.vaadin.cdi.util.BeanManagerProvider in place! Please ensure that you configured the CDI implementation of your choice properly. If your setup is correct, please clear all caches and compiled artifacts.
    at com.vaadin.cdi.util.BeanManagerProvider.getInstance(BeanManagerProvider.java:165) ~[vaadin-cdi-15.0.1.jar:?]
    at net.bigpoint.batman.core.http.servlet.acp.AcpServlet.createServletService(AcpServlet.java:154) ~[batman-core-1.3.0-SNAPSHOT.jar:?]
    at com.vaadin.flow.server.VaadinServlet.createServletService(VaadinServlet.java:336) ~[flow-server-24.1.13.jar:24.1.13]
    at com.vaadin.flow.server.VaadinServlet.init(VaadinServlet.java:132) ~[flow-server-24.1.13.jar:24.1.13]
    at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:633) ~[jetty-servlet-11.0.16.jar:11.0.16]

It seems that before I can use BeanManagerProvider it must be somehow initialized or provided by Jetty, but I could not found how.

The main question: How to combine Vaadin 24 with Guice?

A sub-question is: If use CustomInstantiator, CustomVaadinServletService and CustomServlet as described in Vaadin doc (see the link above), how to use BeanManagerProvider with Jetty?


Solution

  • There is a lot of code/configuration necessary to accomplish this, and it is not suited for a post here. However, I published an example a few months ago for Vaadin 23: https://github.com/oliveryasuna/vaadin-jetty-guice. I have been meaning to update it for Vaadin 24, so I just did. It is also published in the Vaadin Directory: https://vaadin.com/directory/component/embedded-jetty--guice-example.