Composite method do not resolve parameter if in template - jsf-2

it's a bit similar to this problem https://issues.jboss.org/browse/RF-11469
I have a template containing a composite defined like this:
<h:form id="transfer_list">
<ccs:criteriaPanel header="Critère de recherche"
filterAction="#{controller.filter()}">
<form:criteriaForm bean="#{controller.transferCriteria}"
rendered="#{! empty controller.transferSearchForm}"
mode="UPDATE"
controller="#{controller}" />
</ccs:criteriaPanel>
</h:form>
Controller is defined with a ui:param in the template child.
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="/pages/transfer/transferList.xhtml">
<ui:param name="controller" value="#{transferListOpenController}" />
</ui:composition>
Here is the composite impl (criteriaPanel):
<cc:interface>
<cc:attribute name="header" default="#{i18n['HEADER_SEARCH_CRITERIA']}" />
<cc:attribute name="filterAction" method-signature="java.lang.Object filter()" />
<cc:attribute name="update" default="#(.ui-datatable)" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<p:panel header="#{cc.attrs.header}" toggleable="true">
<cc:insertChildren />
<f:facet name="footer">
<p:commandButton id="search_btn"
value="#{i18n['BUTTON_FILTER']}"
action="#{cc.attrs.filterAction}"
icon="ui-icon-search"
update="#{cc.attrs.update}" />
<p:commandButton value="#{i18n['BUTTON_CLEAR_FILTER']}"
action="#{cc.attrs.filterAction}"
process="#this"
immediate="true"
update="#{cc.attrs.update}">
<p:ajax update="#form" resetValues="true" />
</p:commandButton>
</f:facet>
<p:defaultCommand target="search_btn" />
</p:panel>
</div>
</cc:implementation>
Clicking on the button "filterAction" result into this:
javax.faces.FacesException: #{cc.attrs.filterAction}:
javax.el.PropertyNotFoundException: Target Unreachable, identifier
[controller] resolved to null at
com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
at
org.primefaces.application.DialogActionListener.processAction(DialogActionListener.java:45)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
I use Tomcat 8.5 for this and Mojarra 2.2.13. It works if I don't put the whole thing in a composite component (criteriaPanel)
UPDATE
Sample available here: https://github.com/Rapster/primefaces-test/tree/issue-sof-45834296
Works fine with MyFaces 2.2.11 and Mojarra 2.2.8-23 and 2.3.2 (I don't know how impactful upgrading to 2.3 can be though...) From what I read here https://stackoverflow.com/a/42656386/4605161, Mojarra 2.2.8 is aimed for WebLogic but it seems I will need this one (and i'm running on Tomcat)
WORKAROUND
Writing this make it work (but that's a workaround i'd rather use template):
<ui:composition xmlns="http://www.w3.org/1999/xhtml">
<ui:param name="controller" value="#{testView}" />
<ui:decorate template="/template.xhtml">
</ui:decorate>
</ui:composition>
Funny thing is if I put ui:param inside ui:decorate I'll end up with the same exception

Should be fixed in 2.2.15, see github.com/javaserverfaces/mojarra/issues/4271

Related

Cannot load WEB-INF from browser

