java.lang.NullPointerException at org.primefaces.util.ResourceUtils.getComponentResources - jsf

I'm using PF6.0 and Wildfly 10 and my web app in some point needs to build some quite big grid of p:inplace objects on single page. Sounds easy.
The problem: when my grid is too big any ajax request ends with error.
To reproduce this problem I have working example:
The page test.xhtml:
<?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:p="http://primefaces.org/ui">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:form>
<!--it's a part of something bigger so this part is in outputPanel-->
<p:outputPanel id="details">
<h:outputText value="Size: #{backBean.size}" />
<p:panelGrid>
<!--btw. why it forces me to set all of this variables at p.repeat?-->
<p:repeat value="#{backBean.content}"
var="_row"
offset="0"
step="1"
size="#{backBean.content.size()}"
varStatus="_rowStatus" >
<p:row>
<p:repeat value="#{_row}"
var="_cell"
offset="0"
step="1"
size="#{_row.size()}"
varStatus="_rowStatus" >
<p:column>
<p:inplace editor="true">
<f:facet name="output">
<h:outputText value="#{_cell.output}" />
</f:facet>
<f:facet name="input">
<!--in real example it will be more complex with checkboxes, selectonemenu etc-->
<h:outputText value="First:" />
<p:inputText value="#{_cell.something}" />
<br />
<h:outputText value="Second:" />
<p:inputText value="#{_cell.another}" />
</f:facet>
</p:inplace>
</p:column>
</p:repeat>
</p:row>
</p:repeat>
</p:panelGrid>
</p:outputPanel>
<p:commandButton value="more" update="details" actionListener="#{backBean.weNeedMore}" />
</h:form>
</h:body>
</html>
Backing bean:
package com.test;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
#Named(value = "backBean")
#SessionScoped
public class BackBean implements Serializable {
private List<List<CellContent>> content;
private int size;
/**
* Creates a new instance of BackBean
*/
public BackBean() {
}
private void build() {
content = new ArrayList<>();
for(int i=0;i<size;i++) {
List<CellContent> row = new ArrayList<>();
for(int j=0;j<size;j++) {
CellContent cell = new CellContent();
row.add(cell);
}
content.add(row);
}
}
#PostConstruct
public void init() {
size = 10;
//create first content
build();
}
public void weNeedMore() {
//increase until we get error after click.
size = size + 10;
build();
}
//plain getters & setters
public List<List<CellContent>> getContent() {
return content;
}
public void setContent(List<List<CellContent>> content) {
this.content = content;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
and one class that holds my objects:
package com.test;
public class CellContent {
private String something = "";
private String another = "";
private String output = "click_me";
public CellContent() {
}
//some dummy update based on inputs
private void update() {
if(!something.equals(""))
output = something;
if(!another.equals(""))
output = "another: " + another;
}
//those two setters update the object
public void setSomething(String something) {
this.something = something;
update();
}
public void setAnother(String another) {
this.another = another;
update();
}
//rest are plain get&seters
public String getSomething() {
return something;
}
public String getAnother() {
return another;
}
public String getOutput() {
return output;
}
public void setOutput(String output) {
this.output = output;
}
}
When grid of my objects are "small" like 10x10 or 20x20 it works - I can click and update any cell.
But increasing size up to 30 (by hitting more button) leads to this error when I click anything:
09:47:13,602 ERROR [io.undertow.request] (default task-89) UT005023: Exception handling request to /myapp/test.xhtml: javax.servlet.ServletException
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:671)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:100)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:60)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at org.primefaces.util.ResourceUtils.getComponentResources(ResourceUtils.java:66)
at org.primefaces.context.PrimePartialResponseWriter.startMetadataIfNecessary(PrimePartialResponseWriter.java:280)
at org.primefaces.context.PrimePartialResponseWriter.startError(PrimePartialResponseWriter.java:107)
at com.sun.faces.context.AjaxExceptionHandlerImpl.handlePartialResponseError(AjaxExceptionHandlerImpl.java:203)
at com.sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:127)
at javax.faces.context.ExceptionHandlerWrapper.handle(ExceptionHandlerWrapper.java:100)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:123)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
... 34 more
Any idea what's happen? Is there any parameter I could adjust to avoid this error? Or any other solution (my current workaround is using datagrid with pagination).

