Reputation: 500
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
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
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.
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
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}
.
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