NullPointer 异常 - JSF 事件处理(ValueChangeListener)
NullPointer Exception - JSF Event Handling ( ValueChangeListener )
我正在学习 JSF 事件处理,当我尝试 运行 一些示例代码时,出现空指针异常。
这是我的 index.xhtml 片段,
<h:form>
<h2>Implement valueChangeListener</h2>
<hr />
<h:panelGrid columns="2">
Selected Locale:
<h:selectOneMenu value="#{userData.selectedCountry}" onchange="submit()">
<f:valueChangeListener type="com.cyb3rh4wk.test.LocaleChangeListener" />
<f:selectItems value="#{userData.countries}" />
</h:selectOneMenu>
Country Name:
<h:outputText id="countryInterface" value="#{userData.selectedCountry}" />
</h:panelGrid>
</h:form>
UserData.java
@ManagedBean(name = "userData", eager = true)
@ApplicationScoped
public class UserData implements Serializable{
private static Map<String, String> countryMap;
private String selectedCountry = "United Kingdom";
static {
countryMap = new LinkedHashMap<String, String>();
countryMap.put("en", "United Kingdon");
countryMap.put("fr", "French");
countryMap.put("de", "German");
countryMap.put("def", "Default");
}
public String getSelectedCountry() {
return selectedCountry;
}
public void setSelectedCountry(String selectedCountry) {
this.selectedCountry = selectedCountry;
System.out.println("Locale set");
}
public Map<String, String> getCountries() {
return countryMap;
}
public void localeChanged(ValueChangeEvent event) {
selectedCountry = event.getNewValue().toString();
}
}
LocaleChangeListener.java
public class LocaleChangeListener implements ValueChangeListener {
@Override
public void processValueChange(ValueChangeEvent event) throws AbortProcessingException {
UserData userData = (UserData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userData");
String newLocale = event.getNewValue().toString();
if (newLocale != null)
userData.setSelectedCountry(newLocale);
else
userData.setSelectedCountry("Default");
}
}
当我在 Glassfish Server 上 运行 这些时,我得到一个 错误 ,
java.lang.NullPointerException
at com.cyb3rh4wk.test.LocaleChangeListener.processValueChange(LocaleChangeListener.java:25)
at com.sun.faces.facelets.tag.jsf.core.ValueChangeListenerHandler$LazyValueChangeListener.processValueChange(ValueChangeListenerHandler.java:128)
at javax.faces.event.ValueChangeEvent.processListener(ValueChangeEvent.java:134)
谁能帮我解决这个问题?
您得到 NullPointerException
因为在会话范围内找不到 userData
。
发生这种情况的原因是您将 userData
放在应用程序范围内(托管 bean 上的 @ApplicationScoped
注释)并在会话范围内搜索它。
尽管您已验证 userData
为 null,但它仍会打印 Locale set
,因为该 bean 位于上面 2.
中所述的应用程序范围内。
那么解决方法是什么?将 @ApplicationScoped
更改为 @SessionScoped
或通过更改访问您的 userData
:
UserData userData = (UserData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userData");
到
FacesContext ctx = FacesContext.getCurrentInstance();
UserData userData = (UserData)ctx.getExternalContext().getApplicationMap().get("userData");
我正在学习 JSF 事件处理,当我尝试 运行 一些示例代码时,出现空指针异常。
这是我的 index.xhtml 片段,
<h:form>
<h2>Implement valueChangeListener</h2>
<hr />
<h:panelGrid columns="2">
Selected Locale:
<h:selectOneMenu value="#{userData.selectedCountry}" onchange="submit()">
<f:valueChangeListener type="com.cyb3rh4wk.test.LocaleChangeListener" />
<f:selectItems value="#{userData.countries}" />
</h:selectOneMenu>
Country Name:
<h:outputText id="countryInterface" value="#{userData.selectedCountry}" />
</h:panelGrid>
</h:form>
UserData.java
@ManagedBean(name = "userData", eager = true)
@ApplicationScoped
public class UserData implements Serializable{
private static Map<String, String> countryMap;
private String selectedCountry = "United Kingdom";
static {
countryMap = new LinkedHashMap<String, String>();
countryMap.put("en", "United Kingdon");
countryMap.put("fr", "French");
countryMap.put("de", "German");
countryMap.put("def", "Default");
}
public String getSelectedCountry() {
return selectedCountry;
}
public void setSelectedCountry(String selectedCountry) {
this.selectedCountry = selectedCountry;
System.out.println("Locale set");
}
public Map<String, String> getCountries() {
return countryMap;
}
public void localeChanged(ValueChangeEvent event) {
selectedCountry = event.getNewValue().toString();
}
}
LocaleChangeListener.java
public class LocaleChangeListener implements ValueChangeListener {
@Override
public void processValueChange(ValueChangeEvent event) throws AbortProcessingException {
UserData userData = (UserData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userData");
String newLocale = event.getNewValue().toString();
if (newLocale != null)
userData.setSelectedCountry(newLocale);
else
userData.setSelectedCountry("Default");
}
}
当我在 Glassfish Server 上 运行 这些时,我得到一个 错误 ,
java.lang.NullPointerException
at com.cyb3rh4wk.test.LocaleChangeListener.processValueChange(LocaleChangeListener.java:25)
at com.sun.faces.facelets.tag.jsf.core.ValueChangeListenerHandler$LazyValueChangeListener.processValueChange(ValueChangeListenerHandler.java:128)
at javax.faces.event.ValueChangeEvent.processListener(ValueChangeEvent.java:134)
谁能帮我解决这个问题?
您得到
NullPointerException
因为在会话范围内找不到userData
。发生这种情况的原因是您将
userData
放在应用程序范围内(托管 bean 上的@ApplicationScoped
注释)并在会话范围内搜索它。尽管您已验证
userData
为 null,但它仍会打印Locale set
,因为该 bean 位于上面2.
中所述的应用程序范围内。那么解决方法是什么?将
@ApplicationScoped
更改为@SessionScoped
或通过更改访问您的userData
:UserData userData = (UserData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userData");
到
FacesContext ctx = FacesContext.getCurrentInstance();
UserData userData = (UserData)ctx.getExternalContext().getApplicationMap().get("userData");