FOUND IT ;)
I switched back to PF 5.3 to check if it's PrimeFaces issue.
There is no p:repeat # PF5.3 so I switched to ui:repeat.
Same was here but error message finally tells what's going on:
10:37:58,508 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-44) java.lang.IllegalStateException: UT000047: The number of parameters exceeded the maximum of 1000
at io.undertow.server.handlers.form.FormData.add(FormData.java:78)
at io.undertow.server.handlers.form.FormData.add(FormData.java:68)
All what I need to do is update max-parameters value at http-listener in standalone configuration:
<subsystem xmlns="urn:jboss:domain:undertow:3.0">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" max-parameters="10000" socket-binding="http" redirect-socket="https"/>
(found it at https://developer.jboss.org/thread/241526)

Related

My #PostConstruct method is getting called everytime I delete the last element of a dataTable in JSF

I have a dataTable in JSF to show the phone numbers from a selected user.
Like the image below
My DataTable
In this dataTable I have a column with a commandLink to delete the element. The commandLink is working fine except in one particular case : If I delete the element of the last row and I try to delete any other element my #PostConstruct method is called again and it throws an exception. I concluded that the exception is being called because the param that contains the id of the user is null.
My question is why is this bug triggered only when I delete the last row of the dataTable ?
nov 28, 2022 11:36:54 AM com.sun.faces.application.view.FaceletViewHandlingStrategy handleRenderException
SEVERE: Error Rendering View[/telefone.xhtml]
com.sun.faces.mgbean.ManagedBeanCreationException: An error occurred performing resource injection on managed bean telefoneBean
at com.sun.faces.mgbean.BeanBuilder.invokePostConstruct(BeanBuilder.java:227)
at com.sun.faces.mgbean.BeanBuilder.build(BeanBuilder.java:103)
at com.sun.faces.mgbean.BeanManager.createAndPush(BeanManager.java:409)
at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:269)
at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244)
at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
at org.apache.el.parser.AstIdentifier.getValue(AstIdentifier.java:93)
at org.apache.el.parser.AstValue.getValue(AstValue.java:136)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
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:174)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:355)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:164)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:924)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:312)
at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185)
at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:894)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:894)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:559)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
at javax.faces.component.UIForm.visitTree(UIForm.java:371)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:399)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:319)
at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:57)
at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:1004)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:417)
at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
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:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: com.sun.faces.spi.InjectionProviderException
at com.sun.faces.vendor.WebContainerInjectionProvider.invokeAnnotatedMethod(WebContainerInjectionProvider.java:115)
at com.sun.faces.vendor.WebContainerInjectionProvider.invokePostConstruct(WebContainerInjectionProvider.java:95)
at com.sun.faces.mgbean.BeanBuilder.invokePostConstruct(BeanBuilder.java:221)
... 65 more
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at com.sun.faces.vendor.WebContainerInjectionProvider.invokeAnnotatedMethod(WebContainerInjectionProvider.java:113)
... 67 more
Caused by: java.lang.NumberFormatException: null
at java.base/java.lang.Long.parseLong(Long.java:655)
at java.base/java.lang.Long.parseLong(Long.java:817)
at managedBean.TelefoneManagedBean.init(TelefoneManagedBean.java:42)
... 72 more
nov 28, 2022 11:36:54 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Faces Servlet] in context with path [/pos-java-maven-hibernate] threw exception
java.lang.IllegalStateException: CDATA tags may not nest
at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.startCDATA(HtmlResponseWriter.java:681)
at javax.faces.context.ResponseWriterWrapper.startCDATA(ResponseWriterWrapper.java:179)
at javax.faces.context.PartialResponseWriter.startError(PartialResponseWriter.java:341)
at org.primefaces.context.PrimePartialResponseWriter.startError(PrimePartialResponseWriter.java:116)
at com.sun.faces.context.AjaxExceptionHandlerImpl.handlePartialResponseError(AjaxExceptionHandlerImpl.java:200)
at com.sun.faces.context.AjaxExceptionHandlerImpl.handle(AjaxExceptionHandlerImpl.java:124)
at javax.faces.context.ExceptionHandlerWrapper.handle(ExceptionHandlerWrapper.java:100)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:119)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:829)
#PostConstruct
public void init() {
String codUser = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap()
.get("codigouser");
daoUsuario = new DaoUsuario();
daoTelefone = new DaoTelefone();
telefone = new TelefoneUser();
usuario = daoUsuario.pesquisar(Long.parseLong(codUser), UsuarioPessoa.class);
lista = daoTelefone.consultarLista(usuario);
}
The code of my xhtml page
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.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:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form>
<p:breadCrumb>
<p:menuitem></p:menuitem>
<p:menuitem value="Pagina Index" action="index.jsf" />
<p:menuitem value="Pagina Primefaces" action="primefaces.jsf" />
</p:breadCrumb>
</h:form>
<h:form id="formulario">
<h:messages showDetail="true" showSummary="false" id="msg"></h:messages>
<h:panelGrid columns="2">
<h:outputLabel value="Usuário: " />
<h:outputText value="#{telefoneBean.usuario.nome}" />
<h:outputLabel value="ID " />
<h:inputText value="#{telefoneBean.telefone.id}" readonly="true" />
<h:outputLabel value="Numero: " />
<h:inputText value="#{telefoneBean.telefone.numero}" required="true" />
<h:outputLabel value="Tipo: " />
<h:inputText value="#{telefoneBean.telefone.tipo}" required="true" />
<h:commandButton value="Salvar" action="#{telefoneBean.salvar}" />
</h:panelGrid>
</h:form>
<h:form id="formularioTelefones">
<p:dataTable rowStatePreserved="true" value="#{telefoneBean.lista}"
id="tabelatelefones" var="tel">
<f:facet name="header">Lista de Telefones</f:facet>
<p:column>
<h:outputText value="#{tel.id}" />
<f:facet name="header">ID</f:facet>
</p:column>
<p:column>
<h:outputText value="#{tel.numero}" />
<f:facet name="header">Numero</f:facet>
</p:column>
<p:column>
<f:facet name="header">Tipo</f:facet>
<h:outputText value="#{tel.tipo}" />
</p:column>
<p:column>
<f:facet name="header">Deletar</f:facet>
<h:commandLink id="botaodeletar" action="#{telefoneBean.remover}">
<h:graphicImage url="resources/img/deletar.png" />
<f:setPropertyActionListener value="#{tel}"
target="#{telefoneBean.telefone}" />
<f:ajax execute="botaodeletar" render="#form :formulario:msg" />
</h:commandLink>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
I will explain the bug using this example, lets imagine I delete the row with id= 484.If I do this, I can delete any other row perfectly fine.
Now, lets say I delete the row 503. This row is going to be removed, but if I try to remove any other row my #PostConstruct method is going to be called again and it will throw an exception because the param "codigouser"(this is the param that gets the ID of the user I want) will be null, BUT I still am able to add another number to the list and if I do this the table starts working again (with the same conditions)...
.See the example of a dataTable
First I thought the problem was on the method that I use to delete the phone number in the DB. Then I thought the problem was on the method that I use to get the list of phone numbers in the DB. Then I noticed that this bug just happens when I refresh the values of the dataTable. If I dont refresh the values on the dataTable then everything works perfectly fine, but the problem of course is that the phone numbers I remove still show in the table because I didnt refreshed it.
Edit :
The managed bean class
package managedBean;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import dao.DaoTelefone;
import dao.DaoUsuario;
import model.TelefoneUser;
import model.UsuarioPessoa;
#ManagedBean(name = "telefoneBean")
#ViewScoped
public class TelefoneManagedBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private UsuarioPessoa usuario; // the user
private DaoUsuario daoUsuario; // dao to find the user in the database
private DaoTelefone daoTelefone; // dao to find the phone numbers in the data base
private TelefoneUser telefone; // Object used to save and delete the phone number
private List<TelefoneUser> lista; // list of phone numbers from the user
#PostConstruct
public void init() {
String codUser = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap()
.get("codigouser"); // getting the user id
daoUsuario = new DaoUsuario();
daoTelefone = new DaoTelefone();
telefone = new TelefoneUser();
usuario = daoUsuario.pesquisar(Long.parseLong(codUser), UsuarioPessoa.class); // getting the user
lista = daoTelefone.consultarLista(usuario); // getting the list of phone numbers
}
public void setUsuario(UsuarioPessoa usuario) {
this.usuario = usuario;
}
public UsuarioPessoa getUsuario() {
return usuario;
}
public TelefoneUser getTelefone() {
System.out.println("telefone");
return telefone;
}
public String remover() throws Exception {
daoTelefone.deleteId(telefone);
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Informação:", "Telefone removido."));
telefone = new TelefoneUser();
return "";
}
public String salvar() {
telefone.setPessoa(usuario);
daoTelefone.salvar(telefone);
telefone = new TelefoneUser();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Informação:", "Telefone Salvo."));
return "";
}
public void setTelefone(TelefoneUser telefone) {
this.telefone = telefone;
}
public DaoUsuario getDaoUsuario() {
return daoUsuario;
}
public void setDaoUsuario(DaoUsuario daoUsuario) {
this.daoUsuario = daoUsuario;
}
public DaoTelefone getDaoTelefone() {
return daoTelefone;
}
public void setDaoTelefone(DaoTelefone daoTelefone) {
this.daoTelefone = daoTelefone;
}
public List<TelefoneUser> getLista() {
lista = daoTelefone.consultarLista(usuario);
return lista;
}
public void setLista(List<TelefoneUser> lista) {
this.lista = lista;
}
}
The method used to remove the phone number :
public void deleteId(E entidade) throws Exception {
Object primaryKey = HibernateUtil.getPrimaryKey(entidade);
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.createNativeQuery("delete from "+entidade.getClass().getSimpleName().toLowerCase()+" where id="+primaryKey).executeUpdate();
transaction.commit();
}
In the comment section We found the problem. That was a rendering problem here:
<f:ajax execute="botaodeletar" render="#form :formulario:msg" />
Changed to this:
<f:ajax execute="#this" render=":formulario:msg :formularioTelefones:tabelatelefones" />

