I'm running into an odd issue with myfaces 2.1.10 (packaged with TomEE) involving composite components and action methods. Essentially, looking at the example below, myfaces seems to thing that the action method is a property instead and throws an ElException. This same code works fine with Mojarra (under jBoss 7.1.2).
Any idea what I'm doing wrong?
Exception:
javax.el.ELException: /index.xhtml: Property 'act' not found on type com.company.dept.beans.SomeBean
org.apache.myfaces.view.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:55)
org.apache.myfaces.view.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:46)
org.apache.myfaces.view.facelets.compiler.UILeaf.encodeAll(UILeaf.java:505)
javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:541)
javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:541)
org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1981)
org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:285)
javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:59)
org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:116)
org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:241)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:199)
Composite component named "menu":
<composite:interface displayName="Navigation Menu Bar" shortDescription="Navigation menu bar">
<composite:attribute name="action" method-signature="java.lang.String action()"/>
</composite:interface>
<composite:implementation>
<div id="#{cc.clientId}:menuComponent">
<h:form>
<h:commandButton action="#{cc.attrs.action}" value="execute action" />
</h:form>
</div>
</composite:implementation>
The following page uses the component above
<h:head>
</h:head>
<h:body>
<menu:menu action="#{someBean.act}"/>
</h:body>
</html>
The backing bean with the action method
package com.company.dept.beans;
import javax.inject.Named;
#Named
public class SomeBean {
public String act() {
System.out.println("ACT CALLED");
return "SUCCESS";
}
}
This was due to the way the application was packaged. One of the jars that contained the xhtml was missing a faces-config.xml file and that caused MyFaces not to find it. Oddly enough, Mojarra didn't seem to care...
Related
I've been reading and searching among the many pages with similar questions, but I cannot find why my commandButton is not invoking the action (I have debugged it and that is the problem). My code looks simple but... doesn't work. Maybe it's a newbie problem, but I don't know where it is.
I'm writing a portlet for liferay using JSF2 and Liferay Faces Alloy.
I've also read the question commandLink/commandButton/ajax backing bean action/listener method not invoked, very educational for me, but none of the points have solved my problem.
Here is my mainView.xhtml file:
<?xml version="1.0"?>
<f:view
xmlns="http://www.w3.org/1999/xhtml"
xmlns:aui="http://liferay.com/faces/aui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head />
<h:body>
<h:form>
<h:messages globalOnly="true" layout="table" />
<h:outputText id="esteTexto" value="#{ramSession.texto}" />
<br />
<h:commandButton action="#{ramSession.add}" styleClass="btn btn-default" value="#{ramSession.texto}">
</h:commandButton>
</h:form>
</h:body>
</f:view>
And here is my SessionScoped ManagedBean file, RamSession.java:
#ManagedBean
#SessionScoped
public class RamSession extends AbstractBaseBean implements Serializable {
private static final long serialVersionUID = 919724848720360000L;
private String texto;
public void add() {
this.texto = new String("Entrando");
}
#PostConstruct
public void postConstruct() {
this.texto = new String("Jereje");
}
public String getTexto() {
logger.info("gettingTexto");
addGlobalSuccessInfoMessage();
return this.texto;
}
public void setTexto(String texto) {
this.texto = texto;
}
}
I have also tried returning a String (even not necessary), with an actionListener method and even with ajax but nothing. Can anybody help me? Thanks a lot.
Maybe your mojarra listner is not configured correctly.
Follow one of the two following sub-steps
a. Add the liferay-faces-init.jar dependency in each Liferay JSF project by adding the following code to each pom.xml :
<dependency>
<groupId>com.liferay.faces</groupId>
<artifactId>liferay-faces-init</artifactId>
<version>3.1.3-ga4</version>
</dependency>
b. Add the following code in each WEB-INF/web.xml of all your JSF projects :
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
Why not initialize texto in the declaration?
private String texto = "Jereje";
public void addGlobalSuccessInfoMessage(){
//faces message
}
//Getter Setter
Then you can remove the entire PostConstruct method.
Also if all you want to do is set a string and update without navigation just use f:setPropertyActionListener with a f:ajax for updating your messages. You can use action if you want by returning null or void, or actionListener and set the string inside of that, but I'm not seeing why you'd want to. This link may help with those options... Answer by Balus C.
May want to remove any extra logic from your getter method as well. This won't affect your problem but it's cleaner and creating a success message on a getter seems problematic.
<h:form id="myForm">
<h:messages globalOnly="true" layout="table" />
<h:outputText id="esteTexto" value="#{ramSession.texto}" />
<br />
<h:commandButton value="#{ramSession.texto}" actionListener="#{ramSession.addGlobalSuccessInfoMessage()}" styleClass="btn btn-default">
<f:setPropertyActionListener value="Entrando" target="#{ramSession.texto}" />
<f:ajax render="myForm" />
</h:commandButton>
</h:form>
The error is in:
javax.el.PropertyNotFoundException: /index.xhtml: Property 'validar' not found on type fya.beanpages.IndexBean
Its looks like it doesnt find the validar method. And it thinks it is an attribute.
This is the xhtml:
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>FYA WEB</title>
</h:head>
<h:body>
<ui:composition template="/base/base.xhtml">
<ui:param name="title" value="FYA Web Login"/>
<ui:define name="content">
<h:form id="form">
<p:panel id="panel" header="Inicio Sesión">
<p:messages id="panelmsg"/>
<h:panelGrid columns="3">
<h:outputLabel for="nomUsuario" value="Usuario: *" />
<p:inputText id="nomUsuario" value="#{login.usu.nomusuario}" required="true" label="Usuario"/>
<h:outputLabel for="pwdUsuario" value="Contraseña: *" />
<p:password id="pwdUsuario" value="#{login.usu.contraseña}" label="Contraseña" required="true"/>
</h:panelGrid>
<p:commandButton id="btnIniciar" value="Iniciar Sesión" action="#{login.validar}" update="panelmsg" ajax="true"/>
</p:panel>
</h:form>
</ui:define>
</ui:composition>
</h:body>
This is the managed Bean.
package pe.edu.cibertec.managed;
#ManagedBean(name="login")
public class LoginBean {
private Usuario usuario=new Usuario();
private static LoginService loginService= new LoginServiceImpl();
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public String validar() throws Exception {
if(loginService.validar(usuario))
return "paginas/principal";
else{
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Datos Incorrectos"));
return null;
}
}
}
Maybe i think im doing something wrong, can you help me please?
That can happen when you didn't properly install PrimeFaces. This way all <p:xxx> tags are treated as template text (meaning, they are not parsed as JSF components by Facelets but printed plain vanilla straight to HTML output). All EL expressions in template text are by default resolved as property value expressions (like as in <p>blah #{bean.foo} blah</p>) which requires a getter method. All EL expressions which initially represent a method expression would then throw exactly this exception because there's no getter found in the bean.
To properly install PrimeFaces, make sure that the JAR file is in webapp's /WEB-INF/lib (if you're using any IDE like Eclipse, make sure that you absolutely do not touch Build Path setting, if you ever fiddled there in a careless attempt to solve it, undo it all!), and make sure that the project is properly rebuilt and that the server's work folder is properly cleant up and that the deploy in the server does contain the PrimeFaces JAR file in the right place.
Another thing to take into account, the taglib URI http://primefaces.org/ui was introduced in PrimeFaces 3.0. So if you happen to have a JAR of PrimeFaces 2.x or older, then you can also face exactly this problem. You'd need to either upgrade PrimeFaces to at least 3.0, or to fall back to using 2.x compatible taglib URI http://primefaces.prime.com.tr/ui.
The error is in:
javax.el.PropertyNotFoundException: /index.xhtml: Property 'validar' not found on type fya.beanpages.IndexBean
Its looks like it doesnt find the validar method. And it thinks it is an attribute.
This is the xhtml:
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>FYA WEB</title>
</h:head>
<h:body>
<ui:composition template="/base/base.xhtml">
<ui:param name="title" value="FYA Web Login"/>
<ui:define name="content">
<h:form id="form">
<p:panel id="panel" header="Inicio Sesión">
<p:messages id="panelmsg"/>
<h:panelGrid columns="3">
<h:outputLabel for="nomUsuario" value="Usuario: *" />
<p:inputText id="nomUsuario" value="#{login.usu.nomusuario}" required="true" label="Usuario"/>
<h:outputLabel for="pwdUsuario" value="Contraseña: *" />
<p:password id="pwdUsuario" value="#{login.usu.contraseña}" label="Contraseña" required="true"/>
</h:panelGrid>
<p:commandButton id="btnIniciar" value="Iniciar Sesión" action="#{login.validar}" update="panelmsg" ajax="true"/>
</p:panel>
</h:form>
</ui:define>
</ui:composition>
</h:body>
This is the managed Bean.
package pe.edu.cibertec.managed;
#ManagedBean(name="login")
public class LoginBean {
private Usuario usuario=new Usuario();
private static LoginService loginService= new LoginServiceImpl();
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public String validar() throws Exception {
if(loginService.validar(usuario))
return "paginas/principal";
else{
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Datos Incorrectos"));
return null;
}
}
}
Maybe i think im doing something wrong, can you help me please?
That can happen when you didn't properly install PrimeFaces. This way all <p:xxx> tags are treated as template text (meaning, they are not parsed as JSF components by Facelets but printed plain vanilla straight to HTML output). All EL expressions in template text are by default resolved as property value expressions (like as in <p>blah #{bean.foo} blah</p>) which requires a getter method. All EL expressions which initially represent a method expression would then throw exactly this exception because there's no getter found in the bean.
To properly install PrimeFaces, make sure that the JAR file is in webapp's /WEB-INF/lib (if you're using any IDE like Eclipse, make sure that you absolutely do not touch Build Path setting, if you ever fiddled there in a careless attempt to solve it, undo it all!), and make sure that the project is properly rebuilt and that the server's work folder is properly cleant up and that the deploy in the server does contain the PrimeFaces JAR file in the right place.
Another thing to take into account, the taglib URI http://primefaces.org/ui was introduced in PrimeFaces 3.0. So if you happen to have a JAR of PrimeFaces 2.x or older, then you can also face exactly this problem. You'd need to either upgrade PrimeFaces to at least 3.0, or to fall back to using 2.x compatible taglib URI http://primefaces.prime.com.tr/ui.
i want to pass GET parameter from URL to a method, that called by clicking on button.
For example i have URL: /someurl/semepage.xhtml?id=1. And i have a button on my page:
<p:commandButton value="say it" action="#{test.sayIt(param['id'])}"/>
The bean looks like:
#ManagedBean
#ViewScoped
public class Test{
public void sayIt(String value){
System.out.println(value);
}
}
But when i am clicking on button, its just not react. Why is this happen ? Method even not called.
If i pass arguments staticaly like here:
<p:commandButton value="say it" action="#{test.sayIt('someword')}"/>
everything is ok.
Here is one way - using the <f:param, like this:
<h:commandButton value="Test The Magic Word" action="#{test.sayIt}">
<f:param name="id" value="#{param['id']}"></f:param>
<f:ajax execute="something" render="something_else"></f:ajax>
</h:commandButton>
And in your bean
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
.getRequest();
String id = request.getParameter("id");
#Daniel's response is OK, but here it goes a simpler JSF 2-ish alternative for your case, using <f:viewParam /> and EL parameter passing. Note the <f:ajax /> is not needed in this case, as <p:commandButton /> has ajax behaviour by default.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
<f:metadata>
<f:viewParam name="id" />
</f:metadata>
<h:form>
<p:commandButton value="say it" action="#{bean.sayIt(id)}" />
</h:form>
</h:body>
</html>
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
public void sayIt(String value) {
System.out.println(value);
}
}
Tested with JSF 2.2.5 and Primefaces 4. Remember changing tag namespaces in case of using JSF 2.1.x.
Just for the fun of it, have you tried request.getParameter('id')?
I am trying to make two composite componenets play well together by nesting one as a child.
The setup consists of a lightbox and a input both with an attribute called "Value". This works fine, until i introduce a dynamic
number of inputs, and therefore have to use a ui:repeat.
bugTest.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:pw="http://java.sun.com/jsf/composite/components">
<h:head></h:head>
<h:body>
<pw:lightBox value="Header">
<h:form>
<ui:repeat var="input" value="#{BugTestBean.inputs}">
<pw:bugTestInput value="#{input}" />
</ui:repeat>
</h:form>
</pw:lightBox>
</h:body>
</html>
The ui:repeat seems to get the value attribute of the two components mixed up, and the following exception occurs.
Caused by: javax.el.PropertyNotFoundException: /resources/components/bugTestInput.xhtml #15,62 value="#{cc.attrs.value.text}": The class 'java.lang.String' does not have the property 'text'.
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:182)
at javax.faces.component.UIOutput.getValue(UIOutput.java:170)
at javax.faces.component.UIInput.getValue(UIInput.java:284)
at com.sun.faces.facelets.component.UIRepeat$SavedState.populate(UIRepeat.java:879)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:396)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:402)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:402)
at com.sun.faces.facelets.component.UIRepeat.saveChildState(UIRepeat.java:356)
at com.sun.faces.facelets.component.UIRepeat.setIndex(UIRepeat.java:470)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:586)
at com.sun.faces.facelets.component.UIRepeat.encodeChildren(UIRepeat.java:1042)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1819)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:847)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:304)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:105)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:847)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:304)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:105)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:847)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1819)
at com.sun.faces.renderkit.html_basic.CompositeRenderer.encodeChildren(CompositeRenderer.java:78)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:847)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1819)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1822)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1822)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:447)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125)
at com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(PrettyViewHandler.java:159)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
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)
... 33 more
It seems like the value of the lightbox is being passed to the inputs.
have boiled the example down to a minimum to produce the error.
I have tried on Mojarra 2.1.26, and 2.2.4.
BugTestBean.java
#ManagedBean(name="BugTestBean")
#ViewScoped
public class BugTestBean {
private List<BugTestInput> inputs;
public BugTestBean() {
inputs = new ArrayList<BugTestInput>();
inputs.add(new BugTestInput("Test1"));
inputs.add(new BugTestInput("Test2"));
inputs.add(new BugTestInput("Test3"));
inputs.add(new BugTestInput("Test4"));
}
public List<BugTestInput> getInputs() {
return inputs;
}
}
bugTestInput.xhtml
<cc:interface>
<cc:attribute name="value" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:inputText id="input" value="#{cc.attrs.value.text}" />
</div>
</cc:implementation>
BugTestInput.java
public class BugTestInput {
private String text;
public BugTestInput(String text) {
this.text = text;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
lightbox.xhtml
<cc:interface>
<cc:attribute name="value" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<h:outputText value="#{cc.attrs.value}" />
<h:panelGroup>
<cc:insertChildren />
</h:panelGroup>
</div>
</cc:implementation>
Current Solutions
Renaming the attribute value to something else on the lightbox fixes this problem.
Leaving the attribute value empty on the lightbox also works.
Not using the ui:repeat will also fix the problem, but this isn't solid.
Currently i am using 2 attributes on the lightbox and leaving the value empty when needed
<h:outputText value="#{cc.attrs.value}#{cc.attrs.title}" />
Follow up
Regardless of what the attribute name is, if they are the same on both components it will fail.
Is this a bug in JSF, i have searched the bug trackers and most new patch notes without result.
Have you tried using <c:forEach> tag under JSTL, instead of <ui:repeat>? I have always faces issues with the <ui:repeat> tag.
<c:forEach> should work if you do not re-render the component using ajax calls.