Issues when wrapping autoComplete in composite component

UI Components for JSF
Post Reply
ylazzari
Posts: 3
Joined: 31 Aug 2010, 16:28

01 Sep 2010, 17:43

Hi,

I'm trying to create a JSF 2.0 composite component that acts has a wrapper around an PrimeFaces autoComplete component. Here's a sample of what the composite looks like:

Code: Select all

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
                xmlns:p="http://primefaces.prime.com.tr/ui" 
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:composite="http://java.sun.com/jsf/composite">

    <composite:interface>
        <composite:attribute name="selectListener" method-signature="void selectListener(org.primefaces.event.SelectEvent)"/>
        <composite:attribute name="onSelectUpdate" type="java.lang.String"/>
    </composite:interface>

    <composite:implementation>
        <h:outputStylesheet library="css/common" name="test.css"/>
        <h:outputScript library="js/common" name="test.js" target="head"/>
        
        <p:autoComplete var="result" value="#{result}"
                        selectListener="#{cc.attrs.selectListener}"
                        completeMethod="#{testController.autoComplete}"
                        itemLabel="#{result.description}"
                        itemValue="#{result}"
                        minQueryLength="3"
                        onSelectUpdate="#{cc.attrs.onSelectUpdate}"/>

    </composite:implementation>

</ui:composition>
Then, in the client template, the component would be used like this:

Code: Select all

<common:autoCompleteWrapper selectListener="#{someOtherController.handleSelect}" onSelectUpdate="someId"/>
Right now, this generates the following exception when a result is selected:

Code: Select all

javax.faces.FacesException: Unable to resolve composite component from using page using EL expression '#{cc.attrs.selectListener}'
        at com.sun.faces.facelets.tag.TagAttributeImpl$AttributeLookupMethodExpression.invoke(TagAttributeImpl.java:441)
        at org.primefaces.component.autocomplete.AutoComplete.broadcast(AutoComplete.java:200)
        at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:785)
        at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1250)
        at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:77)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
        at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:334)
        at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1518)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:171)
        at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:651)
        at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:591)
        at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
        at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:87)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:158)
        at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:321)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:222)
        at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:166)
        at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:823)
        at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:720)
        at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013)
        at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:220)
        at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)
        at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)
        at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
        at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)
        at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)
        at com.sun.grizzly.ContextTask.run(ContextTask.java:69)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:530)
        at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:511)
        at java.lang.Thread.run(Thread.java:619)
Is my way of relaying the "selectListener" from a component attribute down to the actual PrimeFaces component correct? It seems to handle the "onSelectUpdate" attribute nicely but not the "selectListener". I did a similar test where I wrapped a PrimceFaces button component and relaying the actual button action works fine:

Code: Select all

....
<composite:attribute name="someAction" method-signature="java.lang.String someAction()"/>
....
<p:commandButton action="#{cc.attrs.someAction}" value="Some Label"/>
Is the problem only related to the way the autoComplete component handles its "selectListener" attribute?

Thank you very much for your help.

ylazzari
Posts: 3
Joined: 31 Aug 2010, 16:28

01 Sep 2010, 17:58

I'm using PrimeFaces 2.1 by the way.

And while we're on the subject of autoComplete, since the following issue is not yet addressed: http://code.google.com/p/primefaces/iss ... ail?id=759, I decided that I would try to do what I want to do by styling the results like so:

Code: Select all

<p:autoComplete var="result" itemLabel="<span class='some-class'>#{result.description}</span>"/>
The style gets applied fine to every single result but when a result is selected, the value in the text input box gets set to the literal value of the description, hence it contains the HTML markup as well. I haven't found a nice hook to tell it to use something else to put in the input text box or to leave the original search query string while the result is being handled. Any ideas?

Thanks.

cagatay.civici
Prime
Posts: 18616
Joined: 05 Jan 2009, 00:21
Location: Cybertron
Contact:

01 Sep 2010, 19:36

Yes, this is related to http://code.google.com/p/primefaces/iss ... ail?id=837

Since suggestions are json, you need to encode your html.

ylazzari
Posts: 3
Joined: 31 Aug 2010, 16:28

01 Sep 2010, 20:15

Thanks for the reference to the ticket. I'll be watching it.

As for the other problem, the problem is not that the HTML isn't properly encoded. My style is being applied fine to the results in the drop-down. Here's a sample of the JSON that comes back from an auto-complete request:

Code: Select all