Error Rendering View[dummy.xhtml]: java.lang.NullPointerException [duplicate]

This question already has an answer here:
How to send form input values and invoke a method in JSF bean
(1 answer)
Closed 6 years ago.
I'm pretty new to JSF and recently I get this error, which I couldn't manage to solve. My intention was to open a dialog which has a picklist in it to select from the list and reload the datatable with the chosen elements.
:
13:47:22,873 SEVERE
[javax.enterprise.resource.webcontainer.jsf.context] (default task-72)
javax.faces.component.UpdateModelException:
javax.el.PropertyNotWritableException:
/forms/bestellungLieferant.xhtml #29,29
value="#{bestellungLieferantController.getAllAvailableKomponentDualListModel()}":
Illegal Syntax for Set Operation
My JSF Page:
<!DOCTYPE HTML>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<f:view>
<f:metadata>
<!-- Start working on a task. Task Id is read internally from
request parameters and cached in the CDI conversation scope.
-->
<f:event type="preRenderView"
listener="#{camundaTaskForm.startTaskForm()}" />
</f:metadata>
<h:head>
<title>Paket zusammenstellen</title>
</h:head>
<h:body>
<p:dialog id="komponentenAuswahlDialog" header="Komponenten auswählen"
widgetVar="komponentenAuswahlDialog" modal="true" height="auto"
width="auto" immediate="true" rendered="true">
<p:pickList converter="entityConverter"
id="komponenteAuswahlPickList"
value="#{bestellungLieferantController.getAllAvailableKomponentDualListModel()}"
var="komponente" itemLabel="#{komponente.serienNummer}"
itemValue="#{komponente.id}" showSourceFilter="true"
showTargetFilter="true">
<f:facet name="sourceCaption">Quelle</f:facet>
<f:facet name="targetCaption">Ziel</f:facet>
</p:pickList>
<h:form>
<p:commandButton update="komponenteTable" value="Auswahl speichern"
oncomplete="PF('komponentenAuswahlDialog').hide();" />
</h:form>
</p:dialog>
<h:panelGrid id="paketInformationPG" columns="2" border="1">
<f:facet name="header">
<h:outputText value="Paket zusammenstellen" />
</f:facet>
<h:outputLabel value="Kunde:" />
<h:outputText value="#{processVariables['kunde']}" />
<h:outputLabel value="Betriebssystem:" />
<h:outputText value="Platzhalter" />
<h:outputLabel value="Benutzer:" />
<h:outputText value="#{processVariables['benutzerName']}" />
</h:panelGrid>
<h:panelGrid id="komponentenZusammenstellungPG" columns="2" border="1">
<f:facet name="header">
<h:panelGrid columns="2">
<h:outputText value="Komponenten" />
<h:commandButton type="button"
onclick="PF('komponentenAuswahlDialog').show();" value="+" />
</h:panelGrid>
</f:facet>
<p:dataTable id="komponenteTable" widgetVar="komponenteTable"
var="komponente"
value="#{bestellungLieferantController.komponentenList}">
<p:column>
<f:facet name="header">Typ</f:facet>
<h:outputText value="#{komponente.produkt.typ.name}" />
</p:column>
<p:column>
<f:facet name="header">Bezeichnung</f:facet>
<h:outputText value="#{komponente.produkt.name}" />
</p:column>
<p:column>
<f:facet name="header">SN</f:facet>
<h:outputText value="#{komponente.serienNummer}" />
</p:column>
<p:column headerText="Kaufdatum">
<f:facet name="header">Kaufdatum</f:facet>
<h:outputText value="#{komponente.bestellDatum}" />
</p:column>
<p:column>
<f:facet name="header">Aktion</f:facet>
<p:commandLink value="Bearbeiten" />
<p:commandLink value="Enfernen" />
</p:column>
</p:dataTable>
</h:panelGrid>
</h:body>
</f:view>
</html>
My Controller:
#ManagedBean
#SessionScoped
public class BestellungLieferantController implements Serializable{
#EJB
private BestellungFacade bestellungFacade;
#EJB
private PaketFacade paketFacade;
#EJB
private KomponenteFacade komponenteFacade;
#EJB
private BetriebssystemFacade betriebssystemFacade;
// Komponent-List with added komponent items
private List<Komponente> komponentenList = new ArrayList<Komponente>();
private DualListModel<Komponente> komponentenDualListModel;
public DualListModel<Komponente> getKomponentenDualListModel() {
return komponentenDualListModel;
}
public void setKomponentenDualListModel(DualListModel<Komponente> komponentenDualListModel) {
this.komponentenDualListModel = komponentenDualListModel;
}
public List<Komponente> getKomponentenList() {
return komponentenList;
}
public void setKomponentenList(List<Komponente> komponentenList) {
LogManager logManager = LogManager.getLogManager();
Logger rootLogger = logManager.getLogger("DUMMY");
rootLogger.setLevel(Level.ALL);
rootLogger.info("KomponentenList");
this.komponentenList = komponentenList;
}
/**
* Gets the actual Model with the distinct source and
* #param targetList
* #return
*/
public DualListModel<Komponente> getAllAvailableKomponentDualListModel(){
List<Komponente> sourceKomponenteList = this.komponenteFacade.getAllAvailableKomponente();
List<Komponente> sourceKomponenteDistinctList = new ArrayList<Komponente>();
if (this.komponentenList.size() != 0){
for(Komponente k : sourceKomponenteList){
if (!komponentenList.contains(k)){
sourceKomponenteDistinctList.add(k);
}
}
} else {
sourceKomponenteDistinctList = sourceKomponenteList;
}
// komponentenDualListModel.setSource(sourceKomponenteDistinctList);
// komponentenDualListModel.setTarget(komponentenList);
this.setKomponentenDualListModel(new DualListModel<Komponente>());
this.getKomponentenDualListModel().setSource(sourceKomponenteDistinctList);
this.getKomponentenDualListModel().setTarget(this.komponentenList);
return this.getKomponentenDualListModel();
}
public void putSelectionIntoKomponenteList(){
LogManager logManager = LogManager.getLogManager();
Logger rootLogger = logManager.getLogger("DUMMY");
rootLogger.setLevel(Level.ALL);
rootLogger.info("PutSelectionIntoKomponentList");
rootLogger.info("KOMPONENTELIST: " + komponentenDualListModel.getTarget());
this.komponentenList = this.komponentenDualListModel.getTarget();
}
}
My Stacktrace:
13:47:22,873 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-72) javax.faces.component.UpdateModelException: javax.el.PropertyNotWritableException: /forms/bestellungLieferant.xhtml #29,29 value="#{bestellungLieferantController.getAllAvailableKomponentDualListModel()}": Illegal Syntax for Set Operation
at javax.faces.component.UIInput.updateModel(UIInput.java:866)
at org.primefaces.component.picklist.PickList.updateValue(PickList.java:530)
at org.primefaces.component.picklist.PickList.validateValue(PickList.java:394)
at javax.faces.component.UIInput.validate(UIInput.java:982)
at org.primefaces.component.picklist.PickList.validate(PickList.java:424)
at javax.faces.component.UIInput.executeValidate(UIInput.java:1248)
at javax.faces.component.UIInput.processValidators(UIInput.java:712)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
at org.primefaces.component.dialog.Dialog.processValidators(Dialog.java:423)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1195)
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:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:805)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: javax.el.PropertyNotWritableException: /forms/bestellungLieferant.xhtml #29,29 value="#{bestellungLieferantController.getAllAvailableKomponentDualListModel()}": Illegal Syntax for Set Operation
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:136)
at javax.faces.component.UIInput.updateModel(UIInput.java:832)
... 53 more
Caused by: javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation
at com.sun.el.parser.AstValue.setValue(AstValue.java:228)
at com.sun.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:294)
at org.jboss.weld.el.WeldValueExpression.setValue(WeldValueExpression.java:64)
at org.jboss.weld.el.WeldValueExpression.setValue(WeldValueExpression.java:64)
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:131)
... 54 more
My Converter:
#FacesConverter(value = "entityConverter")
public class EntityConverter implements Converter {
private static Map<Object, String> entities = new WeakHashMap<Object, String>();
#Override
public String getAsString(FacesContext context, UIComponent component, Object entity) {
synchronized (entities) {
if (!entities.containsKey(entity)) {
String uuid = UUID.randomUUID().toString();
entities.put(entity, uuid);
return uuid;
} else {
return entities.get(entity);
}
}
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String uuid) {
for (Entry<Object, String> entry : entities.entrySet()) {
if (entry.getValue().equals(uuid)) {
return entry.getKey();
}
}
return null;
}
}
Any hints are welcome.
Thanks in advance!
You want to access a property in your backing bean. The property is not getAllAvailableKomponentDualListModel or allAvailableKomponentDualListModel but komponentenDualListModel
value="#{bestellungLieferantController.komponentDualListModel}"
You already have the setter and getter method in your bean. However, you need to call the method getAllAvailableKomponentDualListModel() before you access it from the view.
Write like this in p:pickList component value attribute:
value="#{bestellungLieferantController.getAllAvailableKomponentDualListModel}"
Edit
just to see try to return something else in this method like this:
#Override
public Object getAsObject(FacesContext context, UIComponent component, String uuid) {
for (Entry<Object, String> entry : entities.entrySet()) {
if (entry.getValue().equals(uuid)) {
return entry.getKey();
}
}
return uuid;
}

