Websocket CdiUtils NPE с использованием <f: websocket /> - PullRequest
0 голосов
/ 12 мая 2018

Это приложение работало нормально в TC7, Spring 3 и JSF 2.2, но я хотел добавить возможности push-уведомлений в JSF 2.3, поэтому я обновился до TC 9.0.8, Spring 5.0.5 и JSF 2.3.0.простые начальные проблемы из-за обновлений. Приложение развертывается нормально, и Spring Security работает (я могу войти в систему), но затем я получаю эту ошибку:

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)

Мой отладчик показывает, что на CdiUtils: 230 beanManager является нулевым, и я подозреваю, чтоно не может подтвердить, что FacesContext является нулевым на CdiUtils: 213.Я подозреваю, что это связано с путаницей из-за наличия нескольких контейнеров (Tomcat, CDI, Spring и JSF) одновременно.Мне нравятся Spring Security, RestTemplate и JdbcTemplate, поэтому я немного не хочу отказываться от Spring.Вот мой пуш-бин.Я бросил в него каждую аннотацию:

@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, который отправляет сообщение:

<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>

Приемник JSF websocket:

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

Тег JSF websocketи код для отображения сообщения:

<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>

Есть идеи как это исправить?

1 Ответ

0 голосов
/ 15 мая 2018

Посмотрите на это http://balusc.omnifaces.org/2013/10/how-to-install-cdi-in-tomcat.html. Вам необходимо установить Weld.

Вам нужно сделать три шага:

  1. Удалите файл weld-servlet-shaded.jar в веб-приложении / WEB-INF / lib. Если вы используете Maven, это координата:

<dependency>
      <groupId>org.jboss.weld.servlet</groupId>
      <artifactId>weld-servlet-shaded</artifactId>
      <version>3.0.3.Final</version>
    </dependency>
  1. Создайте файл /META-INF/context.xml в веб-контенте веб-приложения со следующим содержимым (или, если он у вас есть, добавьте только запись):

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

Это зарегистрирует фабрику BeanManager в Weld в JNDI Tomcat. Это не может быть выполнено программным способом Weld, потому что JNDI от Tomcat предназначен только для чтения. Этот шаг не обязателен, если вы нацелены как минимум на Mojarra 2.2.11 и / или OmniFaces 2.4 или новее. Оба могут найти его в ServletContext. Однако, могут быть другие библиотеки, которые все еще ожидают найти BeanManager в JNDI, тогда вам лучше всего сохранить этот файл конфигурации для этих библиотек.

  1. Создайте (пустой) файл /WEB-INF/beans.xml (нет, не в / META-INF! Это только для внутренних файлов JAR, таких как OmniFaces).
...