我需要在已经使用 Google Guice 作为 DI 以及嵌入式 Jetty 作为网络服务器的应用程序中使用 Vaadin 框架。主要问题是 Vaadin 组件必须使用 Google Guice 绑定的一些服务。
Jetty 配置了 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;
}
我尝试遵循 Vaadin 文档中描述的方法,自定义 vaadin Instatiator: https://vaadin.com/docs/latest/advanced/custom-instantiators
对于 servlet 定制,使用 com.vaadin.cdi.util.BeanManagerProvider:
@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;
}
}
但是失败并出现异常:
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]
似乎在我可以使用 BeanManagerProvider 之前,它必须以某种方式初始化或由 Jetty 提供,但我找不到如何实现。
主要问题:如何将Vaadin 24与Guice结合起来?
一个子问题是:如果按照 Vaadin 文档中所述使用 CustomInstantiator、CustomVaadinServletService 和 CustomServlet(请参阅上面的链接),如何将 BeanManagerProvider 与 Jetty 一起使用?
完成此操作所需的代码/配置太多,不适合在此处发布。不过,几个月前我发布了一个 Vaadin 23 的示例:https://github.com/oliveryasuna/vaadin-jetty-guice。我一直想为 Vaadin 24 更新它,所以我就这么做了。它还发布在 Vaadin 目录中:https://vaadin.com/directory/component/embedded-jetty--guice-example。