javax.el.MethodNotFoundException: Method not found: JSF

I am getting error while trying a simple application with JSF.
javax.el.MethodNotFoundException: Method not found: com.jsf.training.beans.TravelBean#4b6b8628.travelInfo()
at org.apache.el.util.ReflectionUtil.getMethod(ReflectionUtil.java:245)
at org.apache.el.parser.AstValue.invoke(AstValue.java:271)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:149)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:818)
at javax.faces.component.UICommand.broadcast(UICommand.java:300)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:409)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1044)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
My managed bean is :
#ManagedBean (name="travelBean")
#SessionScoped
public class TravelBean {
private int index = 0;
private String source;
private String destination;
private Date date;
java.sql.Date sqlDate;
private boolean visible = false;
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public TravelBean() {
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public void getDateInSql() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.format(date);
sqlDate = new java.sql.Date(date.getTime());
}
public void getTravelInfo() throws SQLException {
setVisible(true);
/*SearchServiceImpl search = new SearchServiceImpl();
search.searchTrainsService(travelBean);*/
System.out.println("********** in travel Bean :" +source +destination +date);
TrainBean tb = new TrainBean();
tb.getTrainsList(source,destination,sqlDate);
}
and my xhtml :
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<script name="jquery/jquery.js" library="primefaces"></script>
<h:outputStylesheet library="css" name="resources/css/table-style.css" />
</h:head>
<h:body>
<h:form>
<p:growl id="message"></p:growl>
<p:tabView activeIndex="#{travelBean.index}" dynamic="true" effect="fade" effectDuration="fast">
<p:tab title="Trains">
<h:form>
<h:outputText value="Source"/>:<h:inputText id="source" value="#{travelBean.source}"></h:inputText>
<h:outputText value="Destination"/>:<h:inputText id="destination" value="#{travelBean.destination}"></h:inputText>
<h:outputText value="Date"/>:<p:calendar id="date" value="#{travelBean.date}"></p:calendar>
<h:commandButton value="Search Trains" update="table-wrapper" action="#{travelBean.travelInfo}" actionListener="#{travelBean.travelInfo}" >
<!-- <f:ajax execute="#this source destination date" render="output" /> -->
<f:attribute name="source" value="#{travelBean.source}"/>
<f:attribute name="destination" value="#{travelBean.destination}"/>
<f:attribute name="date" value="#{travelBean.date}"/>
</h:commandButton>
<h2><h:outputText id="output" value="#{travelBean.source} #{travelBean.destination} #{travelBean.date}"/></h2>
</h:form>
</p:tab>
<p:tab title="Flights">
<h1>Search flights by routes</h1>
<h:form>
<h:outputText value="Source"/>:<h:inputText id="source" value="#{travelBean.source}"></h:inputText>
<h:outputText value="Destination"/>:<h:inputText id="destination" value="#{travelBean.destination}"></h:inputText>
<h:outputText value="Date"/>:<h:inputText id="date" value="#{travelBean.date}"></h:inputText>
<h:commandButton value="Search Flights" >
<f:ajax execute="#form" render="output" />
</h:commandButton>
<h2><h:outputText id="output" value="#{travelBean.source}"/> </h2>
</h:form>
</p:tab>
</p:tabView>
</h:form>
</h:body>
</html>
I have looked at the other questions, and tried the answer but nothing worked.
Any help is highly appreciated. Thanks in advance!
Just in case the same kind of problem might happen if you are not importing the right library. Sometimes your IDE can autoimport: "import java.awt.event.ActionEvent;" instead of "import javax.faces.event.ActionEvent;" and thus causing the "same" issue. It will not be able to find the method.
action="#{travelBean.travelInfo}" is an action method. Only value methods converts travelInfo from EL expression to getTravelInfo() when searching for appropriate method. In action method exactly travelInfo() method is expected to be present in your managed bean, but it isn't.

p:push objects and update via ui:repeat

This non-working implementation tries to start a new ScheduledExecutorService to dynamically push new Items to the client and update the form:
index.xhtml
<?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://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui" xmlns:ui="http://java.sun.com/jsf/facelets"
xml:lang="en" lang="en">
<h:head>
<title>GG Well Trade</title>
</h:head>
<h:body>
<h:form>
<p:socket channel="/notify" onMessage="#{bean.add()}"/>
<p:commandButton value="Start" action="#{bean.start()}"/>
<ui:repeat value="#{bean.items}" var="item" id="content">
<p:outputLabel for="foo" value="#{item.label}" />
<p:inputText id="foo" value="#{item.value}" />
<p:commandButton value="Remove" action="#{bean.remove(item)}" update="#form" />
<br/>
</ui:repeat>
<!--<p:commandButton value="Add" action="#{bean.add}" update="#form" />-->
</h:form>
</h:body>
</html>
Item.class
public class Item {
private String label;
private String value;
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Bean.class
#ManagedBean
#ViewScoped
#PushEndpoint("/notify")
public class Bean implements Serializable{
private List<Item> items;
#PostConstruct
public void init() {
items = new ArrayList<Item>();
}
public void start() {
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
timer.scheduleAtFixedRate(()->add(),0,3,TimeUnit.SECONDS);
}
public void add() {
Item item = new Item();
item.setLabel("label" + items.size());
items.add(item);
EventBus eventBus = EventBusFactory.getDefault().eventBus();
eventBus.publish("/notify", item);
}
#OnMessage(encoders = {JSONEncoder.class})
public Item onMessage(Item item){
return item;
}
public void remove(Item item) {
items.remove(item);
}
public List<Item> getItems() {
return items;
}
}
Pressing the Add button doesn't update the form, Start button instead does but only on clicks. Is there better ways to do this?
EDIT: exception raised:
HTTP Status 500 -
type Exception report
message
description The server encountered an internal error that prevented it from fulfilling this request.
exception
javax.servlet.ServletException
javax.faces.webapp.FacesServlet.service(FacesServlet.java:671)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
java.lang.NullPointerException
Bean.add(Bean.java:43)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
javax.el.BeanELResolver.invoke(BeanELResolver.java:158)
javax.el.CompositeELResolver.invoke(CompositeELResolver.java:79)
org.apache.el.parser.AstValue.getValue(AstValue.java:159)
org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:184)
com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109)
javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:194)
org.primefaces.component.socket.Socket.getOnMessage(Socket.java:125)
org.primefaces.component.socket.SocketRenderer.encodeEnd(SocketRenderer.java:55)
javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:920)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1863)
javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:890)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1856)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
javax.faces.component.UIComponent.encodeAll(UIComponent.java:1859)
com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:458)
com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:134)
com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
note The full stack trace of the root cause is available in the Apache Tomcat/8.5.8 logs.