{
    "results"
:
    [
        {"label":"<span class='some-class'>result 1</span>","data":"someClass@dd4f56"},
        {"label":"<span class='some-class'>result 2</span>","data":"someClass@183ae1c"},
        {"label":"<span class='some-class'>result 3</span>","data":"someClass@68c944"}
]
The results are correctly styled with the "some-class" style. The problem is when a result is selected, the vale of the "label" property of the selected result is assigned as the value of the input text of the widget. So if you type "res" in the text box, once you select a result, the text in the text box is switched to (literally) "<span class='some-class'>result 1</span>".

While the other issue that I mentioned is being worked on to allow more flexibility to style the results of the autoComplete, is there a way to disable the copying of the "label" property in the value of the input text without hacking JavaScript of that component?

dsoares74
Posts: 3
Joined: 28 Mar 2012, 16:56

13 Jun 2012, 18:32

Hello,

Did someone solve this problem with complete attritute? I'm trying to wrapper the autocomplete in my component, but no success like you could see in following stacktrace:

<composite:interface>
<composite:attribute name="labelPrompt" default="Id" required="false" />
<composite:attribute name="minQueryLength" default="3" required="false" type="java.lang.Integer" />
<composite:attribute name="searchCriteria" default="CONTAINS" required="false" type="java.lang.String" />
<composite:attribute name="addAction" />
<composite:attribute name="completeDescriptionAction" method-signature="java.util.List complete(java.lang.String)" />
<composite:attribute name="handleItemSelected" />
<composite:attribute name="converter" />
<composite:attribute name="managedBean" />
</composite:interface>

<!-- IMPLEMENTATION -->
<composite:implementation>
<h:form id="form" prependId="false" >

<h:panelGrid columns="4" title="Test">
#{cc.attrs.labelPrompt}

<p:autoComplete id="name" value="#{cc.attrs.managedBean.selectMember}"
completeMethod="#{cc.attrs.completeDescriptionAction}" var="_m"
itemLabel="#{_m.name}" itemValue="#{_m}" forceSelection="true"
converter="#{cc.attrs.converter}" minQueryLength="#{cc.attrs.minQueryLength}">

<p:column>#{_m.id}</p:column>
<p:column>#{_m.name}</p:column>

</p:autoComplete>
</h:panelGrid>

</h:form>
</composite:implementation>

10:15:15,532 AVISO [javax.enterprise.resource.webcontainer.jsf.lifecycle] (http-localhost-127.0.0.1-8080-5) javax.el.PropertyNotFoundException: /test.xhtml @19,97 completeDescriptionAction="#{emissaoController.completeMember}": The class 'br.org.fdte.jee.jsf.poc.controller.EmissaoController' does not have the property 'completeMember'.: javax.faces.FacesException: javax.el.PropertyNotFoundException: /test.xhtml @19,97 completeDescriptionAction="#{emissaoController.completeMember}": The class 'br.org.fdte.jee.jsf.poc.controller.EmissaoController' does not have the property 'completeMember'.
at javax.faces.component.UIComponentBase$AttributesMap.get(UIComponentBase.java:2364) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at com.sun.faces.el.CompositeComponentAttributesELResolver$ExpressionEvalMap.get(CompositeComponentAttributesELResolver.java:345) [jsf-impl-2.1.7-jbossorg-2.jar:]
at javax.el.MapELResolver.getValue(MapELResolver.java:196) [jboss-el-api_2.2_spec-1.0.0.Final.jar:1.0.0.Final]
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) [jsf-impl-2.1.7-jbossorg-2.jar:]
at org.apache.el.parser.AstValue.getValue(AstValue.java:169) [jbossweb-7.0.13.Final.jar:]
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189) [jbossweb-7.0.13.Final.jar:]
at org.jboss.weld.el.WeldValueExpression.getValue(WeldValueExpression.java:50) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at com.sun.faces.facelets.el.ContextualCompositeValueExpression.getValue(ContextualCompositeValueExpression.java:156) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.facelets.tag.TagAttributeImpl$AttributeLookupMethodExpression.invoke(TagAttributeImpl.java:442) [jsf-impl-2.1.7-jbossorg-2.jar:]
at org.primefaces.component.autocomplete.AutoComplete.broadcast(AutoComplete.java:340) [primefaces-3.3.RC1.jar:]
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:935) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.7-jbossorg-2.jar:]
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.1.7-jbossorg-2.jar:]
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:]
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:]
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:]
at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_32]
Caused by: javax.el.PropertyNotFoundException: /test.xhtml @19,97 completeDescriptionAction="#{emissaoController.completeMember}": The class 'br.org.fdte.jee.jsf.poc.controller.EmissaoController' does not have the property 'completeMember'.
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111) [jsf-impl-2.1.7-jbossorg-2.jar:]
at javax.faces.component.UIComponentBase$AttributesMap.get(UIComponentBase.java:2362) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final]
... 34 more

tehackio
Posts: 20
Joined: 04 Feb 2012, 14:55

26 Aug 2012, 18:58

Primefaces do not works on composite component.
Must be a requisite(impose) their.

I'm pain to get work p:autoComplete completeMethod inside composite component;
primefaces, jsf, tomcat/jboss latest stable;

arturo
Posts: 90
Joined: 23 Aug 2011, 09:57
Location: Mexico

26 Aug 2012, 19:09

