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)

谁能帮我解决这个问题?

  1. 您得到 NullPointerException 因为在会话范围内找不到 userData

  2. 发生这种情况的原因是您将 userData 放在应用程序范围内(托管 bean 上的 @ApplicationScoped 注释)并在会话范围内搜索它。

  3. 尽管您已验证 userData 为 null,但它仍会打印 Locale set,因为该 bean 位于上面 2. 中所述的应用程序范围内。

  4. 那么解决方法是什么?将 @ApplicationScoped 更改为 @SessionScoped 或通过更改访问您的 userData

    UserData userData = (UserData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("userData");
    

    FacesContext ctx = FacesContext.getCurrentInstance();
    UserData userData = (UserData)ctx.getExternalContext().getApplicationMap().get("userData");