tags:

views:

54

answers:

1

Hi there! I currently have a JSF application that uses two listboxes. The first, say ListBox1, contains a list of manufacturers; each option comes from the database (via a method getManufacturers in a class called QueryUtil), is populated dynamically, and its value is an integer ID. This part works so far.

My goal is to populate a second listbox, say ListBox2, with a list of products sold by the manufacturer. This list of products will come from the database as well (products are linked to a manufacturer via a foreign key relationship, via a method getProducts in my QueryUtil class). How do I go about doing this? Please bear in mind that I've been working with JSF for under 24 hours; I'm willing to accept the fact that I'm missing something very rudimentary.

Again, I've been able to populate the list of manufacturers just fine; unfortunately, adding the Products component gives me java.lang.IllegalArgumentException: argument type mismatch

faces-config.xml

<managed-bean>
  <managed-bean-name>ProductsBean</managed-bean-name>
  <managed-bean-class>com.nieltown.ProductsBean</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
  <managed-property>
    <property-name>manufacturers</property-name>
    <property-class>java.util.ArrayList</property-class>
    <value>#{manufacturers}</value>
  </managed-property>
  <managed-property>
    <property-name>selectedManufacturer</property-name>
    <property-class>java.lang.Integer</property-name>
    <value>#{selectedManufacturer}</value>
  </managed-property>
  <managed-property>
    <property-name>products</property-name>
    <property-class>java.util.ArrayList</property-class>
    <value>#{products}</value>
  </managed-property>
  <managed-property>
    <property-name>selectedProduct</property-name>
    <property-class>java.lang.Integer</property-name>
    <value>#{selectedProducts}</value>
  <managed-property>
</managed-bean>

com.nieltown.ProductsBean

public class ProductsBean {

  private List<SelectItem> manufacturers;
  private List<SelectItem> products;
  private Integer selectedManufacturer;
  private Integer selectedProduct;

  public ProductsBean() {}

    public Integer getSelectedManufacturer(){

        return selectedManufacturer;

    }

    public void setSelectedManufacturer(Integer m){

        selectedManufacturer = m;

    }

    public Integer getSelectedProduct(){

        return selectedProduct;

    }

    public void setSelectedProduct(Integer p){

        selectedProduct = p;

    }  

    public List<SelectItem> getManufacturers(){

        if(manufacturers == null){
            SelectItem option;
            plans = new ArrayList<SelectItem>();
            QueryUtil qu = new QueryUtil();
            Map<Integer, String> manufacturersMap = qu.getManufacturers();
            for(Map.Entry<Integer, String> entry : manufacturersMap.entrySet()){
                option = new SelectItem(entry.getKey(),entry.getValue());
                manufacturers.add(option);

            }
        }
        return manufacturers;

    }

    public void setManufacturers(List<SelectItem> l){

        manufacturers = l;

    }

    public List<SelectItem> getProducts(){

        if(products == null){
            SelectItem option;
            products = new ArrayList<SelectItem>();
            if(selectedPlan != null){
                PMTQueryUtil pqu = new PMTQueryUtil();
                Map<Integer, String> productsMap = pqu.getProducts();
                for(Map.Entry<Integer, String> entry : productsMap.entrySet()){
                    option = new SelectItem(entry.getKey(),entry.getValue());
                    products.add(option);
                }
            }
        }
        return products;
    }

    public void setProducts(List<SelectItem> l){

        products = l;

    }
}

JSP fragment

<h:selectOneListbox id="manufacturerList"
    value="#{ProductsBean.selectedManufacturer}"
    size="10">
    <f:selectItems value="#{ProductsBean.manufacturers}" />
</h:selectOneListbox>
<h:selectOneListbox id="productList"
    value="#{PendingPlansBean.selectedProduct}"
    size="10">
    <f:selectItems binding="#{ProductsBean.products}" />
</h:selectOneListbox>
+2  A: 
<f:selectItems binding="#{ProductsBean.products}" />

You've mistakenly used the binding attribute instead of value. The binding attribute is generally only used to bind the control instances to beans. This is probably the source of the exception because it is expecting the type UIComponent and getting List<SelectItems>.

  <managed-property>
    <property-name>manufacturers</property-name>
    <property-class>java.util.ArrayList</property-class>
    <value>#{manufacturers}</value>
  </managed-property>

Managed properties are a form of dependency injection. By defining the property above, you tell the JSF framework to resolve #{manufacturers} and set it via setManufacturers when the ProductBean is instantiated. At best, this is harmless code that does nothing because there's no variable called manufacturers in any of the scopes; but this mistake may lead to bugs further down the line.

McDowell
Unfortunately, using "value" instead of "binding" was what I tried first. I don't get the exception, but the list of products isn't automatically populated when I select a manufacturer. That's what I'm really trying to do.I may be barking up the wrong tree here; the solution I need may require something more than just a modification of how I set up my bean and JSF controls. Do I need to add an onClick event to the manufacturer list that makes an AJAX call to populate the list of products once a manufacturer has been selected?
nieltown
You need some form of data submission to the server to set the `selectedManufacturer` prior to generating the products list. This could be via an onclick, a button (, or AJAX assuming your chosen JSF stack supports it). I recommend familiarizing yourself with the JSF lifecycle and learn when it can cause your bean methods to be invoked. http://java.sun.com/javaee/5/docs/tutorial/doc/bnaqq.html
McDowell