It works fine for me, here is an example from my project, is a kind of SAP's Object Value Selector or Oracle's List of Values, but check how I map the completeMethod:

Code: Select all

<!-- INTERFACE -->
    <cc:interface componentType="OVSAutoComplete">
        <cc:attribute name="completeMethod" method-signature="java.util.List m(java.lang.String)" />
        <cc:attribute name="valueObject"/>
        <cc:attribute name="value"/>
        <cc:attribute name="converter"/>
        <cc:attribute name="var"/>
        <cc:attribute name="itemLabel"/>
        <cc:attribute name="itemValue"/>
        <cc:attribute name="label"/>
        <cc:attribute name="required" type="boolean"/>
        <cc:attribute name="OVSListener" method-signature="void m(cups.view.customUIComponents.events.OVSRequestEvent)"/>
        <cc:clientBehavior name="change" event="change" targets="#{cc.clientId}:input" default="true"/>
    </cc:interface>

    <!-- IMPLEMENTATION -->
    <cc:implementation>
        <div id="#{cc.clientId}" style="display: table;">
            <div style="display: table-row">

                    <p:autoComplete id="input" binding="#{cc.ac}" value="#{cc.attrs.valueObject}" required="#{cc.attrs.required}"
                                    converter="#{cc.attrs.converter}" completeMethod="#{cc.attrs.completeMethod}" label="#{cc.attrs.label}"
                                    var="#{cc.attrs.var}" itemLabel="#{cc.attrs.itemLabel}" itemValue="#{cc.attrs.itemValue}"
                                    style="display: table-cell">
                        <cc:insertChildren/>
                        <p:ajax event="change" listener="#{cc.onAutoCompleteBlur}"
                                process="@this" immediate="true" update="input"/>
                        <f:event type="postValidate" listener="#{cc.onAutoCompletePostValidate}"/>
                    </p:autoComplete>
                <div style="display: table-cell; width: 1px"> 
                    <p:commandButton id="button" icon="ui-icon-newwin" process="input @this" update="input"/>
                </div>
            </div>
        </div>
    </cc:implementation>
PrimeFaces 4.0 | Extensions 1.1.0 | GlassFish 4.0 | Mojarra 2.2.4 | NetBeans 7.3.1

tehackio
Posts: 20
Joined: 04 Feb 2012, 14:55

26 Aug 2012, 19:20

Do you create a converter for each entity? I'm using generic converter. The value always returns Object with autocomplete in composite component.

Code: Select all

	

....converter methods

@SuppressWarnings("unchecked")
    private Class getClazz(FacesContext facesContext, UIComponent component) {
       
    	ELContext elContext = facesContext.getELContext();
    	ValueExpression valueExpression = facesContext.getApplication().getExpressionFactory()
    	    .createValueExpression(elContext, component.getValueExpression("value").getExpressionString(), Location.class);
        
        return valueExpression.getType(facesContext.getELContext());
    }
primefaces, jsf, tomcat/jboss latest stable;

arturo
Posts: 90
Joined: 23 Aug 2011, 09:57
Location: Mexico

26 Aug 2012, 19:33

Yes, im using a converter for each entity.
Maybe there is a problem with your converter implementation, I would better try with generic programming: write an AbstractConverter<T> and then extend that converter for each concrete class like CityConverter extends AbstractConverter<City>, this way there is no need to infer the type as you did.
PrimeFaces 4.0 | Extensions 1.1.0 | GlassFish 4.0 | Mojarra 2.2.4 | NetBeans 7.3.1

tehackio
Posts: 20
Joined: 04 Feb 2012, 14:55

26 Aug 2012, 20:39

Did you can understand now?

Code: Select all

@FacesConverter(value="genericConverter")
public class GeneticConverter implements Serializable, Converter {

	private static final long serialVersionUID = 1L;

	@SuppressWarnings("unchecked")
	@Override
	public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
		if (value.trim().equals("")) {
			return null;
        } else {
            try {
            	return JPAUtil.getEntityManager().find(getClazz(facesContext, component), Integer.parseInt(value));
            } catch(Exception e) {
            	e.printStackTrace();
                throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Conversion Error"));
            }
        }
	}

	@Override
	public String getAsString(FacesContext facesContext, UIComponent component, Object value) {
        if (value == null || value.equals("")) {
            return "";
        } else {
            return String.valueOf(((Identifiable) value).getId());
        }
	}
	
	@SuppressWarnings("unchecked")
    private Class getClazz(FacesContext facesContext, UIComponent component) {
       
    	ELContext elContext = facesContext.getELContext();
    	ValueExpression valueExpression = facesContext.getApplication().getExpressionFactory()
    	    .createValueExpression(elContext, component.getValueExpression("value").getExpressionString(), Location.class);
        
        return valueExpression.getType(facesContext.getELContext());
    }
	
}
primefaces, jsf, tomcat/jboss latest stable;

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 9 guests