Websocket CdiUtils NPE using <f:websocket />

笑着哭i 提交于 2020-06-27 16:39:14

问题


This application has been working fine in TC7, Spring 3, and JSF 2.2 but I wanted to add the push capabilities of JSF 2.3 so I upgraded to TC 9.0.8, Spring 5.0.5, and JSF 2.3.0 After some simple initial problems due to the upgrades The app deploys fine and Spring Security works (I can login) but then I get this error:

May 11, 2018 2:24:06 PM com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException
SEVERE: Error Rendering View[/index.xhtml]
java.lang.NullPointerException
    at com.sun.faces.cdi.CdiUtils.getBeanReferenceByType(CdiUtils.java:230)
    at com.sun.faces.cdi.CdiUtils.getBeanReference(CdiUtils.java:213)
    at com.sun.faces.renderkit.html_basic.WebsocketRenderer.encodeEnd(WebsocketRenderer.java:111)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:949)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1912)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:491)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:194)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:151)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:126)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:223)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:671)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:651)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:412)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:754)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1385)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

My debugger reveals that on CdiUtils:230 beanManager is null and I suspect but cannot confirm that FacesContext is null on CdiUtils:213. I suspect this is due to confusion from having multiple containers (Tomcat, CDI, Spring and JSF) at the same time. I do like Spring Security, RestTemplate, and JdbcTemplate, so I'm a little reluctant to give Spring up. Here is my Push bean. I threw every annotation at it I had:

@Component
@Scope("Application")
public class PushBean implements Serializable {

    private static final long serialVersionUID = -6558314691176100417L;

    @Inject
    @Push(channel = "facilitatorBroadcastMessages")
    private PushContext push;

    private String facilitatorBroadcastMessage;

    public void setFacilitatorBroadcastMessage(String message) {
        this.facilitatorBroadcastMessage = message;
    }

    public void broadcastFacilitatorMessage() {
        push.send(facilitatorBroadcastMessage);
    }
}

Facelet code that sends the message:

<p:button value="Send Broadcast Message to All Users" onclick="PF('broadcastMessageDialog').show(); " />
<p:dialog id="broadcastMessageDialog" header="Facilitator Message" widgetVar="broadcastMessageDialog" height="500px">
    <p:inputText id="facilitatorBroadcastMessageInput" value="#{pushBean.facilitatorBroadcastMessage}" />
    <p:commandButton onclick="PF('broadcastMessageDialog').hide(); " value="Send" process="@parent" action="#{pushBean.broadcastFacilitatorMessage()}" />
</p:dialog>

JS websocket listener:

function websocketListener(message, channel, event) {
    $("#facilitatorBroadcastMessage").innerHTML = message;
    PF('facilitatorBroadcastMessageDialog').show();
}

JSF websocket tag and code for displaying the message:

<f:websocket channel="facilitatorBroadcastMessages" onmessage="webSocketListener" />
<p:dialog id="facilitatorBroadcastMessageDialog" header="Facilitator Message" widgetVar="facilitatorBroadcastMessageDialog" height="500px">
    <p id="facilitatorBroadcastMessage"></p>
    <p:button onclick="PF('facilitatorBroadcastMessageDialog').hide(); " value="Got it, thanks!"/>
</p:dialog>

Any ideas how to fix this?


回答1:


Look at this http://balusc.omnifaces.org/2013/10/how-to-install-cdi-in-tomcat.html. You need to install Weld.

You need to do this three steps:

  1. Drop weld-servlet-shaded.jar in webapp's /WEB-INF/lib. In case you're using Maven, this is the coordinate:

<dependency>
      <groupId>org.jboss.weld.servlet</groupId>
      <artifactId>weld-servlet-shaded</artifactId>
      <version>3.0.3.Final</version>
    </dependency>
  1. Create /META-INF/context.xml file in webapp's web content with following content (or, if you already have one, add just the entry to it):

<Context>
    <Resource name="BeanManager" 
        auth="Container"
        type="javax.enterprise.inject.spi.BeanManager"
        factory="org.jboss.weld.resources.ManagerObjectFactory" />
   </Context>

This will register Weld's BeanManager factory in Tomcat's JNDI. This cannot be performed programmatically by Weld because Tomcat's JNDI is strictly read-only. This step is not necessary if you're targeting at least Mojarra 2.2.11 and/or OmniFaces 2.4 or newer. Both are able to find it in ServletContext instead. However, there may be other libraries which still expect to find BeanManager in JNDI, you'd then best keep this configuration file anyway for those libraries.

  1. Create a (empty) /WEB-INF/beans.xml file (no, not in /META-INF! that's only for inside JAR files such as OmniFaces).


来源:https://stackoverflow.com/questions/50300380/websocket-cdiutils-npe-using-fwebsocket

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!