I start test my app with primefaces and spring integration but I stop on p:commandButton component. When I click on it, I want show p:growl popup component like here, but unfortunately page is redirect to view in location /WEB-INF/WEB-INF/intro.xhtml (but view is located in /WEB-INF/intro.xhtml) with error of 'resource not found'. May be some one know the problem? I download some example project from GIT and then get the same problem. I change some view code in
/springmvcfacelets/src/main/webapp/templates/maintemplate.xhtml
and paste code from primefaces
<h:form>
<p:growl id="growl" life="2000" />
<p:commandButton value="Ajax Submit" id="ajax" update="growl" actionListener="#{buttonView.buttonAction}" styleClass="ui-priority-primary" />
<p:commandButton value="Non-Ajax Submit" id="nonAjax" actionListener="#{buttonView.buttonAction}" ajax="false" />
<p:commandButton value="With Icon" id="withIcon" actionListener="#{buttonView.buttonAction}" update="growl" icon="ui-icon-disk" />
<p:commandButton actionListener="#{buttonView.buttonAction}" id="iconOnly" update="growl" icon="ui-icon-disk" title="Icon Only" />
<p:commandButton value="Disabled" id="disabled" disabled="true" />
to body in view. Bean was also added and registered.
View code:
<?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: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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title><ui:insert name="title">Default title</ui:insert></title>
</h:head>
<h:body>
<h:form>
<p:panel id="panel" header="New User">
<h:form>
<p:growl id="growl" life="2000" />
<p:commandButton value="Ajax Submit" id="ajax" update="growl"
actionListener="#{buttonView.buttonAction}"
styleClass="ui-priority-primary" />
<p:commandButton value="Non-Ajax Submit" id="nonAjax"
actionListener="#{buttonView.buttonAction}" ajax="false" />
<p:commandButton value="With Icon" id="withIcon"
actionListener="#{buttonView.buttonAction}" update="growl"
icon="ui-icon-disk" />
<p:commandButton actionListener="#{buttonView.buttonAction}"
id="iconOnly" update="growl" icon="ui-icon-disk" title="Icon Only" />
<p:commandButton value="Disabled" id="disabled" disabled="true" />
</h:form>
</p:panel>
</h:form>
</h:body>
</html>
This has nothing to do with primefaces neither the commandbutton component.
You simply can't access files located in the WEB-INF directory using browser. It would be security bug. Web-Inf would be good for loading integrated tempates using <ui:include> (for example) or for storing your configuration (faces-config.xml, web.xml, app-context.xml ...).
Move your file to any other webapp directory excluding web-inf and change the submit result (where page goes, either from form action or from bean) and let us know the result.
Problem was in web.xml(missing appropriate path for JSF) file and in code of the view.

JSF 2.2 custom validator not triggered in ui:repeat

