How to pass a value (selected from selectOneMenu)from page JSF to another - jsf

I want to fill an selectOneMenu with fields from my DataBase
and then use the chosen value in another request SQL.
For know I have my selectOneMenu filled from my data but I dont Know how to retrieve the chosen value and show it into another page. The error is:
org.apache.jasper.JasperException: An exception occurred processing JSP page /Result.jsp
Stacktrace:
at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:553)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:442)
Also I want to write a clean code , I want to create class connection and use it to connect one time in the first page and deconnect at the last page(when I finish).
Bean:
public class BeanTools {
private List<SelectItem> mesElements;
private String maValeur;
public PreparedStatement st;
Connectionx con = new Connectionx(); **//IF I do that on N page I will have N connection!!**
Connection cx = (Connection) con.Connx();
public BeanTools() {
}
public String getMaValeur() {
return maValeur;
}
public void setMaValeur(String maValeur) {
this.maValeur = maValeur;
}
public void setMesElements(List<SelectItem> mesElements) {
this.mesElements = mesElements;
}
public Iterable<String> remplireItem() throws ClassNotFoundException, SQLException
{
String sql;
sql ="select issuestatus.pname from issuestatus;";
System.out.println("sql");
st=(PreparedStatement) cx.prepareStatement(sql);
ResultSet rs1 = st.executeQuery();System.out.println("execute");
String nbb;
ArrayList<String> list = new ArrayList<String>();
while(rs1.next())
{
nbb = rs1.getString("pname");
System.out.println(nbb);
list.add(nbb);
System.out.println("list"+list.toString());
}
return list;
}
public List<SelectItem> getMesElements() throws SQLException, ClassNotFoundException {
if (mesElements == null) {
mesElements = new ArrayList<SelectItem>();
for (String val : remplireItem()) {
mesElements.add(new SelectItem(val));
}
}
return mesElements;
}
}
First JSF page:
<h:form id="form">
Issue status 2 :<h:selectOneMenu style="width:200px" value="#{BeanTools.maValeur}" >
<f:selectItems value="#{BeanTools.mesElements}"/>
</h:selectOneMenu>
<h:commandButton action="submit" value="submit"/>
</h:form>
Second JSF page:
<body>
<h:outputText value="#{BeanTools.maValeur}" />
</body>
The Faces config:
<managed-bean>
<managed-bean-name>BeanTools</managed-bean-name>
<managed-bean-class>KPIs.BeanTools</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<navigation-rule>
<from-view-id>/welcomeJSF.jsp</from-view-id>
<navigation-case>
<from-outcome>submit</from-outcome>
<to-view-id>/Result.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Class Connection:
public class Connectionx {
public Connection cx=null;
public Statement st;
public Connectionx() {}
public Connection Connx()
{
System.out.println("enregister le driver");
try {
Class.forName("com.mysql.jdbc.Driver");
}
catch( Exception ex )
{
System.err.println("Erreur lors du chargement du driver"+ex.getMessage() );
}
try {
/** Connection */
cx = (Connection) DriverManager.getConnection ( "jdbc:mysql://localhost/jiradb","","" );
}
catch( SQLException ex )
{
System. err. println( "Error ") }
return cx;
}
The whole stacktrace:
org.apache.jasper.JasperException: An exception occurred processing JSP page /Result.jsp at line 19
16: <body>
17: <h1>Hello World!</h1>
18:
19: <h:outputText value="#{BeanTools.maValeur}" />
20:
21: </body>
22: </html>
Stacktrace:
at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:553)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:442)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:391)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
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.ApplicationDispatcher.invoke(ApplicationDispatcher.java:684)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:471)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:402)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:546)
at com.sun.faces.application.view.JspViewHandlingStrategy.executePageToBuildView(JspViewHandlingStrategy.java:363)
at com.sun.faces.application.view.JspViewHandlingStrategy.buildView(JspViewHandlingStrategy.java:154)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:100)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:313)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
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:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: javax.servlet.ServletException: javax.servlet.jsp.JspException: java.lang.IllegalStateException: Component javax.faces.component.UIViewRoot#144c984 not expected type. Expected: javax.faces.component.UIOutput. Perhaps you're missing a tag?
at org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:907)
at org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:840)
at org.apache.jsp.Result_jsp._jspService(Result_jsp.java:84)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:419)
... 38 more
Caused by: java.lang.IllegalStateException: Component javax.faces.component.UIViewRoot#144c984 not expected type. Expected: javax.faces.component.UIOutput. Perhaps you're missing a tag?
at com.sun.faces.taglib.html_basic.OutputTextTag.setProperties(OutputTextTag.java:126)
at javax.faces.webapp.UIComponentClassicTagBase.findComponent(UIComponentClassicTagBase.java:690)
at javax.faces.webapp.UIComponentClassicTagBase.doStartTag(UIComponentClassicTagBase.java:1311)
at com.sun.faces.taglib.html_basic.OutputTextTag.doStartTag(OutputTextTag.java:163)
at org.apache.jsp.Result_jsp._jspx_meth_h_005foutputText_005f0(Result_jsp.java:103)
at org.apache.jsp.Result_jsp._jspService(Result_jsp.java:73)
... 41 more

