Ошибка получения виджета автозаполнения Primefaces: свойство 'label' не найдено по типу java.lang.String

Я не могу успешно получить виджет "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}": свойство '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(который включает в себя зависимость между примитивами)...

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

Ответ 1

+1 для утверждений, сделанных вами в первом абзаце: у вас слишком много информации, и конвертер не нужен, поскольку вы привязываетесь к базовому типу String.

Две основные проблемы, которые я вижу здесь:

  • ваш выбор - не использовать коллекцию с безопасным типом в привязке значений. Использование простого LinkedHashMap для хранения значений String, скорее всего, вызовет проблемы, поскольку они будут сохранены как объекты, я не думаю, что компилятор обязан делать какие-либо автобоксины для вас здесь.

  • Реализация completeMethod вашей поддержки по существу возвращает lkp хранилище объектов String. Это то, что предоставляет переменную для var в автозаполнении. Чтобы заявить очевидное, вы не можете называть getLabel() на этом.

Вы можете продолжить один из двух способов.

  • Измените хранилище данных на тип LinkedList строк, потеряйте конвертер, и все будет в порядке. Ваш var будет простым item и itemLabel, а itemValue будет #{item}.

  • Внедрите POJO для инкапсуляции объекта выделения, сохраните конвертер, а затем резервное хранилище данных станет простым списком вашего POJO, а также ваш выбор станет экземпляром POJO вместо строки

EDIT: с вашими разъяснениями проблема заключается в несоответствии типа, возвращаемого выпадающим списком автозаполнения (Type item) и привязкой value автозаполнения к поддержке bean (String тип). Тип, возвращаемый выпадающим списком, должен быть таким же, как тип, с которым вы привязываетесь в резервной копии bean.