带有 CDI 和现有 JAX-RS 服务的 Vaadin 12 PWA

Vaadin 12 PWA with CDI and existing JAX-RS service

我正在尝试将 Vaadin 12 PWA 前端添加到现有的 JAX-RS RESTful 服务,并使用 @Inject 将其注入 Vaadin class,但我一直收到 Nullpointer 异常。

现有服务有一个 /json/keystore 端点(参见下面的 class)并且 Vaadin UI 有一个入口点 /。结合 Vaadin,我无法再访问之前位于 /json/keystore.

的服务

我正在使用最新的 Vaadin CDI 插件 (10.0.2) 和 Thorntail 2.3.0 及其 CDI 插件,它适用于预先存在的 classes,但在使用时不起作用瓦丁.

有什么建议可以遵循吗? 我应该如何将现有服务与 Vaadin 集成,同时保留不同的路径?

我的Vaadin MainView class如下:

package thorntail.elytron.wui;


import thorntail.elytron.core.controller.KeystoreStorageService;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.page.BodySize;
import com.vaadin.flow.component.page.Viewport;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;
import com.vaadin.flow.theme.Theme;
import com.vaadin.flow.theme.material.Material;
import org.jboss.logging.Logger;

import javax.enterprise.inject.Instance;
import javax.inject.Inject;


@Route( value = "" )
@BodySize( width = "100vw", height = "100vh" )
@Viewport( "width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes" )
@Theme( Material.class )
@PWA( name = "Keystore Manager WUI", shortName = "kmwui" )
public class MainView extends VerticalLayout
{

  private static final Logger LOGGER = Logger.getLogger( MainView.class );

  @Inject
  private Instance<KeystoreStorageService> keystoreStorageServiceInstance;


  public MainView()
  {
    LOGGER.info( "Initializing PWA" );
    if( keystoreStorageServiceInstance.isUnsatisfied() )
    {
      LOGGER.warn( "KeystoreStorageService is null" );
    }

    final TextField nameInput = new TextField( "Name" );
    Button submitBtn = new Button( "Submit" );
    submitBtn.addClickListener( e -> Notification.show( nameInput.getValue() ) );
    add( nameInput );
    add( submitBtn );
  }
}

还有我的 KeystoreStorageService class,在 另一个 Maven 模块 中,看起来像这样:

@ApplicationScoped
public class KeystoreStorageService
{

  private static final Logger LOGGER = Logger.getLogger( KeystoreStorageService.class );

  @PersistenceContext( unitName = "keystore" )
  private EntityManager em;

  **
  * @return all the {@link KeystoreModel} in the db
  */
  public List<KeystoreModel> findAll()
  {
    LOGGER.info( "Finding all Keystores" );
    return em.createNamedQuery( "Keystore.findAll", KeystoreModel.class ).getResultList();
  }

    //...other methods here
}

生成的堆栈跟踪,导航到我的 PWA 的主要路线如下所示:

There was an exception while trying to navigate to '' with the exception message 'Unable to create an instance of 'thorntail.elytron.wui.MainView'. The constructor threw an exception.'

java.lang.IllegalArgumentException: Unable to create an instance of 'thorntail.elytron.wui.MainView'. The constructor threw an exception.
    at com.vaadin.flow.internal.ReflectTools.createProxyInstance(ReflectTools.java:510)
    at com.vaadin.flow.internal.ReflectTools.createInstance(ReflectTools.java:447)
    at com.vaadin.flow.di.DefaultInstantiator.getOrCreate(DefaultInstantiator.java:65)
    at com.vaadin.cdi.CdiInstantiator.lambda$getOrCreate(CdiInstantiator.java:77)
    at com.vaadin.cdi.BeanLookup.lookupOrElseGet(BeanLookup.java:89)
    at com.vaadin.cdi.CdiInstantiator.getOrCreate(CdiInstantiator.java:76)
    at com.vaadin.flow.di.Instantiator.createRouteTarget(Instantiator.java:158)
    at com.vaadin.cdi.CdiInstantiator$Proxy$_$$_WeldClientProxy.createRouteTarget(Unknown Source)
    at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.lambda$getRouteTarget(AbstractNavigationStateRenderer.java:116)
    at java.base/java.util.Optional.orElseGet(Optional.java:369)
    at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.getRouteTarget(AbstractNavigationStateRenderer.java:115)
    at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:167)
    at com.vaadin.flow.router.Router.handleNavigation(Router.java:221)
    at com.vaadin.flow.router.Router.navigate(Router.java:192)
    at com.vaadin.flow.router.Router.initializeUI(Router.java:95)
    at com.vaadin.flow.server.BootstrapHandler.createAndInitUI(BootstrapHandler.java:1117)
    at com.vaadin.flow.server.BootstrapHandler.synchronizedHandleRequest(BootstrapHandler.java:396)
    at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
    at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1545)
    at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:227)
    at com.vaadin.cdi.CdiVaadinServlet.service(CdiVaadinServlet.java:65)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
    at io.undertow.websockets.jsr.JsrWebSocketFilter.doFilter(JsrWebSocketFilter.java:173)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletChain.handleRequest(ServletChain.java:68)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.swarm.generated.FaviconErrorHandler.handleRequest(FaviconErrorHandler.java:61)
    at io.undertow.server.handlers.PathHandler.handleRequest(PathHandler.java:94)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
    at io.undertow.servlet.handlers.ServletInitialHandler.access0(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler.call(ServletInitialHandler.java:138)
    at io.undertow.servlet.handlers.ServletInitialHandler.call(ServletInitialHandler.java:135)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction.call(ServletRequestContextThreadSetupAction.java:48)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction.call(ContextClassLoaderSetupAction.java:43)
    at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create[=12=](SecurityContextThreadSetupAction.java:105)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=12=](UndertowDeploymentInfoService.java:1502)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=12=](UndertowDeploymentInfoService.java:1502)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=12=](UndertowDeploymentInfoService.java:1502)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=12=](UndertowDeploymentInfoService.java:1502)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=12=](UndertowDeploymentInfoService.java:1502)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
    at io.undertow.servlet.handlers.ServletInitialHandler.access[=12=]0(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:104)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:360)
    at io.undertow.server.HttpServerExchange.run(HttpServerExchange.java:830)
    at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1349)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
    at com.vaadin.flow.internal.ReflectTools.createProxyInstance(ReflectTools.java:479)
    ... 70 more
Caused by: java.lang.NullPointerException
    at thorntail.elytron.wui.MainView.<init>(MainView.java:52)
    ... 75 more

我设法通过在 Vaadin 项目中添加 beans.xml 并使用 @Route(对于 Vaadin)和 @Application(对于 jax-rs)设置路径来解决问题

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
       http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd" bean-discovery-mode="all">
</beans>

默认情况下,如果使用分数 io.thorntail:cdi,thorntail 不需要额外的 beans.xml 文件用于 CDI,但对于 Vaadin,它是必需的