Finally, there's the root cause of the exception:
Caused by: java.lang.IllegalStateException: Component javax.faces.component.UIViewRoot#144c984 not expected type. Expected: javax.faces.component.UIOutput. Perhaps you're missing a tag?
You forgot the <f:view> in Result.jsp. All JSF components has to go inside a <f:view>. Edit your Result.jsp so that it look like the following basic template:
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%#taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<!DOCTYPE html>
<f:view>
<html lang="en">
<head>
<title>JSP page</title>
</head>
<body>
<h:outputText value="JSF components here." />
</body>
</html>
</f:view>

Related

Why my custom javax.faces.context.ExceptionHandler doesn't handle javax.validation.ConstraintViolationException

My custom exception handler is not being invoked by the container to intercept (checked or unchecked) exceptions (I verified it through the debugger). I have this Entity bean class with #Email annotation for the email field, and when the user types in an invalid email through the JSF page, an error message is being displayed, however, the error message is not the one I set through the custom exception handler class, rather it is the one I have set as the default message for the #Email annotation. The error message generated by the custom exception handler has a prefix string "Exception caught by the custom Exception handler: ". I surmise that an invalid email should throw a ConstraintViolationException, which would be an ideal case for the exception handler to catch.
The JSF page allows the user information to be updated, so when I update the user's email with an invalid one and click the "Update" CommandButton, the registered action method is not being invoked (I verified it through the debugger). Furthermore, what I don't seem to figure out, is that when the "invalid email" error message is displayed on the JSF page, the "Add User" command Button gets disabled, so I can not navigate to the "Add User" JSF page. Any idea, why the exception handler and the page navigation (Add User) are not working in case of an error?
public class CustomExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler wrapped;
private final static Logger logger = Logger.getLogger(CustomExceptionHandler.class.getName());
public CustomExceptionHandler(ExceptionHandler w) {
wrapped = w;
}
#Override
public ExceptionHandler getWrapped() {
return wrapped;
}
#Override
public void handle() throws FacesException {
Iterator iterator = getUnhandledExceptionQueuedEvents().iterator();
while (iterator.hasNext()) {
ExceptionQueuedEvent event = (ExceptionQueuedEvent) iterator.next();
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext)event.getSource();
Throwable throwable = context.getException();
FacesContext fc = FacesContext.getCurrentInstance();
try {
Flash flash = fc.getExternalContext().getFlash();
// Put the exception in the flash scope to be displayed in the error
// page if necessary ...
String errorMessage = "Exception caught by the custom Exception handler: "+throwable.getMessage();
logger.severe(errorMessage);
flash.put("errorDetails", errorMessage);
NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler();
//navigationHandler.handleNavigation(fc, null, "/loginmanagement");
navigationHandler.handleNavigation(fc, null, "error?faces-redirect=true");
fc.renderResponse();
} finally {
iterator.remove();
}
}
// Let the parent handle the rest
getWrapped().handle();
}
}
The factory class:
public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {
private ExceptionHandlerFactory parent;
public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
this.parent = parent;
}
#Override
public ExceptionHandler getExceptionHandler() {
ExceptionHandler result = new CustomExceptionHandler(parent.getExceptionHandler());
return result;
}
}
The faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.3"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd">
<application>
<resource-bundle>
<base-name>webmessages</base-name>
<var>bundle</var>
</resource-bundle>
<locale-config>
<default-locale>en</default-locale>
<!-- <supported-locale>es</supported-locale> -->
</locale-config>
</application>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>
<location>/loginmanagement.xhtml</location>
</error-page>
<factory>
<exception-handler-factory>
org.me.mavenlistservicedb.applicationexception.CustomExceptionHandlerFactory
</exception-handler-factory>
</factory>
</faces-config>
Here is the relevant excerpt of the JSF page
<h:column>
<f:facet name="header">#{bundle.loginmanagementemail}</f:facet>
<h:inputText value = "#{l.email}"
size ="30" rendered = "#{l.canUpdate}" />
<h:outputText value = "#{l.email}"
rendered = "#{not l.canUpdate}" />
</h:column>
<f:facet name="footer">
<h:panelGroup style="display: block; border-color: aquamarine;text-align: center;">
<h:commandButton id="update"
value="Save updates"
action="#{loginManagment.saveUpdate}" />
<h:commandButton id="add"
value="Add User"
action="adduser" />
</h:panelGroup>
</f:facet>
I use Netbeans on Windows 10 with Glassfish 5.1.
Thanks

Is there news on getting the URL of <p:graphicImage>?