after a desperate period of trials and errors i come to you looking for help, since now i am even unsure if i am doing it all wrong.
My code below displays some fields from a user profile in read only input text boxes. The data comes from a bean as ArrayList of "field" objects, whos properties are described in the ui:param directives.
The user can click an unlock/lock button next to the box to start/finish editing her data.
I want to trigger input validation when the user presses enter after editing or clicks the lock button.
But whatever i tried, after editing and pressing enter or clicking the button, the changed value is not written back and my custom validator is not triggered. Somehow it seems that after clicking the button the then rendered input box is not bound to the field? However, the validator works (and all attributes get passed to it) if used in an input text that is always rendered - and i don't understand it :)
Please have a look at it. If i did not explain my intent well enough or if you need more code, please let me know.
Edit: the annotations of the backing bean:
#ManagedBean( name = "beanProfile" )
#RequestScoped
The jsf code:
<ui:composition>
<ui:param name="i18n" value="#{field.i18n}" />
<ui:param name="val" value="#{field.value}" />
<ui:param name="req" value="#{field.required}" />
<ui:param name="min" value="#{field.min}" />
<ui:param name="max" value="#{field.max}" />
<ui:param name="validationType" value="#{field.validationType}" />
<ui:param name="useHidden" value="#{field.hidden}" />
<ui:param name="locked" value="#{field.locked}" />
<ui:param name="fullName" value="#{beanProfile.name}" />
<h:form id="profileFrm">
<h:outputText value="#{msg.role_profile} " styleClass="headingOutputText" />
<h:outputText value="#{fullName}" styleClass="headerTitle" />
<p />
<h:panelGroup>
<ui:repeat var="field" value="#{beanProfile.userFields}">
<h:panelGrid columns="2">
<h:outputText value="#{msg[i18n]}" styleClass="headerTitle" />
<h:message showDetail="true" for="visInput" styleClass="warn"
rendered="#{!useHidden}" />
<h:message showDetail="true" for="invisInput" styleClass="warn"
rendered="#{useHidden}" />
</h:panelGrid>
<h:panelGrid columns="2" columnClasses="nameColumn">
<h:inputText id="visInput" required="true" value="#{val}"
rendered="#{!useHidden}" readonly="#{locked}" >
<f:validator validatorId="customValidator" />
<f:attribute name="requiredField" value="#{req}" />
<f:attribute name="minLen" value="#{min}" />
<f:attribute name="maxLen" value="#{max}" />
<f:attribute name="type" value="#{validationType}" />
</h:inputText>
<h:inputSecret id="invisInput" required="true" value="#{val}"
rendered="#{useHidden}" readonly="#{locked}">
<f:validator validatorId="customValidator" />
<f:attribute name="requiredField" value="#{req}" />
<f:attribute name="minLen" value="#{min}" />
<f:attribute name="maxLen" value="#{max}" />
<f:attribute name="type" value="#{validationType}" />
</h:inputSecret>
<h:commandLink id="lock" action="#{beanProfile.lock(field)}"
rendered="#{!locked}" title="#{msg.profile_lock}">
<h:graphicImage height="16" width="16"
name="images/padlock_unlocked.svg" alt="#{msg.profile_lock}" />
</h:commandLink>
<h:commandLink id="unlock" action="#{beanProfile.unlock(field)}"
rendered="#{locked}" title="#{msg.profile_unlock}">
<h:graphicImage height="16" width="16"
name="images/padlock_locked.svg" alt="#{msg.profile_unlock}" />
</h:commandLink>
</h:panelGrid>
</ui:repeat>
</h:panelGroup>
<p />
<h:commandButton id="submitProfileBtn" value="#{msg.cmd_submit}"
styleClass="button" includeViewParams="true"
action="#{beanProfile.submitProfile()}" />
</h:form>
</ui:composition>
The origin of your problem is that you are using the RequestScoped scope for your backing bean containing the Model, so when you want to do a postback request in order to execute the backing bean method the binding just have dissapeared (not in the server memory) and the JSF lifecycle doesn't execute as expected. The solution is to use a longer scope as the ViewScoped scope. Ideally you should use the CDI compatible viewScoped scope, so you have to use JSF 2.2.x version.
Thank you lametaweb, you led me in the right direction.
Being unable to use the #ViewScoped annotation i found the link
how-to-install-cdi-in-tomcat
and followed BalusC's directions for using CDI in Tomcat. Then i had to let all the java classes implement the Serializable interface.
Now i can use the #ViewScoped annotation and the validator gets triggered.

binding on p:dataTable which is included multiple times causes ID unqiueness exceptions

