I have a problem with passing method parameters to nested composite component.
I have a first component wose composite:interface looks like :
<composite:interface>
<composite:attribute name="onRowEditListener" required="false" method-signature="void listener(org.primefaces.event.RowEditEvent)"/>
</composite:interface>
It uses another composite component component which has a similar interface.
The first level component is used this way :
<mynamespace:compo1 onRowEditListener=#{bean.method}"/>
The nested one is used this way :
<mynamespace:compo2 onRowEditListener=#{cc.attrs.onRowEditListener}"/>
If I insert in both controls, I got :
in the first level control, an output like org.apache.el.MethodExpressionImpl#358f0647, which looks good to me
in the second (nested) level control, an output like org.apache.myfaces.view.facelets.el.LocationValueExpression#ff381f45 .
Raised exception looks like :
19/07/2012 19:39:02 fr.senat.faces.exceptions.DetailedExceptionHandler INFO [DetailedExceptionHandler.java:40] [http-8080-7] - Stack trace: javax.faces.FacesException: Exception while calling broadcast on component : {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /editSenateur.xhtml][Class: javax.faces.component.html.HtmlBody,Id: j_id_5][Class: org.primefaces.component.layout.Layout,Id: j_id_6][Class: org.primefaces.component.layout.LayoutUnit,Id: j_id_v][Class: org.primefaces.component.outputpanel.OutputPanel,Id: detailCommissions][Class: javax.faces.component.html.HtmlForm,Id: j_id_x][Class: org.primefaces.component.tabview.TabView,Id: tabFonctionsInternes][Class: org.primefaces.component.tabview.Tab,Id: fonctionsCommissions][Class: javax.faces.component.UINamingContainer,Id: j_id_10][Class: javax.faces.component.UIPanel,Id: j_idj_id_10__f_cc_facet][Class: org.primefaces.component.outputpanel.OutputPanel,Id: panelTabViewCommissions][Class: org.primefaces.component.tabview.TabView,Id: tabViewCommissions][Class: org.primefaces.component.tabview.Tab,Id: commissionTab][Class: org.primefaces.component.panelgrid.PanelGrid,Id: j_id_15][Class: org.primefaces.component.row.Row,Id: j_id_1b][Class: org.primefaces.component.column.Column,Id: j_id_1c][Class: javax.faces.component.UINamingContainer,Id: j_id_1d][Class: javax.faces.component.UIPanel,Id: j_idj_id_1d__f_cc_facet][Class: org.primefaces.component.datatable.DataTable,Id: sheetFonctions]} created from: /resources/sen/fonctionsCommission.xhtml at line 27 and column 162
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:430)
at javax.faces.component.UIData.broadcast(UIData.java:1610)
at javax.faces.component.UIData.broadcast(UIData.java:1596)
at javax.faces.component.UIData.broadcast(UIData.java:1596)
at javax.faces.component.UIData.broadcast(UIData.java:1596)
at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:1023)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:286)
at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1360)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:752)
at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:38)
at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:170)
at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
at org.apache.myfaces.extensions.cdi.jsf2.impl.listener.phase.CodiLifecycleWrapper.execute(CodiLifecycleWrapper.java:95)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:357)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at fr.senat.faces.filters.HibernateSessionConversationFilter.doFilter(HibernateSessionConversationFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:291)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.apache.myfaces.view.facelets.el.ContextAwareELException: javax.el.ELException: java.lang.IllegalArgumentException: wrong number of arguments
at org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:108)
at org.primefaces.component.behavior.ajax.AjaxBehaviorListenerImpl.processAjaxBehavior(AjaxBehaviorListenerImpl.java:42)
at org.primefaces.event.RowEditEvent.processListener(RowEditEvent.java:41)
at javax.faces.component.behavior.BehaviorBase.broadcast(BehaviorBase.java:74)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:406)
... 31 more
Caused by: javax.el.ELException: java.lang.IllegalArgumentException: wrong number of arguments
at org.apache.el.parser.AstValue.invoke(AstValue.java:195)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
at org.apache.myfaces.view.facelets.el.ValueExpressionMethodExpression.invoke(ValueExpressionMethodExpression.java:68)
at org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:96)
... 35 more
Caused by: java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.el.parser.AstValue.invoke(AstValue.java:191)
... 38 more
It looks like the method is properly passed to the first control, but that the EL expression gets a bullet when passed to the second...
I am using :
MyFaces 2.1.7
Tomcat 6.0.33
Thanks in advance for your help.
UPDATE
The only "progress" I can assess is a kludge...
The kludge class :
/**
*
* #author lpenet
*
* This class is a workaround kluge. Methods passed as a parameter to a
* composite component then to a PrimeFaces p:ajax seems to get a bullet
* somewhere in the process, at least with Tomcat 6 + MyFaces
* 2.1 + CODI 1.0.5 + OpenWebbeans 1.0.3 See :
* http://forum.primefaces.org/viewtopic.php?f=3&t=23558&p=72885#p72885
*
* Using this class as "componentType", one can forward the methode call.
*
* Not so nice, but... works.
*
*/
#FacesComponent(value = "fr.senat.beans.PrimefacesListenerKludge")
public class PrimefacesListenerKludge extends UINamingContainer {
#Override
public String getFamily() {
return "javax.faces.NamingContainer"; // Important! Required for
// composite components.
}
public void forwardRowEditListener(RowEditEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
Object listener = getAttributes().get("onRowEditListener");
if (listener == null) {
return;
}
MethodExpression ajaxEventListener = (MethodExpression) listener;
ajaxEventListener
.invoke(context.getELContext(), new Object[] { event });
}
}
Sample use :
<composite:interface componentType="fr.senat.beans.PrimefacesListenerKludge">
...
<composite:attribute name="onRowEditListener" required="false"
method-signature="void listener(org.primefaces.event.RowEditEvent)"
default="#{cc.parent.attrs.onRowEditListener}" />
</composite:interface>
<composite:implementation>
...
</composite:implementation>
To be honest, I do not know if it is still required with my current stack (PrimeFaces 4/MyFaces 2.1.13/OWB 1.2.1/Tomcat 7.0.32) but lacks the time to test.
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Real time updates from database using JSF/Java EE
(3 answers)
Closed 3 years ago.
I want to update component from JSF bean .
but receive NullPointerException :
java.lang.NullPointerException
at org.primefaces.PrimeFaces$Ajax.update(PrimeFaces.java:335)
at org.primefaces.PrimeFaces$Ajax.update(PrimeFaces.java:359)
at ir.moke.logmag.view.LogView.start(LogView.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:95)
at [internal classes]
at ir.moke.logmag.api.TestLog.addLog(TestLog.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.ibm.ws.jaxrs20.cdi.component.JaxRsFactoryImplicitBeanCDICustomizer.serviceInvoke(JaxRsFactoryImplicitBeanCDICustomizer.java:302)
at [internal classes]
this is my example code :
LogView.java
#SessionScoped
#Named
public class LogView implements Serializable {
private String name;
public void start(#Observes String name) {
this.name = name;
System.out.println("Receive : " + name);
PrimeFaces.current().ajax().update("form:log");
}
public String getName() {
return name;
}
}
TestLog.java
#Path("/log")
public class TestLog {
#Inject
private Event<String> event;
#POST
#Path("/add")
public Response addLog(String name) {
System.out.println("API " + name);
event.fire(name);
return Response.accepted().build();
}
}
HTML
<h:body>
<h:form id="form">
<p:outputLabel value="Output : "/><br/>
<p:outputLabel id="log" value="#{logView.name}"/>
</h:form>
</h:body>
I want to send message from rest api and update component on JSF page .
How can fix this problem ?
My environment :
Liberty 19.0.0.4
JavaEE 8
JSF 2.3
I have a very strange problem with a SessionScoped bean in a JSF 2.0 project. Using Netbeans 6.9.1, Glassfish 3 server and PrimeFaces 3 as the JSF component library.
Here is some code:
package com.hia.jsf;
import com.hia.netlabel.jpa.Genre;
import com.hia.netlabel.jpa.Label;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
#ManagedBean
#SessionScoped
public class LabelDetailJSF implements Serializable{
#ManagedProperty("#{genreLabelListJSF}")
private GenreLabelListJSF genreLabelListJSF;
private List<Genre> DetailLabelGenreList;
private Label DetailLabel;
/** Creates a new instance of LabelDetailJSF */
public LabelDetailJSF() {
}
#PostConstruct
public void init(){
System.out.print("Running init LabelDetailJSF");
if(genreLabelListJSF.getSelectedLabel()!=null)
{
System.out.print("genreLabelListJSF was not null");
this.DetailLabelGenreList=genreLabelListJSF.getSelectedLabel().getGenreList();
this.DetailLabel= (genreLabelListJSF.getSelectedLabel());
}
if(this.DetailLabelGenreList==null){
System.out.println("Bloody thing became null");
}
}
/**
* #return the DetailLabel
*/
public Label getDetailLabel() {
return DetailLabel;
}
/**
* #param DetailLabel the DetailLabel to set
*/
public void setDetailLabel(Label DetailLabel) {
System.out.println("Setting Detail Label For LabelDetailJSF to:"+DetailLabel.getLabelName());
this.DetailLabel = DetailLabel;
}
/**
* #return the DetailLabelGenreList
*/
public List<Genre> getDetailLabelGenreList() {
System.out.println("There is:"+this.DetailLabelGenreList.size()+ " Genres available");
return DetailLabelGenreList;
}
/**
* #param DetailLabelGenreList the DetailLabelGenreList to set
*/
public void setDetailLabelGenreList(List<Genre> DetailLabelGenreList) {
System.out.println("Setting the DetailLabelGenre List to have "+DetailLabelGenreList.size());
this.DetailLabelGenreList = DetailLabelGenreList;
}
/**
* #return the genreLabelListJSF
*/
public GenreLabelListJSF getGenreLabelListJSF() {
return genreLabelListJSF;
}
/**
* #param genreLabelListJSF the genreLabelListJSF to set
*/
public void setGenreLabelListJSF(GenreLabelListJSF genreLabelListJSF) {
this.genreLabelListJSF = genreLabelListJSF;
}
}
So basically I have injected another sessionscoped bean called GenreLabelListJSF into the LabelDetailJSF. I want to display the DetailLabelGenreList inside a dataTable. Here is the XHTML snippet used to display the datatable
<p:dataTable id="detailLabelGenreGrid" value="# {labelDetailJSF.detailLabelGenreList}" var="genre" paginator="true" styleClass="text70" rows="2" >
<p:column style="min-width:196px;">
#{genre.genreName}
</p:column>
</p:dataTable>
When the page loads I initially get the table with some rows in. When I click on the paging buttons that is where the fun starts.
I checked the output from all the System.out statements and found the following when the page loads initially.
INFO: Running init LabelDetailJSF
INFO: genreLabelListJSF was not null
INFO: There is:29 Genres available
INFO: There is:29 Genres available
INFO: There is:29 Genres available
INFO: There is:29 Genres available
INFO: There is:29 Genres available
INFO: There is:29 Genres available
When I click on the page buttons of the datatable I get the following:
INFO: Running init LabelDetailJSF
INFO: Bloody thing became null
SEVERE: javax.el.ELException: /LabelDetail.xhtml #62,165 value="# {labelDetailJSF.detailLabelGenreList}": java.lang.NullPointerException
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:107)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:190)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:178)
at javax.faces.component.UIData.getValue(UIData.java:554)
at org.primefaces.component.datatable.DataTable.getValue(DataTable.java:731)
at javax.faces.component.UIData.getDataModel(UIData.java:1248)
at javax.faces.component.UIData.setRowIndex(UIData.java:447)
at javax.faces.component.UIData.visitTree(UIData.java:1184)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1457)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1457)
at javax.faces.component.UIForm.visitTree(UIForm.java:333)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1457)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1457)
at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:223)
at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:177)
at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:131)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:430)
at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:143)
at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:199)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:277)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)
at com.sun.grizzly.comet.CometEngine.executeServlet(CometEngine.java:473)
at com.sun.grizzly.comet.CometEngine.handle(CometEngine.java:341)
at com.sun.grizzly.comet.CometAsyncFilter.doFilter(CometAsyncFilter.java:84)
at com.sun.grizzly.arp.DefaultAsyncExecutor.invokeFilters(DefaultAsyncExecutor.java:161)
at com.sun.grizzly.arp.DefaultAsyncExecutor.interrupt(DefaultAsyncExecutor.java:137)
at com.sun.grizzly.arp.AsyncProcessorTask.doTask(AsyncProcessorTask.java:88)
at com.sun.grizzly.http.TaskBase.run(TaskBase.java:189)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.NullPointerException
at com.hia.jsf.LabelDetailJSF.getDetailLabelGenreList(LabelDetailJSF.java:72)
at sun.reflect.GeneratedMethodAccessor951.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:302)
at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:175)
at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
at com.sun.el.parser.AstValue.getValue(AstValue.java:116)
at com.sun.el.parser.AstValue.getValue(AstValue.java:163)
at com.sun.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:219)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102)
... 48 more
From what I can see it is almost like the bean looses scope and gets recreated all the time. Initially the values are there then when the paging starts the bean looses value. For example I noticed that the #ManagedProperty bean also becomes null when the paging starts. Which is kind of crazy as it is also a session scoped bean.
Still a new hand at JSF so I probably made some noob mistake. Must mention that I did initially create this as a ViewScoped bean by accident, and after changing the bean to SessionScoped I undeployed the application restarted Glassfish and build and deployed it again.
Any ideas?
You're using the wrong #SessionScoped annotation.
If you've registered the bean with the JSF #ManagedBean annotation, then you need to import the #SessionScoped from the JSF (javax.faces) package as follows:
import javax.faces.bean.SessionScoped;
When you incorrectly use a CDI scope on a JSF managed bean, then there is effectively no JSF scope for the JSF managed bean and it falls back to its default #RequestScoped, which creates a new instance in each HTTP request.
If you've registered the bean with the CDI #Named annotation, then you need to import the #SessionScoped from the CDI (javax.enterprise.context) package as follows:
import javax.enterprise.context.SessionScoped;
When you incorrectly use a JSF scope on a CDI managed bean, then there is effectively no CDI scope for the CDI managed bean and it falls back to its default #Dependent scope, which creates a new instance in each EL expression.
See also:
How to choose the right bean scope?
Backing beans (#ManagedBean) or CDI Beans (#Named)?
What is the default Managed Bean Scope in a JSF 2 application?
I was wondering if and how it is possible to display an <o:graphicImage> as thumbnail inside a <p:lightbox>. To be more precise, I wanted to achieve something like this:
<p:dataTable id="articles" var="article"
value="#{articleMB.articles}" selectionMode="single"
rowKey="#{articles.id}"
selection="#{articleMB.selectedArticle}">
<p:column>
<p:lightBox styleClass="imagebox" id="lighbox">
<h:outputLink value="#{imageBean.getFirstImage(article, true)}">
<o:graphicImage value="#{imageBean.getFirstImage(article, true)}" dataURI="true" height="80" />
</h:outputLink>
</p:lightBox>
</p:column>
</p:dataTable>
Which isn't working obviously, since there's no proper URL passed to the lightbox.
imageBean.getFirstImage(Article article, boolean thumbnail) returns a byte[] of the image, since the images I want to access are stored on an external source.
Edit: So I've done as BalusC mentioned and it seems to be the proper approach. But now I'm getting the following exception:
Caused by: java.lang.IllegalArgumentException: java.lang.ClassCastException#2eae887c
at sun.reflect.GeneratedMethodAccessor307.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.omnifaces.resourcehandler.GraphicResource.getInputStream(GraphicResource.java:259)
at com.sun.faces.application.resource.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:335)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at org.primefaces.application.resource.PrimeResourceHandler.handleResourceRequest(PrimeResourceHandler.java:87)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:655)
... 32 more
This is the method that actually returns the image. It is working fine in every other context:
public byte[] getFirstImage(final Article article, boolean thumbnail)
{
try
{
File dir = new File(getImageFolder(article.getImageFolder(), thumbnail));
File[] files = dir.listFiles(new FilenameFilter()
{
#Override
public boolean accept(File dir, String name)
{
return name.startsWith(String.valueOf(article.getArticleId()));
}
});
Arrays.sort(files);
return Files.readAllBytes(files[0].toPath());
}
catch (Exception e)
{
return new byte[1];
}
}
Edit 2: As mentioned in the comments, I'm facing another weird behaviour. It runs perfectly fine on my local machine but on the server it throws following exception:
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.omnifaces.resourcehandler.GraphicResource.getInputStream(GraphicResource.java:259)
at com.sun.faces.application.resource.ResourceHandlerImpl.handleResourceRequest(ResourceHandlerImpl.java:335)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at org.primefaces.application.resource.PrimeResourceHandler.handleResourceRequest(PrimeResourceHandler.java:87)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:153)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:655)
... 32 more
For exactly this reason, OmniFaces 2.5 introduced the #{of:graphicImageURL()} EL function. This works only if your ImageBean is annotated with #GraphicImageBean.
import org.omnifaces.cdi.GraphicImageBean;
#GraphicImageBean
public class ImageBean {
// ...
}
<h:outputLink value="#{of:graphicImageURL('imageBean.getFirstImage(article, false)')}">
<o:graphicImage value="#{imageBean.getFirstImage(article, true)}" dataURI="true" height="80" />
</h:outputLink>
See also the #GraphicImageBean showcase.
Update: to be clear, you need a converter for non-standard types such as Article. Why such a converter is needed and how to create it is detailed in Conversion Error setting value for 'null Converter'. If you create a #FacesConverter(forClass=Article.class), then the OmniFaces GraphicImage will automatically pickup it.
In your particular case it's however more efficient to just pass the identifier to the image streamer method right away, this saves an additional conversion step. Provided that your Article object has an id property, here's how:
<h:outputLink value="#{of:graphicImageURL('imageBean.getFirstImage(article.id, false)')}">
<o:graphicImage value="#{imageBean.getFirstImage(article.id, true)}" dataURI="true" height="80" />
</h:outputLink>
public byte[] getFirstImage(Long articleId, boolean thumbnail) {
// ...
}
Namely, JSF already has builtin converters for standard types such as Long and boolean.
I'm getting this error with f:setPropertyActionListener and i can't figure out why:
HTTP Status 500 - For input string: "selectedItem"
exception:
javax.servlet.ServletException: For input string: "selectedItem"
javax.faces.webapp.FacesServlet.service(FacesServlet.java:667)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause:
java.lang.NumberFormatException: For input string: "selectedItem"
java.lang.NumberFormatException.forInputString(Unknown Source)
java.lang.Integer.parseInt(Unknown Source)
java.lang.Integer.parseInt(Unknown Source)
javax.el.ListELResolver.coerce(ListELResolver.java:157)
javax.el.ListELResolver.getType(ListELResolver.java:50)
com.sun.faces.el.DemuxCompositeELResolver._getType(DemuxCompositeELResolver.java:215)
com.sun.faces.el.DemuxCompositeELResolver.getType(DemuxCompositeELResolver.java:242)
org.apache.el.parser.AstValue.getType(AstValue.java:60)
org.apache.el.ValueExpressionImpl.getType(ValueExpressionImpl.java:168)
com.sun.faces.facelets.el.TagValueExpression.getType(TagValueExpression.java:98)
com.sun.faces.facelets.tag.jsf.core.SetPropertyActionListenerHandler$SetPropertyListener.processAction(SetPropertyActionListenerHandler.java:209)
javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:813)
javax.faces.component.UICommand.broadcast(UICommand.java:300)
javax.faces.component.UIData.broadcast(UIData.java:1108)
javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:654)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Table Class:
// imports omitted
public class Table<E> extends ArrayList<E> {
private E selectedItem;
public E getSelectedItem() { return selectedItem; }
public void setSelectedItem(E value) { selectedItem = value; }
}
MyTable Bean:
// Imports omitted
#ManagedBean
#ViewScoped
public class MyTable extends Table<File> {
#PostConstruct
public void initBean() {
// Loading some files into the list
}
}
This is the XHTML:
<html> <!-- Namespaces and stuff omitted -->
<h:head>...</h:head>
<h:body>
<h:form>
<h:dataTable var="item" value="#{myTable}">
<h:column>
<h:commandButton value="Try Me!">
<f:setPropertyActionListener value="#{item}" target="#{myTable.selectedItem}"/>
<!-- I'm getting a warning from eclipse here: property not found -->
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
I'm using Eclipse Luna (Java EE IDE) with Tomcat 8 and JSF 2.2.11 (mojarra). Any hints are accepted, thank you!
You kind of coded your self into a corner with your fancy bean implementation. Take a look at the processing steps for the f:setActionPropertyListener. Your code is choking at step 3:
If the value of the "value" expression is not null, call getType() on the "value" and "target" ValueExpressions to determine their property types
for the following reasons:
The EL processor has determined that myTable is a List. Because of this, it has delegated the evaluation of the expression myTable.selectedItem to the javax.el.ListELResolver class
The ELResolver, on encountering the myTable base object, determines it's a List and automatically assumes that the following string is referring to a list index, i.e. myTable.selectedItem, where selectedItem is supposed to be a list index (per the EL specification, the [] and . are interchangeable for lists). You can see it in action here. While it may not be immediately apparent in the tomcat source, if you check the comment in a similar implementation in Jboss for example, you have the following comment:
If the base object is a list, returns the value at the given index. The index is specified by the property argument, and coerced into an integer
"property argument" here is referring to the selectedItem portion of your expression
The EL processor now attempts to convert the string selectedItem to an integer (to be used as a list index) which in turn explodes in a 500
You'll make your work a whole lot easier by not combining your data structure and your backing bean, like Rami. Q suggested. Much cleaner that way IMO
my Answer should be a comment, but its too long for that, so i write it as an answer.
i see some "ERRORS" in your code:
ALL JSF Beans & objects have to be Serializable
if you use Generic Types, they should be Serializable TOO:
public class GenericObject<T extends Serializable> implements Serializable {...}
Setter & Getter of a JSF Object should be like (this.attr = ...;):
public void setSelectedItem(E value) { this.selectedItem = value;}
be sure that you import the managedBean correctly:
import javax.faces.bean.ManagedBean;
instead of <h:dataTable var="item" value="#{myTable}"> you should use <h:dataTable var="item" value="#{myTable.items}">
and declare items as List Attribute of your bean with getter and setter
I've been trying a lot of different things that I would think would work like expected. However, they are causing me some frustration. Here's the scoop:
I am using ICEFaces 1.8 components in a Java EE web application. My goal is to render a bunch of ice:commandButtons on the page based on a query to my database. I want these buttons to be able to toggle selections that I will later use for parameters to another query to the database (basically a query front end of sorts for a set of users). I would like the output to look like so:
When I click on a button, I would like the following update to my page:
When I created the buttons on my page statically, as such:
<ice:commandButton id="seasonSEP09" style="background-color: #FFFFFF;" partialSubmit="true" actionListener="#{bean.updateSeasons}" value="2009-2010" />
<ice:commandButton id="seasonSEP08" style="background-color: #FFFFFF;" partialSubmit="true" actionListener="#{bean.updateSeasons}" value="2008-2009" />
<ice:commandButton id="seasonSEP07" style="background-color: #FFFFFF;" partialSubmit="true" actionListener="#{bean.updateSeasons}" value="2007-2008" />
<ice:commandButton id="seasonSEP06" style="background-color: #FFFFFF;" partialSubmit="true" actionListener="#{bean.updateSeasons}" value="2006-2007" />
this works great, and each button works individually as I would expect. My backing bean is updated, the parameters are correctly added in updateSeasons() method, and my output at the end yields the correct records.
However, I know this is not what I want. I don't want to update these anytime another season is entered in the system. Maintainance nightmare, right?
So what I want to do is dynamically generate these ice:commandButton components based on my database table full of Season objects. Here is the Season class I am using:
public class Season
{
String StartMonth;
String Season;
public String getStartMonth()
{
return StartMonth;
}
public void setStartMonth(String startMonth)
{
StartMonth = sweep;
}
public void setSeason(String season)
{
Season = season;
}
public String getSeason()
{
return Season;
}
}
Very straightforward. Two properties, which I'm guaranteed to be unique in the database.
Here is the backing bean I am using:
public class Bean
{
public Bean()
{
defineSeasonsList();
}
public List<HtmlCommandButton> seasonsList;
// seasonsList getter & setter omitted
public List<String> selectedSeasons;
// selectedSeasons getter & setter omitted
private void defineSeasonsList()
{
seasonsList = new ArrayList<HtmlCommandButton>();
selectedSeasons = new ArrayList<String>();
try
{
hibernate.openTransaction();
for(Season season:defineSeasonsListFromDataSource()))
{
HtmlCommandButton button = new HtmlCommandButton();
button.setId("season" + season.getStartMonth());
button.setValue(season.getSeason);
button.setStyle("background-color: #FFFFFF;");
button.setPartialSubmit(true);
seasonsList.add(button);
}
}
catch (Exception e)
{
System.out.println("Error defining seasons list: " + e.getMessage());
}
finally
{
hibernate.commitTransaction();
}
}
public void updateSeasons(ActionEvent ae)
{
HtmlCommandButton selected = (HtmlCommandButton) ae.getComponent();
if(selectedSeasons.contains(selected.getValue().toString()))
{
selectedSeasons.remove(selected.getValue().toString());
selected.setStyle("background: #FFFFFF;");
}
else
{
selectedSeasons.add(selected.getValue().toString());
selected.setStyle("background: #009DD9; color: #FFFFFF;");
}
}
}
OK, so here comes my dilemma(s).
First, I tried to render this markup:
<p>
<ice:panelGroup>
<ice:panelSeries id="seasonsList" value="#{bean.seasonsList}" var="season">
<ice:commandButton binding="#{season}"/>
</ice:panelSeries>
</ice:panelGroup>
</p>
And I get this output:
So, being frustrated and adventurous, I tried to render this markup to achieve my goal:
<p>
<ice:panelGroup>
<ice:panelSeries id="seasonsList" value="#{bean.seasonsList}" var="season">
<ice:commandButton id="#{season.id}" partialSubmit="true" style="background-color: #FFFFFF" value="#{season.value}" actionListener="#{bean.updateSeasons}"/>
</ice:panelSeries>
</ice:panelGroup>
</p>
Which yielded the following stacktrace:
Aug 4, 2009 2:28:11 PM com.sun.faces.lifecycle.Phase doPhase
SEVERE: JSF1054: (Phase ID: RENDER_RESPONSE 6, View ID: /phase1.jspx) Exception thrown during phase execution: javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl#1a477b7]
Aug 4, 2009 2:28:11 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet Persistent Faces Servlet threw exception
java.lang.IllegalArgumentException: #{season.id}
at javax.faces.component.UIComponentBase.validateId(UIComponentBase.java:549)
at javax.faces.component.UIComponentBase.setId(UIComponentBase.java:351)
at javax.faces.webapp.UIComponentTag.createComponent(UIComponentTag.java:219)
at javax.faces.webapp.UIComponentClassicTagBase.createChild(UIComponentClassicTagBase.java:486)
at javax.faces.webapp.UIComponentClassicTagBase.findComponent(UIComponentClassicTagBase.java:670)
at javax.faces.webapp.UIComponentClassicTagBase.doStartTag(UIComponentClassicTagBase.java:1142)
at com.icesoft.faces.component.CommandButtonTag.doStartTag(CommandButtonTag.java:741)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:204)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.executeJspLifecycle(Parser.java:229)
at com.icesoft.faces.webapp.parser.Parser.parse(Parser.java:162)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:464)
at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:153)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at com.icesoft.faces.webapp.http.core.JsfLifecycleExecutor.apply(JsfLifecycleExecutor.java:17)
at com.icesoft.faces.context.View$2$1.respond(View.java:47)
at com.icesoft.faces.webapp.http.servlet.ServletRequestResponse.respondWith(ServletRequestResponse.java:197)
at com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet$ThreadBlockingRequestResponse.respondWith(ThreadBlockingAdaptingServlet.java:36)
at com.icesoft.faces.context.View$2.serve(View.java:72)
at com.icesoft.faces.context.View.servePage(View.java:133)
at com.icesoft.faces.webapp.http.core.SingleViewServer.service(SingleViewServer.java:52)
at com.icesoft.faces.webapp.http.common.ServerProxy.service(ServerProxy.java:11)
at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet$4.service(MainSessionBoundServlet.java:114)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet.service(MainSessionBoundServlet.java:160)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher$1.service(SessionDispatcher.java:42)
at com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet.service(ThreadBlockingAdaptingServlet.java:19)
at com.icesoft.faces.webapp.http.servlet.EnvironmentAdaptingServlet.service(EnvironmentAdaptingServlet.java:63)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:62)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:153)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
Am I trying to do something that I shouldn't be doing?
Is there a better way to accomplish this goal?
If more information is necessary I'd be happy to provide it.
Thanks in advance, my friends.
UPDATE:
So I tried changing the seasonsList collection from List to List and rendering some different markup, like so:
<p>
<ice:panelGroup>
<ice:panelSeries value="#{bean.seasonsList}" var="season">
<ice:commandButton partialSubmit="true" style="background-color: #FFFFFF" value="#{season}" actionListener="#{Phase1EventBean.updateSeasons}"/>
</ice:panelSeries>
</ice:panelGroup>
</p>
And changing the defineSeasonsList() method to:
public void defineNationalSeasonsList()
{
try
{
seasonsList = new ArrayList<String>();
selectedSeasonsList = new ArrayList<String>();
hibernate.openTransaction();
for(UedaNationalDates season:hibernate.getList(new UedaNationalDates(), QueryFactory.getUedaNationalSeasons(hibernate.getHibSession())))
{
nationalSeasonsList.add(season.getSeason());
}
}
catch (Exception e)
{
System.out.println("Error defining nationalMeasurementPeriods: " + e.getMessage());
}
finally
{
hibernate.commitTransaction();
}
}
This actually renders all the buttons I would like to see, and adds them correctly to the selectedSeasonsList in my backing bean when I click on them, and removes them from it when I click again.
However, on the UI, every button appears to be toggled when I click just the one button. For example, when I click on 2009-2010, this is what I see:
<ice:commandButton binding="#{season}"/>
The binding attribute must be bound to a bean property of type UIComponent. It is used where you want the framework to give you a reference to the component in a backing bean or to provide an instance from the backing bean). See section 3.1.5 of the JSF 1.2 spec for more details.
<ice:commandButton id="#{season.id}"
partialSubmit="true"
style="background-color: #FFFFFF"
value="#{season.value}"
actionListener="#{Phase1EventBean.updateSeasons}"/>
The id attribute cannot be dynamic - JSF will take care of ensuring its uniqueness on the client using the clientId (read this for more detail).
EDIT:
However, on the UI, every button appears to be toggled when I click just the one button.
I am guessing that ice:panelSeries does not store the component state of every row as some repeating controls do (e.g. dataTable). Remember, there is only one button instance, even if it is encoded/decoded once per "row".
I've never used ICEfaces, but I suggest binding to beans similar to this:
public class Bean {
private final List<SelectionBean> seasonsList = Arrays.asList(
new SelectionBean("Spring"), new SelectionBean("Summer"),
new SelectionBean("Autumn"), new SelectionBean("Winter"));
public List<SelectionBean> getSeasonsList() { return seasonsList; }
public static class SelectionBean {
private String season;
private boolean selected;
public SelectionBean() {}
public SelectionBean(String season) { this.season = season; }
public String getSeason() { return season; }
public void setSeason(String season) { this.season = season; }
public String toggle() {
System.out.println("toggle " + season);
selected = !selected;
return null;
}
public String getStyle() {
return selected ? "background-color: yellow" : "background-color: blue";
}
}
}
I've pared the logic down to the bare minimum, but hopefully you get how to modify the logic to put the hibernate support back in. Your component would then become something like this:
<ice:panelSeries value="#{bean.seasonsList}" var="item">
<ice:commandButton partialSubmit="true"
style="#{item.style}"
value="#{item.season}"
action="#{item.toggle}"/>
</ice:panelSeries>
So, for each item in your list, all the binding goes back to the one piece of state (a SelectionBean instance) and you don't try to store any non-declarative state on the component itself.
I try to use action over actionListener when I can - it keeps JSF stuff out of the POJOs.