JSF2.2 Component to wrap a repeat

I'm using JSF 2.2 / Mojarra 2.2.8
In my model there are java.util.Set and I want to edit those Set
public class MyModel {
private Set<Foo> fooSet;
private Set<Bar> barSet;
// getters and setters
}
public class Foo {
private String label;
//getter and setter
}
public class Bar {
private String name;
// getter and setter
}
I'm using composite component for that
<h:form>
<ez:editFooSet myModel="#{someBean.myModel}"/>
<ez:editBarSet myModel="#{someBean.myModel}"/>
<!-- ... -->
</h:form>
My idea is to store a List needed by the ui:repeat in a JSF ManagedBean and use a #FacesComponent to convert the Set to List in encodeBegin() and the List to Set in updateModel()
editFooSet.xhtml :
<cc:interface componentType="my.app.component.FooSetComponent">
<cc:attribute name="myModel" type="my.app.model.MyModel" required="true"/>
</cc:interface>
<cc:implementation>
<ui:repeat value="#{fooSetBean.value}" var="item">
<h:outputLabel value="Foo label: "/>
<h:inputText value="#{item.label}"/>
<h:commandButton value="remove" action="#{fooSetBean.remove(item)}"/>
</ui:repeat>
<h:commandButton value="add" action="#{fooSetBean.add()}"/>
</cc:implementation>
FooSetBean.java
#Named
#ViewScoped
public class FooSetBean {
private List<Foo> value;
// getter and setter
puvlic void remove(Foo foo) {
fooList.remove(foo);
}
public void add() {
fooList.add(new Foo());
}
}
and the FooSetComponent.java :
#FacesComponent("my.app.component.FooSetComponent")
public class FooSetComponent extends UIInput implements NamingContainer {
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
#Override
public Object getSubmittedValue() {
return null;
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
MyModel model = (MyModel) super.getAttributes().get("myModel");
Collection<Foo> foos = model.getFooSet();
List<Foo> fooList = new ArrayList<>(foos);
FooSetBean bean = context.getApplication().evaluateExpressionGet(context, "#{fooSetBean}", FooSetBean.class) ;
bean.setValue(fooList);
super.encodeBegin(context);
}
#Override
public void updateModel(FacesContext context) {
MyModel model = (MyModel) super.getAttributes().get("myModel");
FooSetBean bean = context.getApplication().evaluateExpressionGet(context, "#{fooSetBean}", FooSetBean.class) ;
Collection<Foo> newValue = bean.getValue();
model.setFooSet(new HashSet<>(newValue));
}
}
and the same for editBarSet.xhtml, BarSetBean.java and BarSetComponent.java
And that solution is working
My problem is that I have a lot of those Set and I want to factorize this code
I want to have something like that :
<h:form>
<ez:editRepeat value="#{someBean.myModel.fooSet}" itemClass="#{Foo.class}">
<h:outputLabel value="Foo label: "/>
<h:inputText value="#{item.label"/>
</ez:editRepeat>
<ez:editRepeat value="#{someBean.myModel.barSet}" itemClass="#{Bar.class}">
<h:outputLabel value="Bar name: "/>
<h:inputText value="#{item.name}"/>
</ez:editRepeat>
<!-- ... -->
</h:form>
with the editRepeat.xhtml :
<cc:interface componentType="my.app.component.EditRepeatComponent">
<cc:attribute name="value" type="java.util.collection" required="true"/>
<cc:attribute name="itemClass" type="java.lang.Class" required="true"/>
</cc:interface>
<cc:implementation>
<ui:repeat value="#{fooSetBean.value}" var="item" id="repeat">
<cc:insertChildren/>
<h:commandButton value="remove" action="#{cc.remove(item)}"/>
</ui:repeat>
<h:commandButton value="add" action="#{cc.add()}"/>
</cc:implementation>
with a EditRepeatComponent.java
#FacesComponent("my.app.component.EditRepeatComponent")
public class EditRepeatComponent extends UIInput implements NamingContainer {
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
Collection value = (Collection) super.getAttributes().get("value");
List<Foo> list = new ArrayList<>(value);
setList(list);
super.encodeBegin(context);
}
public List getList() {
return (List) getStateHelper().get("list");
}
public void setList(List list) {
getStateHelper().put("list", list);
}
public void add() {
try {
Class itemClass = (Class) super.getAttributes().get("itemClass");
Object newItem = itemClass.newInstance();
getList().add(newItem);
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
public void remove(Object item) {
getList().remove(item);
}
#Override
public void updateModel(FacesContext context) {
// ???
}
#Override
public Object getSubmittedValue() {
// ???
}
}
But that doesn't work
After a few seconds (the system works during 1 second) I have an exeption :
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at javax.faces.component.AttachedObjectListHolder.restoreState(AttachedObjectListHolder.java:166)
at javax.faces.component.UIComponentBase.restoreState(UIComponentBase.java:1611)
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy$2.visit(FaceletPartialStateManagementStrategy.java:380)
at com.sun.faces.component.visit.FullVisitContext.invokeVisitCallback(FullVisitContext.java:151)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1689)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at com.sun.faces.application.view.FaceletPartialStateManagementStrategy.restoreView(FaceletPartialStateManagementStrategy.java:367)
at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:138)
at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:123)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:585)
at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:150)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:353)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:353)
at javax.faces.application.ViewHandlerWrapper.restoreView(ViewHandlerWrapper.java:353)
at org.omnifaces.viewhandler.RestorableViewHandler.restoreView(RestorableViewHandler.java:86)
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:197)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:121)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:63)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70)
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:247)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:76)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:166)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:197)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:759)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
And I don't understand why
And I don't know yet how to implements updateModel() or getSubmittedValue() to make all the system working
After 2 days I finally succeed
Omnifaces doc http://showcase.omnifaces.org/functions/Converters gave me the solution to deal with ui:repeat : using toArray()
<h:form>
<ez:editRepeat value="#{someBean.myModel.fooSet}" itemClass="my.app.model.Foo">
<h:outputLabel value="Foo label: "/>
<h:inputText value="#{item.label}"/>
</ez:editRepeat>
<ez:editRepeat value="#{someBean.myModel.barSet}" itemClass="my.app.model.Bar">
<h:outputLabel value="Bar name: "/>
<h:inputText value="#{item.name}"/>
</ez:editRepeat>
<!-- ... -->
</h:form>
the editRepeat.xtml (I'm using primefaces p:commanButton to specify update and process attribute so that I don't lose unsubmited input and I don't submit all the form)
<cc:interface>
<cc:attribute name="value" type="java.util.Collection" required="true"/>
<cc:attribute name="itemClass" type="java.lang.String" required="true"/>
</cc:interface>
<cc:implementation>
<h:panelGroup style="display: block; background-color: rgba(200, 200, 200, 0.5); padding: 12px;">
<ui:repeat value="#{cc.attrs.value.toArray()}" var="item">
<h:panelGroup style="background-color: rgba(200, 200, 200, 0.5); margin-left: 12px; margin-bottom: 12px; display: block; padding: 12px;">
<cc:insertChildren/>
<p:commandButton value="remove" action="#{editRepeatBean.remove(cc.attrs.value, item)}"
update="#parent:#parent:#parent" process="#parent:#parent:#parent"
style="margin-left: 12px;"/>
</h:panelGroup>
</ui:repeat>
<p:commandButton value="add" action="#{editRepeatBean.add(cc.attrs.value, cc.attrs.itemClass)}" update="#parent" process="#parent"/>
</h:panelGroup>
</cc:implementation>
the EditRepeatBean.java
#Named
#RequestScoped
public class EditRepeatBean {
public void add(Collection collection, String itemClassName) {
try {
Class itemClass = Class.forName(itemClassName);
Object item = itemClass.newInstance();
collection.add(item);
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
public void remove(Collection collection, Object item) {
collection.remove(item);
}
}
and if you have :
public class MyModel {
private Set<Foo> fooSet;
// getter and setter
}
public class Foo {
private String label;
private Set<Bar> barSet;
// getters and setters
}
public class Bar {
private String name;
// getter and setter
}
you can do
<h:form>
<ez:editRepeat value="#{someBean.myModel.fooSet}" itemClass="my.app.model.Foo">
<h:outputLabel value="Foo label: "/>
<h:inputText value="#{item.label}"/>
<ez:editRepeat value="#{item.barSet}" itemClass="my.app.model.Bar">
<h:outputLabel value="Bar name: "/>
<h:inputText value="#{item.name}"/>
</ez:editRepeat>
</ez:editRepeat>
<!-- ... -->
</h:form>
and it's working too
There is still one problem remaining : the Set must not be null, I will edit if I found a solution
EDIT : solution for the null Collection
Just change the editRepeat.xhtml interface to add a componentType so that the collection will be initialize in the encodeBegin() method and add an cc:attribute to secify the implementation of a Collection with a default value to HashSet
<cc:interface componentType="my.app.component.EditRepeatComponent">
<cc:attribute name="value" type="java.util.Collection" required="true"/>
<cc:attribute name="itemClass" type="java.lang.String" required="true"/>
<cc:attribute name="collectionImpl" type="java.lang.String" default="java.util.HashSet"/>
</cc:interface>
and the EditRepeatComponent.java
#FacesComponent("my.app.component.EditRepeatComponent")
public class EditRepeatComponent extends UIInput implements NamingContainer {
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
ELContext elContext = context.getELContext();
ValueExpression valueExpression = super.getValueExpression("value");
if (valueExpression.getValue(elContext) == null) {
try {
String collectionImpl = (String) super.getAttributes().get("collectionImpl");
Class<? extends Collection> collectionClass = (Class<? extends Collection>) Class.forName(collectionImpl);
Collection collection = collectionClass.newInstance();
valueExpression.setValue(elContext, collection);
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
super.encodeBegin(context);
}
}
well there is still a problem... when an ez:editRepeat is in an other ez:editRepeat, the remove of the inner ez:editRepeat doesn't work
Caused by: javax.el.PropertyNotFoundException: The class 'my.app.model.Bar' does not have the property 'barSet'
Edit : Final solution.
With the previous solution, there was a problem in nested <editRepeat>, during the processValidators() phase, the var of inner <repeat> components is null, causing a Exception and I don't know why, it's may be a bug...
The solution is to #Override processValidators() and re set the repeat.var.
Here is the complete solution with some improvement :
The component is warpped in an other so that the update of the parent just update the component
All the code of EditRepeatBean has been moved to EditRepeatComponent
Add var attribute
rename attributes for consistency
update/render and process/execute done programmatically
<h:form>
<ez:editRepeat value="#{someBean.myModel.fooSet}"
itemType="my.app.model.Foo"
var="foo">
<h:outputLabel value="Foo label: "/>
<h:inputText value="#{foo.label}"/>
<ez:editRepeat value="#{foo.barSet}"
itemType="my.app.model.Bar"
var="bar">
<h:outputLabel value="Bar name: "/>
<h:inputText value="#{bar.name}"/>
</ez:editRepeat>
</ez:editRepeat>
<!-- ... -->
</h:form>
editRepeat.xhtml (the wrapper) :
<cc:interface>
<cc:attribute name="value" type="java.util.Collection" required="true"/>
<cc:attribute name="itemType" type="java.lang.String" required="true"/>
<cc:attribute name="collectionType" type="java.lang.String" default="java.util.HashSet"/>
<cc:attribute name="var" type="java.lang.String" required="true"/>
</cc:interface>
<cc:implementation>
<h:panelGroup id="#{cc.id}Wrapper">
<ez:editRepeatWrapped value="#{cc.attrs.value}" var="#{cc.attrs.var}"
itemType="#{cc.attrs.itemType}"
collectionType="#{cc.attrs.collectionType}"
id="#{cc.id}Wrapped">
<cc:insertChildren/>
</ez:editRepeatWrapped>
</h:panelGroup>
</cc:implementation>
the editRepeatWrapped.xhtml :
<cc:interface componentType="my.app.component.EditRepeatComponent">
<cc:attribute name="value" type="java.util.Collection" required="true"/>
<cc:attribute name="itemType" type="java.lang.String" required="true"/>
<cc:attribute name="collectionType" type="java.lang.String" default="java.util.HashSet"/>
<cc:attribute name="var" type="java.lang.String" required="true"/>
</cc:interface>
<cc:implementation>
<h:panelGroup id="itemsGroup" style="display: block; background-color: rgba(0, 255, 0, 0.20); padding: 6px; margin: 6px;">
<ui:repeat value="#{cc.attrs.value.toArray()}" var="#{cc.attrs.var}"
id="#{cc.attrs.id}Repeat">
<h:panelGroup id="itemGroup" style="background-color: rgba(0, 255, 0, 0.2); margin-left: 12px; margin: 6px; display: block; padding: 6px;">
<cc:insertChildren/>
<p:commandButton value="remove" action="#{cc.remove()}"
style="margin-left: 12px;"/>
</h:panelGroup>
</ui:repeat>
<p:commandButton value="add" action="#{cc.add()}"/>
</h:panelGroup>
</cc:implementation>
the EditeRepeatComponent.java :
#FacesComponent("my.app.component.EditRepeatComponent")
public class EditRepeatComponent extends UIInput implements NamingContainer {
#Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
#Override
public void processValidators(FacesContext context) {
initVar(); // because repeat.var is null at this stage
super.processValidators(context);
}
#Override
public void encodeBegin(FacesContext context) throws IOException {
initValue(context);
initVar();
super.encodeBegin(context);
}
/**
* set var of the repeat component
*/
private void initVar() {
String idRepeatComponent = ((String) super.getAttributes().get("id")) + "Repeat";
String var = (String) getAttributes().get("var");
UIRepeat repeatConponent = (UIRepeat) super.findComponent(idRepeatComponent);
repeatConponent.setVar(var);
}
/**
* if the value is null then initialize the collection with the collection type attribute
*/
private void initValue(FacesContext context) {
ELContext elContext = context.getELContext();
ValueExpression valueExpression = super.getValueExpression("value");
Collection collection = (Collection) valueExpression.getValue(elContext);
if (collection == null) {
try {
String collectionType = (String) getAttributes().get("collectionType");
Class<? extends Collection> collectionClass = (Class<? extends Collection>) Class.forName(collectionType);
collection = collectionClass.newInstance();
valueExpression.setValue(elContext, collection);
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
}
public void remove() {
String var = (String) getAttributes().get("var");
Object item = evaluate(var);
Collection collection = (Collection) getAttributes().get("value");
collection.remove(item);
updateView();
}
private Object evaluate(String var) {
FacesContext facesContext = getFacesContext();
ELContext elContext = facesContext.getELContext();
Application application = facesContext.getApplication();
ExpressionFactory expressionFactory = application.getExpressionFactory();
ValueExpression expression = expressionFactory.createValueExpression(elContext, "#{" + var + "}", Object.class);
Object item = expression.getValue(elContext);
return item;
}
public void add() {
try {
Collection collection = (Collection) getAttributes().get("value");
String itemType = (String) getAttributes().get("itemType");
Class itemClass = Class.forName(itemType);
Object item = itemClass.newInstance();
collection.add(item);
updateView();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException ex) {
throw new RuntimeException(ex);
}
}
/**
* render/update and execute/process the wrapper of the component
*/
private void updateView() {
PartialViewContext context = getFacesContext().getPartialViewContext();
String parentId = this.getParent().getClientId();
context.getRenderIds().add(parentId);
context.getExecuteIds().add(parentId);
}
}
Not that <ui:repeat ... var="#{cc.attrs.var}" ...> is useless, the var isn't set that way (and I don't know why...), it is set in the EditRepeatComponent.initVar() during both encodeBegin() and processValidators() I just put var="#{cc.attrs.var}" for the understanding

Resources