I have a problem when try to validate the rich:calendar component with o:validateOrder.
Code:
<!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:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
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:tablas="http://java.sun.com/jsf/composite/tablas"
xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions"
xmlns:templates="http://java.sun.com/jsf/composite/templates"
>
<body>
<f:metadata>
<f:event type="preRenderView" listener="#{baseController.iniciarConversacion()}" />
</f:metadata>
<ui:composition template="/templates/TemplateABM.xhtml">
<ui:define name="title">
#{msgs['facturacion.abm.generacion.factura.individual.pagina.titulo']}
</ui:define>
<ui:define name="top">
<h1>#{msgs['facturacion.abm.generacion.factura.individual.titulo']}</h1>
</ui:define>
<ui:define name="content">
<h:form id="formFacturaIndividual">
<h:panelGroup id="panelFechas">
<h:inputHidden id="fechaInicioFactura" value="#{facturaController.fechaInicioFactura}">
<f:convertDateTime type="date" pattern="dd/MM/yy"/>
</h:inputHidden>
<h:inputHidden id="fechaFinFactura" value="#{facturaController.fechaFinFactura}">
<f:convertDateTime type="date" pattern="dd/MM/yy"/>
</h:inputHidden>
<h:inputHidden id="fechaEmisionComprobanteUltima" value="#{comprobanteController.fechaEmisionComprobanteUltima}">
<f:convertDateTime type="date" pattern="dd/MM/yy"/>
</h:inputHidden>
</h:panelGroup>
<o:validateOrder id="validacionFechaFacturaMenorAFechaInicioFactura" type="gte" components="fechaFactura fechaInicioFactura"
message="#{msgs['comun.abm.fecha.factura.menor.limite.dia']}" showMessageFor="fechaFactura" />
<o:validateOrder id="validacionFechaFacturaMayorAFechaFinFactura" type="lte" components="fechaFactura fechaFinFactura"
message="#{msgs['comun.abm.fecha.factura.menor.limite.dia']}" showMessageFor="fechaFactura" />
<o:validateOrder id="validacionFechaFacturaMayorAFechaEmisionUltimoComprobante" type="gte" components="fechaFactura fechaEmisionComprobanteUltima"
message="#{of:format1(msgs['comun.abm.fecha.factura.menor.ultimo.comprobante'], comprobanteController.fechaEmisionComprobanteUltima)}" showMessageFor="fechaFactura" />
<o:massAttribute name="disabled" value="#{tipoComprobanteController.entidad == null}">
<rich:panel id="panelDatosFactura" header="#{msgs['facturacion.abm.generacion.padron.panel.datos.factura']}">
<h:panelGrid id="DatosFactura" columns="3">
<h:outputLabel value="#{msgs['facturacion.abm.generacion.padron.fecha.factura']}" for="fechaFactura"/>
<rich:calendar
id="fechaFactura"
datePattern="dd/MM/yyyy"
showWeeksBar="false"
enableManualInput="true"
value="#{generacionFacturacionIndividualController.facturaBean.fechaFactura}"
required="true"
requiredMessage="La Fecha de la Factura es Obligatoria" >
<a4j:ajax event="change" execute="#form" />
</rich:calendar>
<h:panelGroup>
<rich:message for="fechaFactura"/>
</h:panelGroup>
</h:panelGrid>
</rich:panel>
</o:massAttribute>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
Exception:
java.lang.IllegalArgumentException: All values must implement java.lang.Comparable.
at org.omnifaces.component.validator.ValidateOrder.validateValues(ValidateOrder.java:142)
at org.omnifaces.component.validator.ValidateMultipleFields.validateComponents(ValidateMultipleFields.java:213)
at org.omnifaces.component.validator.ValidatorFamily.processValidators(ValidatorFamily.java:63)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1216)
at javax.faces.component.UIForm.processValidators(UIForm.java:253)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:536)
at org.richfaces.context.MetaComponentProcessingVisitCallback.visit(MetaComponentProcessingVisitCallback.java:73)
at org.richfaces.context.BaseExtendedVisitContext.invokeVisitCallback(BaseExtendedVisitContext.java:103)
at org.richfaces.context.ExtendedExecuteVisitContext.invokeVisitCallback(ExtendedExecuteVisitContext.java:55)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1652)
at javax.faces.component.UIForm.visitTree(UIForm.java:371)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1663)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1663)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:383)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:257)
at org.richfaces.context.ExtendedPartialViewContext.processPartial(ExtendedPartialViewContext.java:263)
at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:183)
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1162)
at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at ar.com.filter.HibernateSessionRequestFilter.doFilter(HibernateSessionRequestFilter.java:35)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1074)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String
at java.lang.String.compareTo(String.java:108)
at java.util.Collections$ReverseComparator.compare(Collections.java:3578)
at java.util.Collections$ReverseComparator.compare(Collections.java:3569)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:324)
at java.util.TimSort.sort(TimSort.java:189)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
at org.omnifaces.component.validator.ValidateOrder$Type$4.invoke(ValidateOrder.java:99)
at org.omnifaces.component.validator.ValidateOrder$Type$4.invoke(ValidateOrder.java:95)
at org.omnifaces.component.validator.ValidateOrder$Type.validateOrder(ValidateOrder.java:111)
at org.omnifaces.component.validator.ValidateOrder.validateValues(ValidateOrder.java:139)
... 44 more
I debuged the code and the problem is that the rich:calendar component send String instead Date type, this doesn't happen me in other pages i dont know is omnifaces problem or richfaces. Any ideas?
The <o:validateXxx> components are sensitive to their location relative to the target input components. This is very useful to prioritize validation depending on component's own converter and validators.
When placed before the target input components, then they will validate the raw unsubmitted values, and they will run before any of component's own validators.
When placed after the target input components, then they will validate the converted values (if any converter is involved), and they will run after any of component's own validators.
In your particular case, you placed the <o:validateOrder> between those components. This is not the recommended approach. You will end up getting a List filled with Date instances from components above the validator and String instances from components below the validator.
See also the ValidateMultipleFields javadoc (emphasis mine):
This validator can be placed anywhere in the form, but keep in mind that the components will be validated in the order as they appear in the form. So if this validator is been placed before all of the components, then it will be executed before any of the component's own validators. If this validator fails, then the component's own validators will not be fired. If this validator is been placed after all of the components, then it will be executed after any of the component's own validators. If any of them fails, then this validator will not be exeucted. It is not recommended to put this validator somewhere in between the referenced components as the resulting behaviour may be confusing. Put this validator either before or after all of the components, depending on how you would like to prioritize the validation.
Related
I'm making a project to school in JSF and I have few problems with that.
First of all, the h:commandButton doesn't work properly when I want to redirect myself to another page of the project by pushing it. There is an error displayed:
javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
index.jsp:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%# taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%# taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>Firma Komputerowa - Baza Danych</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/table-style.css" />
</head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:commandButton action="#{producentBean.redirect }" value="Dodaj"/>
</h:panelGrid>
<h:panelGrid>
<h:dataTable value="#{producentBean.List}" var="p"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row" border="1" >
<h:column>
<f:facet name="header">ID producenta</f:facet>
<h:inputText value="#{p.getId}"/>
</h:column>
<h:column>
<f:facet name="header">Nazwa producenta</f:facet>
<h:inputText value="#{p.getNazwa}" />
</h:column>
<h:column>
<f:facet name="header">NIP</f:facet>
<h:inputText value="#{p.getNip}" />
</h:column>
<h:column>
<f:facet name="header">REGON</f:facet>
<h:inputText value="#{p.getRegon}" />
</h:column>
<h:column>
<f:facet name="header">Miasto</f:facet>
<h:inputText value="#{p.getMiasto}" />
</h:column>
<h:column>
<f:facet name="header">Adres</f:facet>
<h:inputText value="#{p.getAdres}" />
</h:column>
<h:column>
<f:facet name="header">Telefon</f:facet>
<h:inputText value="#{p.getTel}" />
</h:column>
<h:column>
<f:facet name="header">E-mail</f:facet>
<h:inputText value="#{p.getEmail}" />
</h:column>
</h:dataTable>
</h:panelGrid>
</h:form>
</f:view>
...
</body>
</html>
ProducentBean.java:
public class ProducentBean extends Polacz implements Serializable {
public String redirect() {
return "dodaj_pr";
}
}
I was trying to do it in many ways, but I can't deal with it.
I also have an another question: is there in JSF a possibility to display a table dynamically from database, for example by choosing a table name selecting an option in ? My database contains three tables with different count of colums each.
I'll be very happy if somebody gives me some advices.
EDIT:
OK, I tried to do this:
private String dodajPrUrl = "dodaj_pr?faces-redirect=true";
public String getDodajPrUrl() {
return this.dodajPrUrl;
}
public void setDodajPrUrl(String newUrl) {
this.dodajPrUrl = newUrl;
}
and in index.jsp:
<h:commandButton action="#{producentBean.redirect }" value="Dodaj" />
It gives me still the same error.
EDIT2:
Stack trace:
SEVERE: javax.faces.FacesException: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
javax.faces.FacesException: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at com.sun.faces.context.ExceptionHandlerImpl.handle(ExceptionHandlerImpl.java:142)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.component.UpdateModelException: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at javax.faces.component.UIInput.updateModel(UIInput.java:853)
at javax.faces.component.UIInput.processUpdates(UIInput.java:735)
at javax.faces.component.UIData.iterate(UIData.java:2001)
at javax.faces.component.UIData.processUpdates(UIData.java:1253)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1231)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
... 26 more
Caused by: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at com.sun.el.parser.AstValue.setValue(AstValue.java:207)
at com.sun.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:291)
at javax.faces.component.UIInput.updateModel(UIInput.java:818)
... 35 more
Look at the stack trace. Here's the most important part:
Caused by: javax.faces.component.UpdateModelException: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at javax.faces.component.UIInput.updateModel(UIInput.java:853)
at javax.faces.component.UIInput.processUpdates(UIInput.java:735)
at javax.faces.component.UIData.iterate(UIData.java:2001)
at javax.faces.component.UIData.processUpdates(UIData.java:1253)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1231)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
... 26 more
Read from bottom to top. During update model values phase, JSF is traversing the component tree starting from UIViewRoot component (<f:view>). In an UIForm component (<h:form>) there is an UIData component (<h:dataTable>) which has an UIInput component (<h:inputText>) which needs to be processed. The updateModel() basically needs to put the submitted, converted and validated value in the model (the managed bean). However, that operation has failed because the property is not writable (i.e. the setter method cannot be found based on the EL expression syntax).
Well, let's look at the properties of your <h:inputText> components in general.
<h:inputText value="#{p.getId}"/>
...
<h:inputText value="#{p.getNazwa}" />
...
<h:inputText value="#{p.getNip}" />
Wait, that's strange. They start all with "get"! This is definitely not normal. JSF is then looking for methods like setGetId(), setGetNazwa(), etc which just doesn't make sense (and you likely also don't have, given this exception). It's expected that they represent concrete property names like "id", "nazwa", "nip", etc and not full method names.
Thus, so in the model:
private Long id;
private String nazwa;
private String nip;
// Add/generate getters and setters in the following syntax:
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// ...
And so in the view:
<h:inputText value="#{p.id}"/>
...
<h:inputText value="#{p.nazwa}" />
...
<h:inputText value="#{p.nip}" />
This is however already covered in a bit sane JSF book/tutorial/resource. Are you absolutely positive that you were reading the right one? Your question also shows that you're using JSF 2.0 in combination with the deprecated JSP view technology instead of its successor Facelets. Start at our JSF wiki page.
You have few problems here. First, in your input components you have values like p.getId. In your bean, you probably have methods called getId and setId, but this means that you have property called just id which you can read and write. So change your values to: p.id, p.nazwa, p.nip... You can see that I'm using all lower letters, not Id but id.
Second, you should change your action method to something like this (if you want redirect):
public String redirect() {
return "dodaj_pr?faces-redirect=true";
}
and command button tag to something like this:
<h:commandButton action="#{producentBean.redirect}" value="Dodaj" />
I had the same mistake. The error was that in the value property of the inputext in the EL there were blank spaces between } and " as shown below.
<h:inputText id="txtNroOficio" value="# {bean.nombre} " />
I deleted the blank spaces and it worked.
Don't give the () in your command button. In your bean method return some string and use navigation to move to another page.
I want to create my custom composite component in JSF (with primefaces) that shows a label in front of an input an adds a message at the end.
In order to do that here is my source code:
The composite:
<?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:p="http://primefaces.org/ui"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface componentType="customInput">
<composite:attribute name="label" />
<composite:attribute name="value" />
</composite:interface>
<composite:implementation>
<h:panelGrid columns="3">
<h:outputText value="#{cc.attrs.label}:" />
<p:inputText id="abcde" value="#{cc.attrs.value}" />
<p:message for="abcde" />
</h:panelGrid>
</composite:implementation>
</html>
The backing bean:
#FacesComponent(value = "customInput")
public class CustomInput extends InputText implements NamingContainer {
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
}
So far, so good. Now I want to use the events inherited by the p:inputText component. Like for example:
<pch2:PchInputText2 label="Name" id="test2" value="#{testBean.test}">
<p:ajax event="blur" listener="#{chantierFormBean.updateMap()}" />
<p:ajax event="change" listener="#{chantierFormBean.updateMap()}" />
</pch2:PchInputText2>
I know that I could pass these events by adding
<composite:clientBehavior name="change" event="change" targets="abcde" />
to the composite:interface part, but then I have to add one client behavior for every event (in the future). Isn't there a method to pass all events inherited by the primefaces inputtext?
Thanks in advance
That's not possible.
A composite is in first place not the right tool for this job. It's not primarily intented to DRY out and refactor repeated XHTML code. It's intented to create a whole new (input) component tied to a single model value. For example, a <p:fileUpload> and <p:imageCropper> togeher which is tied to a single com.example.Image property. Or three <p:selectOneMenu> together which is tied to a single java.time.LocalDate property.
Use a tagfile instead.
<ui:composition ...>
<h:outputLabel for="#{id}" value="#{label}:" />
<p:inputText id="#{id}" value="#{value}">
<ui:insert />
</p:inputText>
<p:message for="#{id}" />
</ui:composition>
See also:
How to make a grid of JSF composite component?
When to use <ui:include>, tag files, composite components and/or custom components?
I found a problem while using the bootsfaces inputText with ajax.
I'm using JSF 2.2, Bootsfaces 0.8.1 and Primefaces 5.3.
I'm trying to enter a date value into the inputText field. As soon as I enter the last value for the date the inputText should trigger the change event. At this point I would like to use ajax for calling a bean method. The problem is, that my field loses focus as soon as I try to enter the last value and the method's never been invoked.
So I tried a bit with Primefaces and it almost works like I wanted. At this point I got different questions:
Why does my inputText field lose the focus while entering the last value? (Bootsfaces)
Why is the bean method never called after I lose the focus? (Bootsfaces)
Is it possible to invoke the bean method after the bean value has been set by the field? (Primefaces)
I added the code below, so maybe you can reproduce this behaviour.
test.xhtml - sample xhtml with both primefaces and bootsfaces fields
<?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:b="http://bootsfaces.net/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta charset="UTF-8"/>
</h:head>
<h:body>
<h:form id="form">
<b:panel id="filterPanel" title="Filter properties" immediate="true" collapsed="false" collapsible="true">
<b:row>
<b:column span="12">
<b:inputText id="dateA" type="date" value="#{test.dateA}" immediate="true" class="form-control">
<f:ajax event="change" listener="#{test.searchA()}"/>
</b:inputText>
</b:column>
</b:row>
<b:row>
<b:column span="12">
<p:inputText id="dateB" type="date" value="#{test.dateB}" immediate="true" class="form-control">
<p:ajax event="change" listener="#{test.searchB()}"/>
</p:inputText>
</b:column>
</b:row>
</b:panel>
</h:form>
</h:body>
</html>
TestBean.java - my bean for setting the values and calling methods
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "test")
#ViewScoped
public class TestBean {
private String dateA;
private String dateB;
public void searchA() {
System.out.println("Search A");
}
public void searchB() {
System.out.println("Search B");
}
public String getDateA() {
return dateA;
}
public void setDateA(String dateA) {
this.dateA = dateA;
System.out.println(dateA);
}
public String getDateB() {
return dateB;
}
public void setDateB(String dateB) {
this.dateB = dateB;
System.out.println(dateB);
}
}
Please help me finding a solution or explain me what I'm doing wrong here.
Thanks
mweber
You've found a subtle difference between BootsFaces and PrimeFaces. I recommend you always define the values of process and update for the sake of clarity. In your case,
<b:inputText id="dateA" type="date" value="#{test.dateA}" immediate="true" class="form-control">
<f:ajax event="change" listener="#{test.searchA()}" render="#none"/>
</b:inputText>
makes the BootsFaces input field behave exactly like its PrimeFaces counterpart.
The default values of update and process are different. Since BootsFaces 0.8.5, the default values are:
process="#form" for <b:commandButton /> and <b:commandLink />
process="#this" for every other BootsFaces component
update="#form" for every BootsFaces component
According to Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes, the PrimeFaces default values are:
For the sake of convenience, here's my version of the XHTML file:
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
xmlns:b="http://bootsfaces.net/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta charset="UTF-8"/>
</h:head>
<h:body>
<h:form id="form">
<b:panel id="filterPanel" title="Filter properties" immediate="true" collapsed="false" collapsible="true">
<b:row>
<b:column span="12">
<b:inputText id="dateA" type="date" value="#{test.dateA}" immediate="true" class="form-control">
<f:ajax event="change" listener="#{test.searchA()}" render="#none"/>
</b:inputText>
</b:column>
</b:row>
<b:row>
<b:column span="12">
<p:inputText id="dateB" type="date" value="#{test.dateB}" immediate="true" class="form-control">
<p:ajax event="change" listener="#{test.searchB()}"/>
</p:inputText>
</b:column>
</b:row>
</b:panel>
</h:form>
</h:body>
</html>
I've tested it with BootsFaces 0.8.5.
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.
I'm making a project to school in JSF and I have few problems with that.
First of all, the h:commandButton doesn't work properly when I want to redirect myself to another page of the project by pushing it. There is an error displayed:
javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
index.jsp:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%# taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%# taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>Firma Komputerowa - Baza Danych</title>
<link rel="stylesheet" href="${pageContext.request.contextPath}/resources/table-style.css" />
</head>
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:commandButton action="#{producentBean.redirect }" value="Dodaj"/>
</h:panelGrid>
<h:panelGrid>
<h:dataTable value="#{producentBean.List}" var="p"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row" border="1" >
<h:column>
<f:facet name="header">ID producenta</f:facet>
<h:inputText value="#{p.getId}"/>
</h:column>
<h:column>
<f:facet name="header">Nazwa producenta</f:facet>
<h:inputText value="#{p.getNazwa}" />
</h:column>
<h:column>
<f:facet name="header">NIP</f:facet>
<h:inputText value="#{p.getNip}" />
</h:column>
<h:column>
<f:facet name="header">REGON</f:facet>
<h:inputText value="#{p.getRegon}" />
</h:column>
<h:column>
<f:facet name="header">Miasto</f:facet>
<h:inputText value="#{p.getMiasto}" />
</h:column>
<h:column>
<f:facet name="header">Adres</f:facet>
<h:inputText value="#{p.getAdres}" />
</h:column>
<h:column>
<f:facet name="header">Telefon</f:facet>
<h:inputText value="#{p.getTel}" />
</h:column>
<h:column>
<f:facet name="header">E-mail</f:facet>
<h:inputText value="#{p.getEmail}" />
</h:column>
</h:dataTable>
</h:panelGrid>
</h:form>
</f:view>
...
</body>
</html>
ProducentBean.java:
public class ProducentBean extends Polacz implements Serializable {
public String redirect() {
return "dodaj_pr";
}
}
I was trying to do it in many ways, but I can't deal with it.
I also have an another question: is there in JSF a possibility to display a table dynamically from database, for example by choosing a table name selecting an option in ? My database contains three tables with different count of colums each.
I'll be very happy if somebody gives me some advices.
EDIT:
OK, I tried to do this:
private String dodajPrUrl = "dodaj_pr?faces-redirect=true";
public String getDodajPrUrl() {
return this.dodajPrUrl;
}
public void setDodajPrUrl(String newUrl) {
this.dodajPrUrl = newUrl;
}
and in index.jsp:
<h:commandButton action="#{producentBean.redirect }" value="Dodaj" />
It gives me still the same error.
EDIT2:
Stack trace:
SEVERE: javax.faces.FacesException: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
javax.faces.FacesException: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at com.sun.faces.context.ExceptionHandlerImpl.handle(ExceptionHandlerImpl.java:142)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.component.UpdateModelException: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at javax.faces.component.UIInput.updateModel(UIInput.java:853)
at javax.faces.component.UIInput.processUpdates(UIInput.java:735)
at javax.faces.component.UIData.iterate(UIData.java:2001)
at javax.faces.component.UIData.processUpdates(UIData.java:1253)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1231)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
... 26 more
Caused by: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at com.sun.el.parser.AstValue.setValue(AstValue.java:207)
at com.sun.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:291)
at javax.faces.component.UIInput.updateModel(UIInput.java:818)
... 35 more
Look at the stack trace. Here's the most important part:
Caused by: javax.faces.component.UpdateModelException: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at javax.faces.component.UIInput.updateModel(UIInput.java:853)
at javax.faces.component.UIInput.processUpdates(UIInput.java:735)
at javax.faces.component.UIData.iterate(UIData.java:2001)
at javax.faces.component.UIData.processUpdates(UIData.java:1253)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1242)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1231)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
... 26 more
Read from bottom to top. During update model values phase, JSF is traversing the component tree starting from UIViewRoot component (<f:view>). In an UIForm component (<h:form>) there is an UIData component (<h:dataTable>) which has an UIInput component (<h:inputText>) which needs to be processed. The updateModel() basically needs to put the submitted, converted and validated value in the model (the managed bean). However, that operation has failed because the property is not writable (i.e. the setter method cannot be found based on the EL expression syntax).
Well, let's look at the properties of your <h:inputText> components in general.
<h:inputText value="#{p.getId}"/>
...
<h:inputText value="#{p.getNazwa}" />
...
<h:inputText value="#{p.getNip}" />
Wait, that's strange. They start all with "get"! This is definitely not normal. JSF is then looking for methods like setGetId(), setGetNazwa(), etc which just doesn't make sense (and you likely also don't have, given this exception). It's expected that they represent concrete property names like "id", "nazwa", "nip", etc and not full method names.
Thus, so in the model:
private Long id;
private String nazwa;
private String nip;
// Add/generate getters and setters in the following syntax:
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// ...
And so in the view:
<h:inputText value="#{p.id}"/>
...
<h:inputText value="#{p.nazwa}" />
...
<h:inputText value="#{p.nip}" />
This is however already covered in a bit sane JSF book/tutorial/resource. Are you absolutely positive that you were reading the right one? Your question also shows that you're using JSF 2.0 in combination with the deprecated JSP view technology instead of its successor Facelets. Start at our JSF wiki page.
You have few problems here. First, in your input components you have values like p.getId. In your bean, you probably have methods called getId and setId, but this means that you have property called just id which you can read and write. So change your values to: p.id, p.nazwa, p.nip... You can see that I'm using all lower letters, not Id but id.
Second, you should change your action method to something like this (if you want redirect):
public String redirect() {
return "dodaj_pr?faces-redirect=true";
}
and command button tag to something like this:
<h:commandButton action="#{producentBean.redirect}" value="Dodaj" />
I had the same mistake. The error was that in the value property of the inputext in the EL there were blank spaces between } and " as shown below.
<h:inputText id="txtNroOficio" value="# {bean.nombre} " />
I deleted the blank spaces and it worked.
Don't give the () in your command button. In your bean method return some string and use navigation to move to another page.