I'm attempting to use a special PrimeFaces data exporter implementation as being used in this answer:
https://stackoverflow.com/a/14413932/396732
Our use case however is a little more complex, e.g. using Facelets to show the respective datatable for export, which has row expansions with sub tables in them.
insiderListManagerDialogs.xhtml:
<ui:include src="insiderListManagerListDialog.xhtml">
<ui:param name="idPrefix" value="il-emp" />
<ui:param name="widgetVarPrefix" value="ilEmp" />
<ui:param name="dialogTitle" value="#{msg['entity.employee.internal.plural.label']}" />
<ui:param name="mapPropertyName" value="insiderListEmployeesMap" />
<ui:param name="sortColumn" value="#{ent.lastTime}" />
<ui:param name="keyColumnsXhtml" value="listDialogInsiderListKeyColumns.xhtml" />
<ui:param name="valueColumnsXhtml" value="listDialogEmployeeValueColumns.xhtml" />
</ui:include>
insiderListManagerListDialog.xhtml:
<p:dialog id="#{idPrefix}-il-view-dialog"
widgetVar="#{widgetVarPrefix}Dialog"
header="#{dialogTitle}"
modal="true"
resizable="false"
appendToBody="true"
onShow="resetFilterInput( '#{idPrefix}' );"
width="1000"
height="750">
<h:form id="#{idPrefix}-il-view-form">
<p:dataTable id="list-entities"
widgetVar="listEntitiesTable"
binding="#{table}"
value="#{insiderListManager.listInstances}"
var="key"
scrollable="true"
scrollHeight="625"
scrollWidth="985"
resizableColumns="true"
expandedRow="#{insiderListManager.listEntitiesRowTogglerOpen}"
filteredValue="#{insiderListManager.filteredEntities}"
sortBy="#{sortColumn}"
styleClass="bx-datatable-header-hidden-m"
tyle="width: 970px;">
<f:facet name="header">
<p:inputText id="globalFilter"
onkeypress="if (event.keyCode == 13) { listEntitiesTable.filter(); return false;}"
size="70"
styleClass="bx-dt-header-element" />
<p:commandButton id="search-btn"
icon="ui-icon bx-icon-search"
value="#{msg['common.action.search.label']}"
process="#this"
onclick="listEntitiesTable.filter(); return false;"
styleClass="bx-dt-header-element" />
<p:commandButton title="#{msg['common.action.excelExport.all.hint']}"
icon="ui-icon bx-icon-excel"
action="#{insiderListManager.exportXls( table )}"
ajax="false"
styleClass="bx-button-border bx-dt-header-element" />
<div class="bx-clear-float" />
</f:facet>
<p:column width="15"
resizable="false">
...
<p:rowExpansion>
<p:dataTable value="#{insiderListManager[mapPropertyName].get(key)}"
var="value">
<ui:include src="#{valueColumnsXhtml}" />
</p:dataTable>
</p:rowExpansion>
</p:dataTable>
<h:panelGroup id="button-panel" layout="block" styleClass="left-button-panel mt-5px">
<p:commandButton id="toggle-button"
icon="#{insiderListManager.listEntitiesRowTogglerOpen ? 'ui-icon ui-icon-circle-triangle-e' : 'ui-icon ui-icon-circle-triangle-s'}"
value="#{insiderListManager.listEntitiesRowTogglerOpen ? msg['common.action.collapseAll.label'] : msg['common.action.expandAll.label']}"
process="#this"
update="#form">
<f:setPropertyActionListener target="#{insiderListManager.listEntitiesRowTogglerOpen}"
value="#{not insiderListManager.listEntitiesRowTogglerOpen}" />
</p:commandButton>
</h:panelGroup>
</h:form>
</p:dialog>
Note the
<p:commandButton title="..."
icon="ui-icon bx-icon-excel"
action="#{insiderListManager.exportXls( table )}"
... />
which is using the bound data table as described in the link posted at the top.
We are using JSF 2.1 (Mojarra 2.1.22 - and we cannot switch to MyFaces) which allows expressions to construct IDs like #{idPrefix}-il-view-dialog from a <ui:param name="idPrefix" value="il-emp" />.
However, we are getting ID uniqueness exception:
Caused by: java.lang.IllegalStateException: Component ID il-emp-il-view-form:list-entities:globalFilter has already been found in the view.
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:846)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
at com.sun.faces.application.view.StateManagementStrategyImpl.saveView(StateManagementStrategyImpl.java:144)
at com.sun.faces.application.StateManagerImpl.saveView(StateManagerImpl.java:133)
at com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:419)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
at com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(PrettyViewHandler.java:163)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
... 49 more
Same happens to other buttons with explicit IDs if omitted, e.g. the search button (<p:commandButton id="search-btn" ...).
QUESTION:
Why is this happening and how can we avoid this problem when we are bound to using PrimeFaces dialogs for each use case displayed? (we have more than one dialog)
Note that when removing the <p:dataTable ... binding="..." the page works correctly.
You're basically binding physically different <p:dataTable> components to one and same EL variable. If this EL variable is not null (i.e. already set by a previous component in the same view), then JSF will reuse it instead of creating a new one, and override all of its attributes during view build time, resulting in "weird" behavior during view render time and potential duplicate component ID errors during state saving.
In your specific case, you can use UIComponent#getNamingContainer() to directly reference the parent <p:dataTable> component from inside a child component.
<p:dataTable ... (NO binding!)>
...
<p:comandButton ... action="#{bean.exportXls(component.namingContainer)}" />
Might it happen that it's nested in another NamingContainer component, then you need to use #{component.namingContainer.parent.namingContainer} instead. And so forth for multiple ones.

