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: