0

I have 2 SelectOneMenu as follows in the index.xhtml. The menu1 essentially chooses a language(sp or en) and menu2 displays the possible serial numbers(0 to 3). I have the init constructor(post constructor) which initialises the default values on the two Menus. However for some strange reason, if I select a serial number other than the default serial number for the language other than the default language, somehow the language gets reset to init default :(

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core">

    <h:head>
        <title>My page</title>
    </h:head>
    <h:body>
                            <div>
                                <h4>Change Existing Description</h4>
                            </div>
                            <h:form id="myForm">
                                    <h:panelGrid columns="4">
                                        <h:outputLabel value="Language:" />
                                        <h:selectOneMenu value="#{myBean.language}">
                                            <f:selectItems value="#{myBean.languages}" />
                                            <f:ajax listener="#{myBean.doUpdate}" render ="myForm" />
                                        </h:selectOneMenu>
                                        <h:outputLabel value="SerialID:" />
                                        <h:selectOneMenu value="#{myBean.serialID}">
                                            <f:selectItems value="#{myBean.serialIDs}" />
                                            <f:ajax listener="#{myBean.doUpdate}" render ="myForm" />
                                        </h:selectOneMenu>

                                    </h:panelGrid>
                                </h:form>
    </h:body>
</html>

Here is my Bean code. Where is the problem?? please advise!

package bean;



import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.Stateful;
import javax.enterprise.context.RequestScoped;
import javax.faces.bean.ManagedBean;



@ManagedBean(name = "myBean")
//@Stateless
@Stateful
@RequestScoped
public class MyBean {

    public static final int PERMISSIONS = 2;
    private List<String> languages;
    private String language;
    private int serialID;
    private List<Integer> serialIDs;

    /**
     * init() method for initializing the bean. Is called after constuction.
     */

    @PostConstruct
    private void init() {
    //public MyBean () {
        languages = getAllLanguages();
        language = "en"; //defaultLanguage 
        serialID = 3;
        serialIDs = getSerialIDsFromOverview();
    } 

    public List<String> getLanguages() {
        System.out.println("getLanguages, language " +language);
        return languages;
    }


    public int getPERMISSIONS() {
        return PERMISSIONS;
    }

    public String getLanguage() {
        System.out.println("getLanguage " +language);
        return language;
    }

    public void setLanguage(String language) {
        System.out.println("setLanguage " +language);
        this.language = language;
    }


    public int getSerialID() {
        System.out.println("getSerialID " +serialID);
        return serialID;
    }

    public void setSerialID(int serialID) {
          System.out.println("setSerialID " +serialID);
        this.serialID = serialID;
    }

    public List<Integer> getSerialIDs() {
        System.out.println("getSerialIDs language =  "+language );
        return serialIDs;
    }

    public List<String> getAllLanguages() {
        List<String> results = new ArrayList<String>();
        results.add("sp");
        results.add("en");

        if(results != null){
            System.out.println("getting all languages");
        }
        return results;
    }


    public void doUpdate() {

         System.out.println("doUpdate language " +language);
         System.out.println("doUpdate serialID " +serialID);

    }

    /**
     * Returns a list of all serialIDs present in the overview.
     * @return 
     */
    private List<Integer> getSerialIDsFromOverview() {
        List<Integer> results = new ArrayList<Integer>();
        results.add(0);
        results.add(1);
        results.add(2);
        results.add(3);
        return results;
    }

}

UPDATES:

After taking suggestions from cubbuk, I sat down and corrected my code with @ViewScoped annotation and making the bean implement Serializable. THIS WORKS. However, the next thing I had to do was include an @EJB annotation to call a stateless bean which calls the Entity manager to fetch the serialIDs from a database instead of "hardcoding" it. That is when I encounter the problem: Not serializable exception "java.io.NotSerializableException: bean.__EJB31_Generated__. How do I solve this? When I made myBean back to RequestScope and remove Serializable, I could run the code without problems however there the toggling of the menu to init values :(

By the way I check this post: @EJB in @ViewScoped managed bean causes java.io.NotSerializableException and set my STATE SAVING METHOD to server but that gives me "empy response from server" pop up message :( Please help!

Community
  • 1
  • 1
user907810
  • 3,208
  • 10
  • 39
  • 47
  • I can't verify by my workstation, but have you tried to add a id to a select (i.e. `` and to render this element ( ``) and not the form? – alepuzio Feb 04 '13 at 13:09
  • You should change the scope of your bean to ViewScoped. As your bean is requestScoped after each ajax call your init method is getting called again as the bean is constructed for each request. – cubbuk Feb 04 '13 at 13:25
  • @cubbuk : if I change it to "vieScoped" I get this error:java.io.NotSerializableException: bean.MyBean – user907810 Feb 04 '13 at 13:38
  • You need to implement Serializable in your backing bean. Here is the explanation for this necessity from the following post of BalusC: "Note that the bean needs to implement Serializable as it will be stored in the view map which is in turn stored in the session. Some servletcontainer configurations will namely store sessions on disk instead of in memory. This is also mandatory when you have configured JSF view state saving method to client instead of (default) server." – cubbuk Feb 04 '13 at 13:41
  • @alepuzio: I added an output label with id= lang which would output me the language and serial ID but sadly there is some random behaviour. When I chose "sp" I see the output label showing only "en" and when I change serial Id from anything other than default for "sp" I see the "default serial ID" – user907810 Feb 04 '13 at 14:02

1 Answers1

1

Since you are using @RequestScoped bean as your backing bean after each request your init method is getting called and your values are getting reset. To avoid that you need to use @ViewScoped bean as your backing bean. I updated your bean accordingly note that your backing bean now implements Serializable interface. This is needed as this bean will be stored in your servlet and it needs to be flushed to disk if the content can not be hold in the memory. For learning the details of @ViewScoped beans please check the following post:

http://balusc.blogspot.com/2010/06/benefits-and-pitfalls-of-viewscoped.html

Apart from these, for naming conventions I renamed your getAllLanguages and getSerialIDsFromOverview methods to initAllLanguages and initSerialIds as methods starting with get and set can be confusing because they are mostly used for getters and setters.

Lastly when you use f:ajax command by default the UIInput the ajax command is bind to is rendered and executed. Since you don't refresh the h:selectOneMenu menus according to the values of each other you don't need to render the whole form. The following will be enough for this case:

<h:form id="myForm">
                                    <h:panelGrid columns="4">
                                        <h:outputLabel value="Language:" />
                                        <h:selectOneMenu value="#{myBean.language}">
                                            <f:selectItems value="#{myBean.languages}" />
                                            <f:ajax listener="#{myBean.doUpdate}"/>
                                        </h:selectOneMenu>
                                        <h:outputLabel value="SerialID:" />
                                        <h:selectOneMenu value="#{myBean.serialID}">
                                            <f:selectItems value="#{myBean.serialIDs}" />
                                            <f:ajax listener="#{myBean.doUpdate}"/>
                                        </h:selectOneMenu>

                                    </h:panelGrid>
                                </h:form>

@ManagedBean
@ViewScoped
public class MyBean implements Serializable
{

    public static final int PERMISSIONS = 2;
    private List<String> languages;
    private String language;
    private int serialID;
    private List<Integer> serialIDs;

    /**
     * init() method for initializing the bean. Is called after constuction.
     */
    @PostConstruct
    protected void init()
    {
        //public MyBean () {
        System.out.println("lang: " + language);
        System.out.println("serialId: " + serialID);
        System.out.println("init is called");
        initAllLanguages();
        initSerialIds();
        language = "en"; //defaultLanguage 
        serialID = 3;
    }

    public List<String> getLanguages()
    {
        return languages;
    }

    public int getPERMISSIONS()
    {
        return PERMISSIONS;
    }

    public String getLanguage()
    {
        return language;
    }

    public void setLanguage(String language)
    {
        this.language = language;
    }

    public int getSerialID()
    {
        return serialID;
    }

    public void setSerialID(int serialID)
    {
        this.serialID = serialID;
    }

    public List<Integer> getSerialIDs()
    {
        return serialIDs;
    }

    private void initAllLanguages()
    {
        languages = new ArrayList<String>();
        languages.add("sp");
        languages.add("en");
    }

    public void doUpdate()
    {

        System.out.println("doUpdate language " + language);
        System.out.println("doUpdate serialID " + serialID);

    }

    /**
     * Returns a list of all serialIDs present in the overview.
     *
     * @return
     */
    private void initSerialIds()
    {
        serialIDs = new ArrayList<Integer>();
        serialIDs.add(0);
        serialIDs.add(1);
        serialIDs.add(2);
        serialIDs.add(3);
    }
}

Cheers

cubbuk
  • 7,800
  • 4
  • 35
  • 62
  • Thanks for the explanation. With your suggestion, I did implement Serializable and changed bean to ViewScoped. When I used the above code in a more elaborate layout of my web application where I have input text areas etc within the form. The ViewScoped simply doesnt update the form :( Is there a way to retain the RequestScope and still get this working? – user907810 Feb 04 '13 at 16:35
  • What do you mean by viewScoped doesn't update the form. You can update the form by specifying the input ids in the execute attribute of ajax. For example the following will update the parent form of your input. Btw @form is a shortcut defined by EL to retrieve the id of the parent form of the input which makes the ajax call. – cubbuk Feb 04 '13 at 17:48
  • Yes this is exactly what I used. However, although the language and serial Id changes when I choose them, the form doesnt seem to show the changed view as per the language and serial id in my complex code. – user489152 Feb 05 '13 at 14:23
  • If you are displaying the same language attribute somewhere outside the form, then you need to render that component through the `render` attribute. Assume that you show the language in a component with id `language` then you need an ajax command similar to following: If you are asking smtg else, please add some code to clarify yourself better. – cubbuk Feb 05 '13 at 14:46
  • I think I fpund out exactly where the problem occurs. I am going to update my Post. Please take a look. I am sure you have the answer :) – user907810 Feb 07 '13 at 10:17
  • Sorry mate I really have no idea =( – cubbuk Feb 07 '13 at 11:19