sairn
sairn

Reputation: 500

Primefaces autocomplete widget getting error: Property 'label' not found on type java.lang.String

I am unable to successfully get the "p:autocomplete" widget to work...

Using the autocomplete widget, as shown here...

<p:autoComplete id="abc"  dropdown="true" value="#{testBean.parmMap['inputval']}" completeMethod="#{testBean.testList}" var="items" itemLabel="#{items.label}" itemValue="#{items}" converter="#{itemConverter}" ></p:autoComplete>

I am receiving the following error message...

javax.el.PropertyNotFoundException: /index.xhtml @18,245 itemLabel="#{items.label}": Property 'label' not found on type java.lang.String

I have not been able to get past this error. Not certain where the problem lies --I've included most of the relevant code shown below. Thank you for any guidance you can provide me!

Here is the entire facelets page - index.xhtml...

<?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:util="http://java.sun.com/jsf/composite/util"      
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:p="http://primefaces.org/ui">      
    <f:view contentType="text/html">
        <h:head>
            <title>testprimeac</title>
            <meta charset="utf-8" />
        </h:head>
        <h:body>
            <h:form id="form1">
                <p:autoComplete id="abc"  dropdown="true" value="#{testBean.parmMap['inputval']}" completeMethod="#{testBean.testList}" var="items" itemLabel="#{items.label}" itemValue="#{items}" converter="#{itemConverter}" ></p:autoComplete>
            </h:form>
        </h:body>
    </f:view>
