2

Im trying to create a JSF page that lets the user select X amount of ingredients, and then saves those selected ingredients to a list.

Ingredient is an object with two values, String IngredientName and int ingredientPrice.

What I want to do is to create 1 selectItem per Ingredient in an IngredientList (dynamically sized), and then save the selected items to another list of ingredients.

I've tried doing this multiple different ways but either I get classcast exceptions or the checkboxes don't appear at all.

My Bean:

@ManagedBean
@SessionScoped
public class ManagedIngredientsBean {

@EJB
IngredientBean iBean;

private List<Ingredient> ingredientList;
private List<Ingredient> checkedOptions;
private List<SelectItem> selectList;

public ManagedIngredientsBean() {

}


public String createNew(){

    ingredientList = iBean.getAllIngredients();
    selectList = new ArrayList<SelectItem>(ingredientList.size());
    for(Ingredient i : ingredientList){
        selectList.add(new SelectItem(i.getIngredientName()));
    }

    return "createnew.xhtml";
}

public List<SelectItem> getSelectList() {
    return selectList;
}

public void setSelectList(List<SelectItem> selectList) {
    this.selectList = selectList;
}

public List<Ingredient> getCheckedOptions() {
    return checkedOptions;
}

public void setCheckedOptions(List<Ingredient> checkedOptions) {
    this.checkedOptions = checkedOptions;
}

public List<Ingredient> getIngredientList() {
    return ingredientList;
}

public void setIngredientList(List<Ingredient> ingredientList) {
    this.ingredientList = ingredientList;
}

@FacesConverter(value="userConverter")
public static class UserConverter implements Converter {
    public Object getAsObject(FacesContext facesContext,
                              UIComponent component, String value) {
        return value;
    }

    public String getAsString(FacesContext facesContext,
                              UIComponent component, Object o) {
        Ingredient i = (Ingredient) o;
        return i.getIngredientName();

    }
}
}

IngredientBean used to get the Ingredient items from the persistence database and returning them as a list:

@Stateless(name = "IngredientEJB")
public class IngredientBean {

    EntityManagerFactory entFactory;
    EntityManager em;

    public IngredientBean() {
        entFactory = Persistence.createEntityManagerFactory("NewPersistenceUnit");
        em = entFactory.createEntityManager();
    }

    public List<Ingredient> getAllIngredients(){
        TypedQuery<Ingredient> ingQuery = em.createQuery("SELECT i FROM Ingredient i", Ingredient.class);
        List<Ingredient> iList =  ingQuery.getResultList();

        return iList;

    }
}

My JSF Page:

<!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:f="http://xmlns.jcp.org/jsf/core">

<h:head>
    <title>Create New Order</title>
</h:head>

<h:body>
    <h:form>
        <h:selectManyCheckbox value = "#{managedIngredientsBean.checkedOptions}">
                <f:converter converterId="userConverter"/>
                <f:selectItem value = "#{managedIngredientsBean.selectList}" var = "item" itemLabel = "#{item.getIngredientName()}" itemValue = "#{item}"/>
        </h:selectManyCheckbox>
    </h:form>

</h:body>

</html>

I'm probably missing something obvious or simply misunderstanding how to use the selectManyCheckbox element but I'm completely stuck on how to fix this. Appreciate any answers on how I should be implementing this. :)

Edit: Forgot to mention, the createNew() method in the managed bean is called in the previous JSF page and redirects to this one.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Hallow
  • 103
  • 1
  • 2
  • 10
  • This isn't an old fashioned forum. This is a question & answer site. There's no need to yell "SOLVED" in title once you got the answer. Just mark the answer accepted. The question will appear as answered (and thus, "solved") in the listing and the search. Or, if no one of the answers actually helped in understanding and solving the problem, and you figured a completely different answer on your own, post it as a true answer yourself instead of malforming the question. – BalusC Dec 06 '13 at 15:46
  • I solved it myself and I will add the solution when I have the time. Just figured I'd make sure no one wasted their time on this in the meantime. Sorry if it was a breach of etiquette :) – Hallow Dec 06 '13 at 15:52
  • I know. All I'm saying is: Just post the answer as an answer, not as a question. Otherwise other people will stumble upon the eternal problem the discussion forums have: the inability to quickly find answers via search. – BalusC Dec 06 '13 at 15:53

1 Answers1

2

your converter is broken.

first, it have to be a bean so must not be a static class.

second, it "should" be symmetric:

x.equals(c.getAsObject(ctx, comp, c.getAsString(ctx, component, x))); "should" be true.

@FacesConverter(value="userConverter")
public class UserConverter implements Converter 
{
    public Object getAsObject(FacesContext facesContext, UIComponent component, String value) 
    {
        return database.loadIngredientByUniqueValue(value);
    }

    public String getAsString(FacesContext facesContext,UIComponent component, Object o) 
    {
        Ingredient i = (Ingredient) o;
        return i.getSomeUniqueValue();
    }
}
Michele Mariotti
  • 7,372
  • 5
  • 41
  • 73
  • Not only that, `selectList` is also broken. – BalusC Dec 06 '13 at 11:20
  • Thanks for the response. I solved the problem by using arrays instead of lists and changing some code around. I'll post the answer here later :) – Hallow Dec 06 '13 at 15:08