【问题标题】:Primefaces autocomplete widget getting error: Property 'label' not found on type java.lang.StringPrimefaces 自动完成小部件出现错误:在 java.lang.String 类型上找不到属性“标签”
【发布时间】:2012-11-22 09:18:57
【问题描述】:

我无法成功让“p:autocomplete”小部件工作...

使用自动完成小部件,如下所示...

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

我收到以下错误消息...

javax.el.PropertyNotFoundException: /index.xhtml @18,245 itemLabel="#{items.label}": 在 java.lang.String 类型上找不到属性“标签”

我无法克服这个错误。不确定问题出在哪里 --我已经包含了下面显示的大部分相关代码。感谢您为我提供的任何指导!

这是整个 facelets 页面 - 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>`

这里是“Item”类...

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;
    }
}

这里是 ItemConverter 类... 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;
    }
}

这是 TestBean 类... 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);
    }
}

这里是 RefData 类(在 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 - 这是 pom.xml(包括 primefaces 依赖项)...

<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>

【问题讨论】:

  • 完整方法应该没有String的参数吗?该方法甚至被调用了吗?

标签: jsf-2 autocomplete primefaces


【解决方案1】:

+1 对于您在第一段中所做的断言:您在此处确实有太多信息,并且转换器是不必要的,因为您绑定到基本的 String 类型。

我在这里看到的两个主要问题是

  1. 您选择在值绑定中不使用类型安全集合。使用普通的LinkedHashMap 来保存字符串值很可能会导致问题,因为它们将被存储为对象,我认为编译器没有义务在这里为你做任何自动装箱。

  2. 您的支持completeMethod 实现本质上是返回lkp 存储String 对象。这就是在 autocomplete 中为 var 提供变量的原因。很明显,你不能打电话给getLabel()

您可以通过以下两种方式中的任何一种进行操作

  1. 将您的数据存储更改为 Strings 的类型安全 LinkedList,丢失转换器,您应该没问题。您的var 将是普通的itemitemLabelitemValue 都将是#{item}

  2. 实现一个 POJO 来封装选择对象,保留转换器,然后您的支持数据存储成为您的 POJO 的简单列表,并且您的选择成为 POJO 的实例而不是字符串

编辑:经过您的澄清,问题是由于自动完成下拉列表返回的类型(类型item)和自动完成与支持bean的value绑定(String类型)存在差异)。下拉选择返回的类型必须与您在支持 bean 中绑定的类型相同。

【讨论】:

  • 嗨 K - 感谢您的回复!我正在使用类型安全,例如“LinkedHashMap”...但是,引用似乎已被删除(可能是论坛标记使用不当?)。 “完整方法”也返回一个类型安全的 Item 对象列表(即“List”)。无论如何,我原以为“var”属性会像“”一样。这是正确的吗?...--如果是这样,我希望“#{items.label}”在给定的 Item 对象上调用“getLabel”方法,因为“List”是通过迭代的。我是否正确理解了这些属性?再次感谢您的帮助!
  • 我对标记做了些微改动...看起来类型安全的泛型现在正在显示...thx sd
  • @sairn,考虑到所有事情,我认为您应该将自动完成的 value 绑定到您的支持 bean 中的独立 POJO,而不是您尝试对 Map 执行的操作现在。您已将 itemValue 属性设置为 POJO 类型,尝试将其强制为 String 类型将失败
  • 嗨,K - 谢谢。也许我的问题是我误解了这些属性的作用。 (也许我把它倒过来了)——“值”属性是否应该指代填充自动完成的条目列表......即,public List getTestList()? --或者,它是指用户输入(或选择)的值吗?我曾认为“completeMethod”应该连接到“getTestList”方法。并且“值”属性代表用户输入。 FWIW - 根据我看到的 PrimeFaces 文档示例,我将“itemValue”设置为“#{items}”而不是“#{items.value}”......
  • Hi K...问题(澄清):在上面的例子中,我假设“value=”属性应该连接到用户输入/选择值的字符串值。您是否建议将其连接到与用户选择相对应的 Item 对象?...即,类似于“public Item getSelectedItem(){}”?再次感谢,s
猜你喜欢
  • 1970-01-01
  • 2016-09-16
  • 2016-01-10
  • 2019-11-05
  • 2012-05-22
  • 2012-06-06
  • 2015-05-12
  • 2016-09-22
相关资源
最近更新 更多