Primefaces 3.4.2 javascript error

I'm developing a web application using the 3.4.2 version of Primefaces. I have a p:pickList on it. Application is working using a general template and each page replaces the general_content of the template, which is being reloaded for every request. My problem is that the picklist is not working (cannot interact with it) because some JavaScript error happens when I load the page. This is my xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"
template="/templates/general_template.xhtml">
<ui:define name="metadata">
<f:metadata>
<f:viewParam id="user" name="user"
value="#{navegableUserData._ParamUser}" />
<f:viewParam id="NavIndex" name="NavIndex"
value="#{navegableUserData._QueueIndex}" />
<f:event type="preRenderView"
listener="#{navegableUserData.initialize}" />
</f:metadata>
<h:message for="user" />
</ui:define>
<ui:define name="general_content">
<h:form id="SystemUserForm">
<p:pickList id="rolePickList" value="#{navegableUserData._ListRoles}"
var="role" itemValue="#{role}" converter="rolConverter">
<f:facet name="sourceCaption">
<h:outputText value="#{msg.AVAILABLE}" />
</f:facet>
<f:facet name="targetCaption">
<h:outputText value="#{msg.ASSIGNED}" />
</f:facet>
<p:column>
<h:outputText value="#{role._Nombre}" />
</p:column>
</p:pickList>
</h:form>
</ui:define>
This is the JavaScript error I have:
Firebug in Firefox
Firebug is telling me the element 'a' cannot be found in the first line of primefaces.js
"a is undefined"
PrimeFaces={escapeClientId:function(a){return"#"+a.replace(/:/g,"\\:")},
...
Inspector in Chrome
Uncaught TypeError: Cannot call method 'replace' of undefined primefaces.js.xhtml:1
PrimeFaces.escapeHTML primefaces.js.xhtml:1
(anonymous function) primefaces.js.xhtml:27
bG.extend.each jquery.js.xhtml:14
bG.fn.bG.each jquery.js.xhtml:14
PrimeFaces.widget.PickList.PrimeFaces.widget.BaseWidget.extend.generateItems primefaces.js.xhtml:27
PrimeFaces.widget.PickList.PrimeFaces.widget.BaseWidget.extend.init primefaces.js.xhtml:27
e.(anonymous function) jquery.js.xhtml:373
c jquery.js.xhtml:373
PrimeFaces.createWidget primefaces.js.xhtml:1
PrimeFaces.cw primefaces.js.xhtml:1
(anonymous function)
It looks like some jquery is failing. With the previous version of Prime, 3.4.1, everything is working fine.
p:pickList (primefaces v3.4.2) requires itemLabel to be specified.
Just add
itemLabel="#{role}"
to your p:pickList

f:param to composite components

In JSF2.1 composite component if we try to pass f:param to a composite component (command button) and recieve in the component as editableValueHolder ,It doesn't seems to be working,
Any ideas?
<mycomp id="button" outcome="newpage" >
<f:param name="foo" outcome="bar" for="button"/>
</mycomp>
compositeComponent....
<cc:interface>
<cc:attribute name="action" targets="commandLink" required="true" />
</cc:interface>
<cc:implementation>
<h:commandLink id="commandLink" action="#{cc.attrs.action}">
</h:commandLink>
</cc:implementation>
Use <cc:insertChildren>.
<h:commandLink ...>
<cc:insertChildren />
</h:commandLink>

Resources