</html>`

Here is the "Item" class...

package aaa.bbb.ccc.war;

public class Item
{

    private String label;
    private String value;

    public String getLabel()
    {
        return label;
    }

    public void setLabel(String label)
    {
        this.label = label;
    }

    public String getValue()
    {
        return value;
    }

    public void setValue(String value)
    {
        this.value = value;
    }
}

Here is the ItemConverter class... package aaa.bbb.ccc.war;

import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;

public class ItemConverter implements Converter
{

    @Override
    public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue)
    {
        if (submittedValue.trim().equals(""))
        {
            return null;
        }
        else
        {
            itemList = getItemList();

            try
            {
                for (Item item : itemList)
                {
                    if (item.getValue().equalsIgnoreCase(submittedValue))
                    {
                        return item;
                    }
                }

            }
            catch (Exception e)
            {
                throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid item object"));
            }
        }

        return null;
    }

    @Override
    public String getAsString(FacesContext facesContext, UIComponent component, Object value)
    {
        if (value == null || value.equals(""))
        {
            return "";
        }
        else
        {
            return String.valueOf(((Item) value).getValue());
        }
    }
    private static List<Item> itemList;

    private static List<Item> getItemList()
    {
        if (null == itemList)
        {
            refData = getRefData();
            itemList = refData.getTestList();
        }

        return itemList;
    }
    private static RefData refData;

    private static RefData getRefData()
    {
        refData = (RefData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("refData");
        if (null == refData)
        {
            refData = new RefData();
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("refData", refData);
        }
        return refData;
    }
}

Here is the TestBean class... package aaa.bbb.ccc.war;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component("testBean")
@Scope("request")
public class TestBean implements Serializable
{

    private RefData refData;
    private LinkedHashMap<String, String> parmMap;

    public TestBean()
    {
    }

    public Map<String, String> getParmMap()
    {
        refData = getRefData();
        return refData.getParmMap();
    }

    public void setParmMap(LinkedHashMap<String, String> m)
    {
        refData = getRefData();
        refData.setParmMap(m);
        storeRefData(refData);
    }

    public void setTestList(List<Item> list) throws Exception
    {
        try
        {
            refData = getRefData();
            refData.setTestList(list);
            storeRefData(refData);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public List<Item> getTestList()
    {
        refData = getRefData();
        return refData.getTestList();
    }

    private static RefData getRefData()
    {
        RefData refData = (RefData) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("refData");
        if (null == refData)
        {
            refData = new RefData();
            FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("refData", refData);
        }
        return refData;
    }

    private static void storeRefData(RefData r)
    {
        FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("refData", r);
    }
}

Here is the RefData class (referred to in TestBean)... package aaa.bbb.ccc.war;

import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

public class RefData implements Serializable
{

    public RefData() //(String key)
    {
    }
    private static final Map<String, String> listBoxEntryMap;

    static
    {
        Map<String, String> m = new LinkedHashMap<String, String>();
        m.put("aaavalue", "aaalabel");
        m.put("bbbvalue", "aablabel");
        m.put("cccvalue", "abblabel");
        m.put("dddvalue", "bbblabel");
        m.put("eeevalue", "bbclabel");
        m.put("fffvalue", "bcclabel");
        m.put("gggvalue", "ccclabel");
        m.put("hhhvalue", "ccalabel");
        m.put("iiivalue", "caalabel");
        m.put("jjjvalue", "aaclabel");
        m.put("kkkvalue", "acclabel");
        m.put("lllvalue", "bbalabel");
        m.put("mmmvalue", "baalabel");

        listBoxEntryMap = Collections.unmodifiableMap(m);
    }
    private Map<String, String> parmMap;

    public Map getParmMap()
    {
        if (null == this.parmMap)
        {
            this.parmMap = new LinkedHashMap<String, String>();
            this.parmMap.put("inputval", "");
        }

        return this.parmMap;
    }

    public void setParmMap(Map m)
    {
        this.parmMap = m;
    }
    List<Item> testList = new ArrayList<Item>();

    public void setTestList(List<Item> data) throws IOException
    {
        testList = data;
    }

    public List<Item> getTestList()
    {
        try
        {
            if (null == testList || testList.isEmpty())
            {
                testList = getListOfItems();
            }

            return testList; //(list);
        }
        catch (Exception ex)
        {
            java.util.logging.Logger.getLogger(RefData.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;
    }

    public static List<Item> getListOfItems()
    {
        List<Item> list = null;
        try
        {
            Map<String, String> map = listBoxEntryMap;
            Iterator iter = map.keySet().iterator();

            list = new ArrayList<Item>();
            Item item = null;

            while (iter.hasNext())
            {
                String key = (String) iter.next();
                String val = (String) map.get(key);
                item = new Item();
                item.setLabel(key);
                item.setValue(val);
                list.add(item);
            }
        }
        catch (Exception e)
        {
            System.out.println("Exception during query call..." + e.getMessage());
            e.printStackTrace();
        }

        return list;
    }
}

FWIW - Here is the pom.xml (which includes the primefaces dependency)...

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>aaa.bbb.ccc</groupId>
    <artifactId>testprimeac-war</artifactId>
    <packaging>war</packaging>
    <version>1</version>
    <name>testprimeac-war</name>
    <url>http://maven.apache.org</url>
    <properties>
        <org.springframework-version>3.1.1.RELEASE</org.springframework-version>
        <jsf-version>2.1.11</jsf-version>
    </properties>    
    <dependencies>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>                
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.1.11</version>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.1.11</version>
        </dependency>
        <dependency>
            <groupId>javax.el</groupId>
            <artifactId>el-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.web</groupId>
            <artifactId>el-impl</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>        
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>3.4.2</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
            </plugin>
        </plugins>
        <finalName>testprimeac-${project.version}</finalName>       
    </build>
</project>

Upvotes: 3

Views: 6297

Answers (1)

kolossus
kolossus

Reputation: 20691

+1 for the assertions you made in your first paragraph: You do have too much information on here and the converter is unnecessary since you're binding to a basic String type.

The two main issues I see here Are

  1. your choice to not use a type-safe collection in your value binding. Using a plain LinkedHashMap to hold String values will most likely cause problems as they will be stored as objects, I don't think the compiler is obliged to do any autoboxing for you here.

  2. Your backing completeMethod implementation is essentially returninglkp a store of String objects. This is what provides the variable for var in the autocomplete . To state the obvious, you can't call getLabel() on that.

You can proceed either of 2 ways

  1. Change your data store to a typesafe LinkedList of Strings , Lose the converter and you should be fine. Your var will be plain item and itemLabel and itemValue will both be #{item}.

  2. Implement a POJO to encapsulate the selection object, keep the converter and then your backing data store becomes a simple list of your POJO and also your selection becomes an instance of the POJO instead of a String

EDIT: With your clarifications, the problem is as a result of the discrepancy in the type returned by the autocomplete dropdown (Type item) and the value binding of the autocomplete to the backing bean (String type). The type returned by the dropdown selection must be the same as the type you're binding to in the backing bean.

Upvotes: 2

Related Questions