Basically my question is the same as this one answered five years ago: I would like to output the URL of a server-provided image as from <p:graphicImage>, but just the URL and not an <img> tag. What I am looking for is a solution like this:
(This is not working code, just to illustrate:)
<p:graphicImage var="url" value="#{MyForm.image}"/>
<span id="imageData" data-image="#{url}/>
Which should output to the HTML like this:
<span id="imageData" data-image="http://localhost:8080/contextPath/javax.faces.resource/dy...
I am currently using a JavaScript work-around for this, but this requirement seems so common to me that I would expect newer development has already targeted it and there is a built-in solution. Is there news on that topic since the last five years?
Just took a look at the GraphicImageRenderer wanting to figure out how they produce that dynamic URL. They are using a static method on their DynamicContentSrcBuilder:
protected String getImageSrc(FacesContext context, GraphicImage image) throws Exception {
String name = image.getName();
if (name != null) {
// ...
} else {
return DynamicContentSrcBuilder.build(context, image.getValue(), image, image.isCache(), DynamicContentType.STREAMED_CONTENT, image.isStream());
}
}
So why not just reproduce this call on the p:graphicImage component?
I'll first bind it to a property of a RequestScoped bean and then get the URI from that bean which reproduces behavior of the renderer shown above:
The XHTML code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
<h:head/>
<body>
<p:graphicImage binding="#{myBean.imgComponent}"
value="#{myBean.img}" />
<h:outputText id="imageData" pt:data-image="#{myBean.getImgUri()}" />
</body>
</html>
And my bean aka myBean:
package test;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.enterprise.context.RequestScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import org.primefaces.application.resource.DynamicContentType;
import org.primefaces.component.graphicimage.GraphicImage;
import org.primefaces.model.StreamedContent;
import org.primefaces.util.DynamicContentSrcBuilder;
#Named
#RequestScoped
public class MyBean {
private GraphicImage imgComponent;
private String imgUri;
public StreamedContent getImg() throws IOException {
// ...
}
public GraphicImage getImgComponent() {
return imgComponent;
}
public void setImgComponent(GraphicImage imgComponent) {
this.imgComponent = imgComponent;
}
public String getImgUri() throws UnsupportedEncodingException {
assert null != imgComponent;
if (null == imgUri) {
// here we reproduce the GraphicImageRenderer behavior:
imgUri = DynamicContentSrcBuilder.build(FacesContext.getCurrentInstance(), imgComponent.getValue(),
imgComponent, imgComponent.isCache(), DynamicContentType.STREAMED_CONTENT, imgComponent.isStream());
}
return imgUri;
}
}
Alternatively we can use the GraphicImageRenderer and publish the protected method getImageSrc:
public class MyBean {
// ...
public String getImgUri() throws Exception {
assert null != imgComponent;
if (null == imgUri) {
imgUri = new GraphicImageRendererXtension().getPublicImageSrc(FacesContext.getCurrentInstance(),
imgComponent);
}
return imgUri;
}
}
public class GraphicImageRendererXtension extends GraphicImageRenderer {
// publish the protected GraphicImageRenderer#getImageSrc method:
public String getPublicImageSrc(FacesContext context, GraphicImage image) throws Exception {
return getImageSrc(context, image);
}
}
But why did I write #{myBean.getImgUri()} instead of #{myBean.imgUri}? I'm still not sure, but using the latter produces a PropertyNotFoundException:
javax.el.PropertyNotFoundException: /myView.xhtml #20,46 value="#{myBean.imgUri}": ELResolver did not handle type: [null] with property of [imgUri]
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:117)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:200)
at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:187)
at javax.faces.component.UIOutput.getValue(UIOutput.java:179)
at com.sun.faces.renderkit.html_basic.HtmlBasicInputRenderer.getValue(HtmlBasicInputRenderer.java:205)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.getCurrentValue(HtmlBasicRenderer.java:360)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeEnd(HtmlBasicRenderer.java:171)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:949)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1912)
at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:918)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:309)
at com.sun.faces.renderkit.html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:114)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:918)
at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:86)
at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:73)
at org.primefaces.component.layout.LayoutUnitRenderer.encodeEnd(LayoutUnitRenderer.java:49)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:949)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1912)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1908)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:491)
at javax.faces.view.ViewDeclarationLanguageWrapper.renderView(ViewDeclarationLanguageWrapper.java:126)
...
Caused by: javax.el.PropertyNotFoundException: ELResolver did not handle type: [null] with property of [imgUri]
at org.apache.el.parser.AstValue.getValue(AstValue.java:174)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:190)
at org.apache.webbeans.el22.WrappedValueExpression.getValue(WrappedValueExpression.java:68)
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:115)
... 122 more
Possibly invoking the DynamicContentSrcBuilder.build() method somehow messes up the ongoing resolving of the value expression #{myBean.imgUri}, while #{myBean.getImgUri()} is not affected.
Getting back to your question: no there is no news. The dynamic URI is built and directly sent to the browser while rendering. The GraphicImage component does not provide any getter for this. What I presented here is a server side variant of a work around without the need to create a new servlet.
Edit:
Of course you can also parameterize the getImageUri method and bind your Image component to some arbitrary variable which would bring you closer to your demonstration var="..." example:
public class MyBean {
// ...
public String getImgUri(GraphicImage imgComponent) throws Exception {
assert null != imgComponent;
String imgUri = new GraphicImageRendererXtension().getPublicImageSrc(FacesContext.getCurrentInstance(),
imgComponent);
return imgUri;
}
}
Then use this method by:
<p:graphicImage binding="#{myImage}" value="#{myBean.img}" />
<h:outputText id="imageData" pt:data-image="#{myBean.getImgUri(myImage)}" />
This way there's no need to create a bean or method for each image.

