0
votes

i'm trying to use the primefaces autoComplete component with POJO.
I know i need a converter. I've successfully used it many time before. But this time i've a special requirement.
I need the POJO only to show many columns to the user, but when it's selected i only want to get one of his property (String), not the POJO itself.
When i've used autoComplete successfully it only with full POJO, I mean : use a list of POJO and on selection also get a POJO (and not only one of his property).

<p:autoComplete
        value="#{testBean.selectedA.val2}"
        completeMethod="#{testBean.testAutoComplete}"
        var="varB" 
        itemLabel="#{varB.val10}"
        itemValue="#{varB.val10}" 
        forceSelection="true" dropdown="true">

        <p:column>
            <h:outputText value="#{varB.val10}" />
        </p:column>
        <p:column>
            <h:outputText value="#{varB.val11}" />
        </p:column>

</p:autoComplete>

Here testBean.selectedA.val2 is of type String. In fact selectedA is a DTO, so inside all property are of primitive type, or String type, but no other POJO.
varB is a POJO
varB.val10 is of type String.
varB.val11 is of type String.

If in my backing bean testBean.selectedA.val2 is empty/null there is no problem. Now if i need to initialize this value (testBean.selectedA.val2) in the backing bean to show a value to the user i get one error. So i don't know how i can put a default value in the String property linked to the autoComplete

INFO  [stdout] (default task-15) /test.xhtml @26,42 itemLabel="#{varB.val10}": The class 'java.lang.String' does not have the property 'val10'.

I think my problem is because i use autoComplete with POJO list but only want a String property as a result.

The problem look like this one : Is this a bug in primefaces autocomplete?

Do you have any ideas ? Is it possible to use autoComplete in this conditions ? Thank in advance for your help.

Below are some additional informations.

My configuration :
Primefaces 5.1.6
Wildfly 8.1

Full stack trace :

11:00:32,915 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (default task-15) Error Rendering View[/test.xhtml]: javax.el.PropertyNotFoundException: /test.xhtml @26,42 itemLabel="#{varB.val10}": The class 'java.lang.String' does not have the property 'val10'.
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at org.primefaces.component.autocomplete.AutoComplete.getItemLabel(AutoComplete.java:152) [primefaces-5.1.6.jar:5.1.6]
    at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeInput(AutoCompleteRenderer.java:189) [primefaces-5.1.6.jar:5.1.6]
    at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeSingleMarkup(AutoCompleteRenderer.java:146) [primefaces-5.1.6.jar:5.1.6]
    at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeMarkup(AutoCompleteRenderer.java:129) [primefaces-5.1.6.jar:5.1.6]
    at org.primefaces.component.autocomplete.AutoCompleteRenderer.encodeEnd(AutoCompleteRenderer.java:107) [primefaces-5.1.6.jar:5.1.6]
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:312) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:889) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1857) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1860) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1860) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:461) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:133) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:337) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647) [jboss-jsf-api_2.2_spec-2.2.6.jar:2.2.6]
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:130) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at fr.legrain.solstyce.webapp.AuthFilter.doFilter(AuthFilter.java:65) [classes:]
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:132) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:85) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar:1.0.15.Final]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_25]
    at java.lang.Thread.run(Thread.java:724) [rt.jar:1.7.0_25]
Caused by: javax.el.PropertyNotFoundException: The class 'java.lang.String' does not have the property 'val10'.
    at javax.el.BeanELResolver.getBeanProperty(BeanELResolver.java:731) [jboss-el-api_3.0_spec-1.0.3.Final.jar:1.0.3.Final]
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:351) [jboss-el-api_3.0_spec-1.0.3.Final.jar:1.0.3.Final]
    at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) [jsf-impl-2.2.6-jbossorg-4.jar:]
    at com.sun.el.parser.AstValue.getValue(AstValue.java:140) [javax.el-3.0.0.jar:]
    at com.sun.el.parser.AstValue.getValue(AstValue.java:204) [javax.el-3.0.0.jar:]
    at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:226) [javax.el-3.0.0.jar:]
    at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) [weld-core-impl-2.2.5.Final.jar:2014-09-15 07:54]
    at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) [weld-core-impl-2.2.5.Final.jar:2014-09-15 07:54]
    at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) [jsf-impl-2.2.6-jbossorg-4.jar:]
    ... 56 more

I've tried to make here a simple example to show my problem.
The view test.xhtml :

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">

<h:head>
    <title>Test</title>
