Primefaces JSF null, возвращенный из RequestContext.getCurrentInstance()
Я разрабатываю приложение, используя библиотеку тегов Primefaces.
До сих пор я скопировал некоторые примеры с их официального сайта, и все, кажется, работает, за исключением всего, что использует метод RequestContext.getCurrentInstance(). Он либо возвращает null каждый раз, заставляя Tomcat генерировать исключение NullPointer, либо зависает навсегда, никогда ничего не возвращая.
Вот мой код (случай, когда он висит):
GlobalCounterBean.java
package org.primefaces.examples.view;
import java.io.Serializable;
import org.primefaces.context.RequestContext;
public class GlobalCounterBean implements Serializable{
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public synchronized void increment() {
count++;
System.out.println("aaaa");
RequestContext.getCurrentInstance().push("counter", count);
}
}
test.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<p:spinner />
<h:form>
<h:outputText value="#{globalCounter.count}" styleClass="ui-widget display" />
<br />
<p:commandButton value="Click" actionListener="#{globalCounter.increment}" />
</h:form>
<p:push onmessage="handleMessage" channel="counter" />
<script type="text/javascript">
function handleMessage(evt, data) {
$('.display').html(data);
}
</script>
</h:body>
</html>
А вот код для случая, когда он возвращает ноль (все файлы находятся в одном проекте):
ChatController.java:
package org.primefaces.examples.view;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.primefaces.context.RequestContext;
public class ChatController implements Serializable {
private final static String CHANNEL = "chat";
private String message;
private String username;
private boolean loggedIn;
private Set<String> users = new HashSet<String>();
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public boolean isLoggedIn() {
return loggedIn;
}
public void setLoggedIn(boolean loggedIn) {
this.loggedIn = loggedIn;
}
public void send() {
RequestContext.getCurrentInstance().push(CHANNEL, username + ": "+ message);
message = null;
}
public void login() {
RequestContext requestContext = RequestContext.getCurrentInstance();
if(users.contains(username)) {
loggedIn = false;
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Username taken", "Try with another username."));
requestContext.addPartialUpdateTarget("growl");
}
else {
users.add(username);
loggedIn = true;
requestContext.push(CHANNEL, username + " joined the channel.");
}
}
public void disconnect() {
RequestContext.getCurrentInstance().push(CHANNEL, username + " has left the channel.");
loggedIn = false;
username = null;
}
}
chat.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
</head>
<body>
<f:view>
<p:growl id="growl" showDetail="true" />
<h:form>
<p:fieldset id="container" legend="PrimeChat">
<h:panelGroup rendered="#{chatController.loggedIn}" >
<p:outputPanel layout="block" style="width:600px;height:200px;overflow:auto"
styleClass="chatroom" />
<p:spinner />
<p:separator />
<p:inputText value="#{chatController.message}" styleClass="messageInput" />
<p:spacer width="5" />
<p:commandButton value="Send" actionListener="#{chatController.send}" global="false" oncomplete="$('.messageInput').val('').focus()"/>
<p:spacer width="5" />
<p:commandButton value="Disconnect" actionListener="#{chatController.disconnect}" global="false"
oncomplete="chatAgent.close()" update="container" />
</h:panelGroup>
<h:panelGroup rendered="#{not chatController.loggedIn}" >
Username: <p:inputText value="#{chatController.username}" />
<p:spacer width="5" />
<p:commandButton value="Login" actionListener="#{chatController.login}" update="container"
icon="ui-icon-person"/>
</h:panelGroup>
</p:fieldset>
</h:form>
<p:push onmessage="handleMessage" channel="chat" widgetVar="chatAgent" />
<script type="text/javascript">
function handleMessage(evt, data) {
var chatContent = $('.chatContent');
chatContent.append(data + '<br />');
//keep scroll
chatContent.scrollTop(chatContent.height());
}
</script>
<script type="text/javascript">
function handleComplete(xhr, status, args) {
if(args.validationFailed) {
PrimeFaces.debug("Validation Failed");
}
else {
PrimeFaces.debug("Save:" + args.saved);
PrimeFaces.debug("FirstName: " + args.user.firstname + ", Lastname: " + args.user.lastname);
}
}
</script>
</f:view>
</body>
</html>
лица-config.xml:
<?xml version="1.0" encoding="utf-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<managed-bean eager="true">
<managed-bean-name>chatController</managed-bean-name>
<managed-bean-class>org.primefaces.examples.view.ChatController</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>globalCounter</managed-bean-name>
<managed-bean-class>org.primefaces.examples.view.GlobalCounterBean</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
<!--
No ManagedBean declarations here as we are using @ManagedBean Annotations.
-->
</faces-config>
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" >
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
</web-app>
И вот исключение, брошенное в консоль tomcat:
2012-05-27 19:16:25 com.sun.faces.context.ExceptionHandlerImpl log
SEVERE: JSF1073: javax.faces.event.AbortProcessingException caught during processing of INVOKE_APPLICATION 5 : UIComponent-ClientId=j_idt2:j_idt16, Message=java.lang.NullPointerException
2012-05-27 19:16:25 com.sun.faces.context.ExceptionHandlerImpl log
SEVERE: java.lang.NullPointerException
javax.faces.event.AbortProcessingException: java.lang.NullPointerException
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:178)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:84)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:773)
at javax.faces.component.UICommand.broadcast(UICommand.java:296)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:781)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1246)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:77)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.NullPointerException
at org.primefaces.examples.view.ChatController.login(ChatController.java:69)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.el.parser.AstValue.invoke(AstValue.java:191)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:149)
... 21 more
1 ответ
Ваш web.xml
отсутствует часть "Конфигурация URL" в настройке PrimeFaces Push.
Как упоминалось в моем ответе на ваш предыдущий вопрос, подробности установки PrimeFaces Push описаны в главе 6 Руководства пользователя PrimeFaces. Вот выдержка из того, что вы пропустили:
6.1 Настройка
Push-сервер
PrimeFaces Push использует сервлет в качестве диспетчера. Этот сервлет должен находиться в приложении, отличном от приложения JSF, и в данный момент может быть развернут только на сервере Jetty.
<servlet> <servlet-name>Push Servlet</servlet-name> <servlet-class>org.primefaces.push.PushServlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>channels</param-name> <param-value>chat,counter</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Push Servlet</servlet-name> <url-pattern>/prime-push/*</url-pattern> </servlet-mapping>
Конфигурация каналов определяет имена тем, которые может публиковать сервер push.
Конфигурация URL
Приложение JSF должно определить URL-адрес push-сервера для отправки сообщений.
<context-param> <param-name>primefaces.PUSH_SERVER_URL</param-name> <param-value>ws://url_to_push_server</param-value> </context-param>