Primefaces Push causes IllegalStateException

Currently im working on primefaces push function. actually, the push function is working properly.
This is my push flow:
I have two application with share same database, admin dashboard(primefaces + spring) and webapi (spring mvc). when there are data inserted to database via webapi, then web api will call the admin url that will trigger to push notification for all logged in user. and its working fine, as expected.
my problems is, when there are push notification, and then user do logout at the same time (at least notification growl not gone) it will throw java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed and sometime Cannot create a session after the response has been committed.
i have try to change Login Controller to ViewScope, and put this context-param to web xml, but still not working.
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
Please Help,
this is the full stack trace:
SEVERE: Servlet.service() for servlet [facesServlet] in context with path [/WebAdmin] threw exception [java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed] with root cause
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:482)
at com.sun.faces.context.ExternalContextImpl.redirect(ExternalContextImpl.java:678)
at org.omnifaces.util.FacesLocal.redirect(FacesLocal.java:882)
at org.omnifaces.util.Faces.redirect(Faces.java:1170)
at com.sepakbole.web.controller.LoginController.doLogout(LoginController.java:84)
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.apache.el.parser.AstValue.invoke(AstValue.java:279)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:273)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
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:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.sepakbole.web.filter.AuthorizationFilter.doFilter(AuthorizationFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1082)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:623)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Update:
This is my Controller:
import java.io.Serializable;
import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import org.primefaces.push.EventBus;
import org.primefaces.push.EventBusFactory;
#ManagedBean
#ApplicationScoped
public class PushMessageController implements Serializable {
private static final long serialVersionUID = 1L;
private String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public void execute(){
EventBus eventBus = EventBusFactory.getDefault().eventBus();
eventBus.publish("/receive-message", data);
}
}
And Below is the PushEndPoint:
import org.primefaces.push.annotation.OnMessage;
import org.primefaces.push.annotation.PushEndpoint;
import org.primefaces.push.annotation.Singleton;
import org.primefaces.push.impl.JSONEncoder;
#PushEndpoint("/receive-message")
#Singleton
public class MessageResource {
#OnMessage(encoders = {JSONEncoder.class})
public String onMessage(String data) {
return data;
}
}
and this this is placed on my template:
<p:socket channel="/receive-message" onMessage="handleMessage"></p:socket>
<p:growl widgetVar="growl-msg" globalOnly="true" id="growl-msg" life="2000" />
<script type="text/javascript">
function handleMessage(facesmessage) {
PF('growl-msg').renderMessage({"summary":"New Message",
"detail":facesmessage,
"severity":"info"})
}
</script>
to trigger the notification, i call this url. Where the data parameter is dynamic message that will showed into growl.
http://localhost:5050/WebAdmin/primepushpage/receive-message.jsf?data=Testing123
and this is my receive-message.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="../pages/template.xhtml">
<ui:define name="content">
<f:metadata>
<f:viewParam name="data" value="#{pushMessageController.data}" />
</f:metadata>
<h:form>
<p:remoteCommand name="remoteCommand" actionListener="#{pushMessageController.execute}" autoRun="true" />
</h:form>
</ui:define>
</ui:composition>
and this is doFilter method on my Authorization Filter:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURL = request.getContextPath() + "/pages/index.jsf";
boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));
boolean pushRequest = request.getRequestURI().contains("primepush");
if (loggedIn || loginRequest || resourceRequest || pushRequest) {
if (!resourceRequest) { // Prevent browser from caching restricted resources. See also http://stackoverflow.com/q/4194207/157882
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response); // So, just continue request.
}
else if (ajaxRequest) {
response.setContentType("text/xml");
response.setCharacterEncoding("UTF-8");
response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
}
else {
if(!response.isCommitted()){
response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
return;
}
}
}
and i have add push servlet mapping on my web.xml, also my pom.xml already have atmosphere-runtime dependency. and i use Tomcat 7 for the container.
I had a same issue. After page was refresh via ajax and user manualy refreshed page I got from ocpsoft rewrite following warning:
Response has already been committed, and further write operations are not permitted. This may result in an IllegalStateException being triggered by the underlying application.
And after that the page was in invalid state and second refresh was needed. I have spent many hours trying to solve this issue and as last thing I tried to use different versions of atmosphere runtime (at first I have used the latest 2.4.9) and found out that it works correctly with versions 2.4.0 until 2.4.2.
Primefaces manual says that you can use version 2.3.RC6 and newest, but with versions below 2.4.0 I got nasty exceptions during application startup.
I use Primefaces 6.0 and application is deployed on Tomcat 8.0.39

Primefaces fileupload component does not work [duplicate]

