0

I am learning JSF Event Handling and when I try to run some sample code, I am getting a Null Pointer Exception.

This is my index.xhtml snippet,

<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");   
    } 
}

When I run these on Glassfish Server, I get an error,

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)

Can anyone help me with this ?

Shinchan
  • 572
  • 2
  • 5
  • 16

1 Answers1

1
  1. You are getting NullPointerException because userData is not found in the session scope.

  2. The reason this is happening is that you put the userData in the application scope (@ApplicationScoped annotation on your managed bean) and searching it in the session scope.

  3. Eventhough you verified that userData is null it still prints Locale set because the bean is in the application scope as described in 2. above.

  4. So what is the solution? Either change @ApplicationScoped to @SessionScoped or access your userData by changing:

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

to

    FacesContext ctx = FacesContext.getCurrentInstance();
    UserData userData = (UserData)ctx.getExternalContext().getApplicationMap().get("userData");
ujulu
  • 3,289
  • 2
  • 11
  • 14