</h:head>
<h:body>

    <h:panelGrid columns="2" cellpadding="10">

        <p:outputLabel value="A.val1 : " />
        <p:inputText value="#{testBean.selectedA.val1}"/>

        <p:outputLabel value="A.val2 : " />
        <p:autoComplete
            value="#{testBean.selectedA.val2}"
            completeMethod="#{testBean.testAutoComplete}"
            var="varB" 
            itemLabel="#{varB.val10}"
            itemValue="#{varB.val10}" 
            forceSelection="true" dropdown="true">
            <p:column>
                <h:outputText value="#{varB.val10}" />
            </p:column>
            <p:column>
                <h:outputText value="#{varB.val11}" />
            </p:column>
        </p:autoComplete>

    </h:panelGrid>

</h:body>
</html>

The managed bean TestBean.java:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class TestBean implements Serializable {

    private static final long serialVersionUID = 7752061447417566324L;

    private A selectedA;

    private BService bService;

    @PostConstruct
        public void init() {
        bService = new BService();

        selectedA = new A();
        selectedA.setVal1("xxx");
        selectedA.setVal2("bb2"); //comment this line and there is no more problem
       }

    public List<B> testAutoComplete(String query) {
        List<B> allValues = bService.getAllValues();
        List<B> filteredValues = new ArrayList<B>();

        if(query==null || query.equals("")) {
            return allValues;
        } else {
            for (int i = 0; i < allValues.size(); i++) {
                B b = allValues.get(i);
                if(b.getVal10().toLowerCase().contains(query.toLowerCase())) {
                    filteredValues.add(b);
                }
            }
            return filteredValues;
        }
      }

    public A getSelectedA() {
        return selectedA;
    }

    public void setSelectedA(A selectedA) {
        this.selectedA = selectedA;
    }

}

The service BService.java :

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


public class BService implements Serializable {

    private static final long serialVersionUID = -7442506301755842723L;

    private static final List<B> allValues = new ArrayList<B>();

    public BService() {
        init();
    }

    public void init() {
        if(allValues.isEmpty()) {
            allValues.add(new B("aa1", "ab"));
            allValues.add(new B("bb2", "abc"));
            allValues.add(new B("ab3", "abcd"));
        }
    }

    public List<B> getAllValues() {
        return allValues;
    }

}

The converter BConverter.java :

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;


@FacesConverter(forClass=B.class)
public class BConverter implements Converter {

    private BService bService = new BService();

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object valueToRender) {
        if (valueToRender == null || valueToRender.equals("")) {  
            return "";  
        } else {  
            return String.valueOf(((B) valueToRender).getVal10());
        }  
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) {
        if (submittedValue.trim().equals("")) {  
            return null;  
        } else {  
            try {  
                //int number = Integer.parseInt(submittedValue);  
                return bService.getAllValues().get(bService.getAllValues().indexOf(submittedValue));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return submittedValue;
   }

}

The class A.java :

public class A {

    private String val1;
    private String val2;

    public A() {

    }

    public A(String val1, String val2) {
        super();
        this.val1 = val1;
        this.val2 = val2;
    }

    public String getVal1() {
        return val1;
    }

    public void setVal1(String val1) {
        this.val1 = val1;
    }

    public String getVal2() {
        return val2;
    }

    public void setVal2(String val2) {
        this.val2 = val2;
    }

}

The class B.java :

public class B {

    private String val10;
    private String val11;

    public B() {

    }

    public B(String val10, String val11) {
        super();
        this.val10 = val10;
        this.val11 = val11;
    }

    public String getVal10() {
        return val10;
    }
    public void setVal10(String val10) {
        this.val10 = val10;
    }
    public String getVal11() {
        return val11;
    }
    public void setVal11(String val11) {
        this.val11 = val11;
    }

}
1

1 Answers

0
votes

Your problem is here: The class 'java.lang.String' does not have the property 'val10'. it mean that you have value of type String and you try to get property val10 from this String which doesn't exist.

Your code has a mistake itemValue="#{varB.val10}" should be replaced by itemValue="#{varB}", and itemLabel="#{varB.val10}" can be eliminated because you use:

   `<p:column>
        <h:outputText value="#{varB.val10}" />
    </p:column>
    <p:column>
        <h:outputText value="#{varB.val11}" />
    </p:column>` 

To display values. Consider rewrite your code in such way:

<p:autoComplete
        value="#{testBean.selectedA.val2}"
        completeMethod="#{testBean.testAutoComplete}"
        var="varB" 
        itemValue="#{varB}"
        forceSelection="true" dropdown="true">

        <p:column>
            <h:outputText value="#{varB.val10}" />
        </p:column>
        <p:column>
            <h:outputText value="#{varB.val11}" />
        </p:column>

</p:autoComplete>

And value="#{testBean.selectedA.val2}" should pointing to the object of same type which you get from autocomplete method.