Important : The issue which is discussed in this thread has been fixed as of PrimeFaces 5.1 final (community release) released on Monday, October 6, 2014 (just a few minutes ago from now). I attempted on JSF 2.2.8-02 (or api, impl).
As such, if you happened to use that version (or higher, no need to mention), you would not even need to read this question anymore.
I have a web application running on
GlassFish 4.0
Mojarra 2.2.4
PrimeFaces 4.0 final
Everything except file upload with AJAX works well. The following xhtml file sends multipart contents via an AJAX request triggered by a PrimeFaces command button.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:form prependId="true" enctype="multipart/form-data">
<p:fileUpload id="txtCatImage"
value="#{testManagedBean.uploadedFile}"
mode="advanced"
dragDropSupport="true"
fileLimit="1"
sizeLimit="100000"
multiple="false"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
fileUploadListener="#{testManagedBean.fileUploadListener}"/>
<p:message for="txtCatImage" showSummary="false"/>
<p:commandButton id="btnSubmit"
actionListener="#{testManagedBean.insert}"
ajax="true" icon="ui-icon-check" value="Save"/>
</h:form>
</h:body>
</html>
The test managed bean:
#ManagedBean
#ViewScoped
public final class TestManagedBean implements Serializable {
private static final long serialVersionUID = 1L;
private UploadedFile uploadedFile;
public TestManagedBean(){}
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void fileUploadListener(FileUploadEvent event){
uploadedFile=event.getFile();
}
public void insert(){
if(uploadedFile!=null){
System.out.println(uploadedFile.getFileName());
}
else{
System.out.println("The file object is null.");
}
}
}
When a file is uploaded from a file browser, it shows the file name in its listener - fileUploadListener().
After uploading a file, when the given command button is pressed (ajax="true"), it causes the following exception to be thrown.
WARNING: javax.servlet.ServletException: The request content-type is not a multipart/form-data
javax.faces.FacesException: javax.servlet.ServletException: The request content-type is not a multipart/form-data
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:44)
at org.primefaces.component.fileupload.FileUploadRenderer.decode(FileUploadRenderer.java:44)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:831)
at javax.faces.component.UIInput.decode(UIInput.java:771)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1225)
at javax.faces.component.UIInput.processDecodes(UIInput.java:676)
at javax.faces.component.UIForm.processDecodes(UIForm.java:225)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929)
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
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.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:70)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at filter.NoCacheFilter.doFilter(NoCacheFilter.java:28)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.servlet.ServletException: The request content-type is not a multipart/form-data
at org.apache.catalina.fileupload.Multipart.getPart(Multipart.java:187)
at org.apache.catalina.connector.Request.getPart(Request.java:4535)
at org.apache.catalina.connector.RequestFacade.getPart(RequestFacade.java:1095)
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decodeAdvanced(NativeFileUploadDecoder.java:60)
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:37)
... 48 more
SEVERE: javax.servlet.ServletException: The request content-type is not a multipart/form-data
at org.apache.catalina.fileupload.Multipart.getPart(Multipart.java:187)
at org.apache.catalina.connector.Request.getPart(Request.java:4535)
at org.apache.catalina.connector.RequestFacade.getPart(RequestFacade.java:1095)
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decodeAdvanced(NativeFileUploadDecoder.java:60)
at org.primefaces.component.fileupload.NativeFileUploadDecoder.decode(NativeFileUploadDecoder.java:37)
at org.primefaces.component.fileupload.FileUploadRenderer.decode(FileUploadRenderer.java:44)
at javax.faces.component.UIComponentBase.decode(UIComponentBase.java:831)
at javax.faces.component.UIInput.decode(UIInput.java:771)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1225)
at javax.faces.component.UIInput.processDecodes(UIInput.java:676)
at javax.faces.component.UIForm.processDecodes(UIForm.java:225)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
at javax.faces.component.UIComponentBase.processDecodes(UIComponentBase.java:1220)
at javax.faces.component.UIViewRoot.processDecodes(UIViewRoot.java:929)
at com.sun.faces.lifecycle.ApplyRequestValuesPhase.execute(ApplyRequestValuesPhase.java:78)
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.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:70)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at filter.NoCacheFilter.doFilter(NoCacheFilter.java:28)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:357)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:260)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:188)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:722)
It can only work, when the ajax attribute of the command button is set to false - ajax="false".
I have downgraded the Mojarra version to 2.1.9 in Tomcat 7.0.35. It worked with this Mojarra version along with PrimeFaces 4.0 final (and PrimeFaces 4.0 RC1 too) - files uploaded with an AJAX request.
I have alternatively tried on the following Mojarra versions
2.2.0
2.2.1
2.2.2
2.2.3
2.2.4
in GlassFish 4.0 but none of them succeeded to upload files with an AJAX request which is highly required because editing of rows using <p:rowEditor/> (along with images in each row, for example) in PrimeFaces DataTable is always AJAX based.
I want to keep GlassFish 4.0 anyhow. I have also tried to downgrade Mojarra 2.1.9 in GlassFish 4.0 but it failed to create bundles ending with an exception. GlassFish 4.0 doesn't seem to work with Mojarra lower than 2.2.x.
So, what is responsible for causing this exception - PrimeFaces or JSF? Just confused. Is there any workaround to upload files with AJAX requests in this given environment?
EDIT:
Filter mapping in web.xml:
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
The problem remains stationary along with the Mojarra version 2.2.5 (or api, impl) released on January 08, 2014.
Once again tried on the Mojarra version 2.2.6 (or api, impl) released on March 04, 2014. The problem remains intact.
Still does not work on PrimeFaces 5.0 final released on May 05, 2014.
As Kai rightfully pointed out in his answer on the current question, the problem is caused by the NativeFileUploadDecoder as used by FileUploadRenderer not checking whether the request is a multipart/form-data request or not. This will cause trouble when the component is present in a form on which a "regular" ajax request is being submitted. The CommonsFileUploadDecoder checks that correctly and that's why it works correctly in JSF 2.1 which didn't have a native file upload parser yet.
His solution of workarounding this with a custom renderer is in the right direction, however the approach is quite clumsy. There's in this particular case absolutely no need of copypasting the whole class consisting more than 200 lines just to add a few more lines. Instead, just extend exactly that class and override exactly the method with an if check before delegating to the super as follows:
package com.example;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import org.primefaces.component.fileupload.FileUploadRenderer;
public class MyFileUploadRenderer extends FileUploadRenderer {
#Override
public void decode(FacesContext context, UIComponent component) {
if (context.getExternalContext().getRequestContentType().toLowerCase().startsWith("multipart/")) {
super.decode(context, component);
}
}
}
That's it (keep that <renderer-kit> entry in faces-config.xml though). There's no point of continuing the decode if the request isn't a multipart request. The file parts wouldn't be available anyway (and there's also no point of casting back to javax.servlet.* API when the same functionality is readily available via ExternalContext).
I had the same issue. It seems to be more related to the <p:commandButton> than the <p:fileUpload> component, since it works with an <h:commandButton> (even with ajax).
You could try:
<h:commandButton id="btnSubmit" actionListener="#{testManagedBean.insert}" value="Save">
<f:ajax execute="#all" render="#form"/>
</h:commandButton>
I cannot tell you why or how it works, but it fixed the issue for me.
The downside of course is, that you have to do the styling by yourself, at least until
the Primefaces guys fix this issue.
EDIT:
After digging in the sources and doing some debugging if figured out that there are actually two requests made (I tried in <p:wizard/>). The first one is the multipart/form-data one which actually does the file upload. It fires the fileUploadEvent in the Bean. I the wizards next button is pressed another form with enctype application/www-urlencoded is submitted. This causes the exception. Conclusion is, that unlike what I wrote in the comment suppressing the exception is a valid solution. This can even be done in a way that does not include changing the Primefaces.jar which is handy if the guys fix the issue in a future version.
So here is what needs to be done:
Create a new class com.yourpackage.fileupload.FileUploadRenderer
Copy and paste the following code inside your new class:
package com.yourpackage.fileupload.fileupload;
import java.io.IOException;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.servlet.http.HttpServletRequest;
import org.primefaces.component.fileupload.CommonsFileUploadDecoder;
import org.primefaces.component.fileupload.FileUpload;
import org.primefaces.component.fileupload.NativeFileUploadDecoder;
import org.primefaces.config.ConfigContainer;
import org.primefaces.context.RequestContext;
import org.primefaces.expression.SearchExpressionFacade;
import org.primefaces.renderkit.CoreRenderer;
import org.primefaces.util.HTML;
import org.primefaces.util.WidgetBuilder;
public class FileUploadRenderer extends CoreRenderer {
#Override
public void decode(FacesContext context, UIComponent component) {
FileUpload fileUpload = (FileUpload) component;
if (!fileUpload.isDisabled()) {
ConfigContainer cc = RequestContext.getCurrentInstance().getApplicationContext().getConfig();
String uploader = cc.getUploader();
boolean isAtLeastJSF22 = cc.isAtLeastJSF22();
if (uploader.equals("auto")) {
if (isAtLeastJSF22) {
if (isMultiPartRequest(context)) {
NativeFileUploadDecoder.decode(context, fileUpload);
}
} else {
CommonsFileUploadDecoder.decode(context, fileUpload);
}
} else if (uploader.equals("native")) {
if (!isAtLeastJSF22) {
throw new FacesException("native uploader requires at least a JSF 2.2 runtime");
}
NativeFileUploadDecoder.decode(context, fileUpload);
} else if (uploader.equals("commons")) {
CommonsFileUploadDecoder.decode(context, fileUpload);
}
}
}
#Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
FileUpload fileUpload = (FileUpload) component;
encodeMarkup(context, fileUpload);
if (fileUpload.getMode().equals("advanced")) {
encodeScript(context, fileUpload);
}
}
protected void encodeScript(FacesContext context, FileUpload fileUpload) throws IOException {
String clientId = fileUpload.getClientId(context);
String update = fileUpload.getUpdate();
String process = fileUpload.getProcess();
WidgetBuilder wb = getWidgetBuilder(context);
wb.initWithDomReady("FileUpload", fileUpload.resolveWidgetVar(), clientId, "fileupload");
wb.attr("auto", fileUpload.isAuto(), false)
.attr("dnd", fileUpload.isDragDropSupport(), true)
.attr("update", SearchExpressionFacade.resolveComponentsForClient(context, fileUpload, update), null)
.attr("process", SearchExpressionFacade.resolveComponentsForClient(context, fileUpload, process), null)
.attr("maxFileSize", fileUpload.getSizeLimit(), Long.MAX_VALUE)
.attr("fileLimit", fileUpload.getFileLimit(), Integer.MAX_VALUE)
.attr("invalidFileMessage", fileUpload.getInvalidFileMessage(), null)
.attr("invalidSizeMessage", fileUpload.getInvalidSizeMessage(), null)
.attr("fileLimitMessage", fileUpload.getFileLimitMessage(), null)
.attr("messageTemplate", fileUpload.getMessageTemplate(), null)
.attr("previewWidth", fileUpload.getPreviewWidth(), 80)
.attr("disabled", fileUpload.isDisabled(), false)
.callback("onstart", "function()", fileUpload.getOnstart())
.callback("onerror", "function()", fileUpload.getOnerror())
.callback("oncomplete", "function()", fileUpload.getOncomplete());
if (fileUpload.getAllowTypes() != null) {
wb.append(",allowTypes:").append(fileUpload.getAllowTypes());
}
wb.finish();
}
protected void encodeMarkup(FacesContext context, FileUpload fileUpload) throws IOException {
if (fileUpload.getMode().equals("simple")) {
encodeSimpleMarkup(context, fileUpload);
} else {
encodeAdvancedMarkup(context, fileUpload);
}
}
protected void encodeAdvancedMarkup(FacesContext context, FileUpload fileUpload) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = fileUpload.getClientId(context);
String style = fileUpload.getStyle();
String styleClass = fileUpload.getStyleClass();
styleClass = styleClass == null ? FileUpload.CONTAINER_CLASS : FileUpload.CONTAINER_CLASS + " " + styleClass;
boolean disabled = fileUpload.isDisabled();
writer.startElement("div", fileUpload);
writer.writeAttribute("id", clientId, "id");
writer.writeAttribute("class", styleClass, styleClass);
if (style != null) {
writer.writeAttribute("style", style, "style");
}
//buttonbar
writer.startElement("div", fileUpload);
writer.writeAttribute("class", FileUpload.BUTTON_BAR_CLASS, null);
//choose button
encodeChooseButton(context, fileUpload, disabled);
if (!fileUpload.isAuto()) {
encodeButton(context, fileUpload.getUploadLabel(), FileUpload.UPLOAD_BUTTON_CLASS, "ui-icon-arrowreturnthick-1-n");
encodeButton(context, fileUpload.getCancelLabel(), FileUpload.CANCEL_BUTTON_CLASS, "ui-icon-cancel");
}
writer.endElement("div");
//content
writer.startElement("div", null);
writer.writeAttribute("class", FileUpload.CONTENT_CLASS, null);
writer.startElement("table", null);
writer.writeAttribute("class", FileUpload.FILES_CLASS, null);
writer.startElement("tbody", null);
writer.endElement("tbody");
writer.endElement("table");
writer.endElement("div");
writer.endElement("div");
}
protected void encodeSimpleMarkup(FacesContext context, FileUpload fileUpload) throws IOException {
encodeInputField(context, fileUpload, fileUpload.getClientId(context));
}
protected void encodeChooseButton(FacesContext context, FileUpload fileUpload, boolean disabled) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = fileUpload.getClientId(context);
String cssClass = HTML.BUTTON_TEXT_ICON_LEFT_BUTTON_CLASS + " " + FileUpload.CHOOSE_BUTTON_CLASS;
if (disabled) {
cssClass += " ui-state-disabled";
}
writer.startElement("span", null);
writer.writeAttribute("class", cssClass, null);
//button icon
writer.startElement("span", null);
writer.writeAttribute("class", HTML.BUTTON_LEFT_ICON_CLASS + " ui-icon-plusthick", null);
writer.endElement("span");
//text
writer.startElement("span", null);
writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);
writer.writeText(fileUpload.getLabel(), "value");
writer.endElement("span");
if (!disabled) {
encodeInputField(context, fileUpload, clientId + "_input");
}
writer.endElement("span");
}
protected void encodeInputField(FacesContext context, FileUpload fileUpload, String clientId) throws IOException {
ResponseWriter writer = context.getResponseWriter();
writer.startElement("input", null);
writer.writeAttribute("type", "file", null);
writer.writeAttribute("id", clientId, null);
writer.writeAttribute("name", clientId, null);
if (fileUpload.isMultiple()) {
writer.writeAttribute("multiple", "multiple", null);
}
if (fileUpload.getStyle() != null) {
writer.writeAttribute("style", fileUpload.getStyle(), "style");
}
if (fileUpload.getStyleClass() != null) {
writer.writeAttribute("class", fileUpload.getStyleClass(), "styleClass");
}
if (fileUpload.isDisabled()) {
writer.writeAttribute("disabled", "disabled", "disabled");
}
writer.endElement("input");
}
protected void encodeButton(FacesContext context, String label, String styleClass, String icon) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String cssClass = HTML.BUTTON_TEXT_ICON_LEFT_BUTTON_CLASS + " ui-state-disabled " + styleClass;
writer.startElement("button", null);
writer.writeAttribute("type", "button", null);
writer.writeAttribute("class", cssClass, null);
writer.writeAttribute("disabled", "disabled", null);
//button icon
String iconClass = HTML.BUTTON_LEFT_ICON_CLASS;
writer.startElement("span", null);
writer.writeAttribute("class", iconClass + " " + icon, null);
writer.endElement("span");
//text
writer.startElement("span", null);
writer.writeAttribute("class", HTML.BUTTON_TEXT_CLASS, null);
writer.writeText(label, "value");
writer.endElement("span");
writer.endElement("button");
}
private boolean isMultiPartRequest(FacesContext context) {
if (context == null) {
return false;
}
return ((HttpServletRequest) context.getExternalContext().getRequest()).getContentType().startsWith("multipart");
}
}
Add the following lines at the bottom of your faces-config.xml:
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.FileUploadRenderer</renderer-type>
<renderer-class>com.yourpackage.fileupload.FileUploadRenderer</renderer-class>
</renderer>
</render-kit>
You're ready to go!
What have we done? We created our own FileUploadRenderer which checks if the contentType is really multipart/form-data using the method isMultiPartRequest(). Only if this returns true the rest of the code is executed. In any other case nothing will happen which means that no exception will be thrown. If Primefaces fixes this issue you just need to remove the lines from your faces-config.xml to use their class.
Let me know if that works for you!
EDIT
This code checks wether or not the given request is of type multipart/form-data. If it is not the execution is stopped. The original Primefaces code would continue anyway. As I mentioned above if you upload a file inside a Primefaces component there are actually two requests made:
The Ajax-FileUpload using the <p:fileUpload/> (enctype: multipart/form-data)
The Ajax action in the <p:editRow/> or <p:wizard/> (enctype: application/www-form-urlencoded)
The first one is handled by the renderer while the second one causes the exception in the original code since the renderer tries to handle something which it is not capable of. With the changes made in the code only multipart/form-data forms are handled by the renderer so no exceptions occur. IMO it is clearly a bug in the sources of Primefaces. The code differences is just the method private boolean isMultiPartRequest(FacesContext context) and its one occurrence in the code. Glad I could help you!
Although this is old and already answered, i wanted to share something, just in case you missed it:
PrimeFaces 4+ now has a context paramter, which you can use (in web.xml) to manually choose which uploader should be used (native-servlet3 or commons). You can use this to force commons-uploader like this:
<context-param>
<param-name>primefaces.UPLOADER</param-name>
<param-value>commons</param-value>
</context-param>
(Of course you still need FileUploadFilter as described above and in the guide).
See PrimeFaces User's Guide for more information.
#BalusC - Your suggestion for extending the existing FileUploadRenderer is very clean. Thanks!
Depending on the version of JSF you'r using you may see a random iFrame pop up. This is a bug noted here: JAVASERVERFACES-2843
In my first attempt to fix this (without having to upgrade to 2.2.1) I just hid the iFrame with CSS.
#JSFFrameId {
visibility:hidden;
}
This worked but for some reason additional AJAX submits would not fire. I then called a little script to remove the iFrame and that fixed the problem.
<h:commandButton id="btnSubmit" action="#{fileUploadController.upload}" value="Save" >
<f:ajax execute="#all" render="frmMain" onevent="removeIFrame()" />
</h:commandButton>
JavaScript:
function removeIFrame()
{
document.getElementById("JSFFrameId").removeNode();
}
I had the same issue,
In my case i have used primefaces file uploader in a data table, tried to modify the existing image using onRowEdit, which was end up with the same error mentioned above.
Then i changed the primefaces jar to 5.1 version. Now its working fine.
The custom class work for me:
#Override
public void decode(FacesContext context, UIComponent component) {
if (!context.getExternalContext().getRequestContentType().toLowerCase().startsWith("multipart/")) {
return;
}
FileUpload fileUpload = (FileUpload) component;
if (!fileUpload.isDisabled()) {
PrimeConfiguration cc = RequestContext.getCurrentInstance().getApplicationContext().getConfig();
String uploader = cc.getUploader();
boolean isAtLeastJSF22 = cc.isAtLeastJSF22();
String inputToDecodeId = getSimpleInputDecodeId(fileUpload, context);
if (uploader.equals("auto")) {
if (isAtLeastJSF22)
NativeFileUploadDecoder.decode(context, fileUpload, inputToDecodeId);
else
CommonsFileUploadDecoder.decode(context, fileUpload, inputToDecodeId);
}
else if (uploader.equals("native")) {
NativeFileUploadDecoder.decode(context, fileUpload, inputToDecodeId);
}
else if (uploader.equals("commons")) {
CommonsFileUploadDecoder.decode(context, fileUpload, inputToDecodeId);
}
}
}

Dynamically generate ice:commandButton components

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.

Resources