I have an application with a risk matrix. The headings are 5 severities (from the severitiesBean
in my example) and 5 likelihoods (from the likelihoodsBean
in my example). (The headings go by different names in literature, such as exposure or probability or consequences.) In each cell there is a risk rating (enumerated from the riskRatingsBean
). To give you an idea of what this looks like visually, there is an example here.
I am able to display the matrix just fine, which seems all people asking related questions on SO cared about. However, I want to display and allow the administrator of the system to edit the risk for each cell in the grid. A selectOneMenu
dropdown in either h: or p: (PrimeFaces) seems like a good way of allowing the selection.
Here's the JSF:
<h:panelGroup id="editArea">
<table border="1" style="border-collapse:collapse;" class="riskMatrix">
<tr>
<td rowspan="2" colspan="2"></td>
<th colspan="5">Severity</th>
</tr>
<tr>
<!-- Severities going across the top -->
<ui:repeat var="severity" value="#{severitiesBean.severities}">
<th style="text-align: center;">
<h:outputText value="#{severity.name}"/>
</th>
</ui:repeat>
</tr>
<ui:repeat id="likelihoodLoop" var="likelihood" value="#{likelihoodsBean.likelihoods}" varStatus="lkhdvar">
<tr>
<ui:fragment rendered="#{lkhdvar.index == 0}">
<th rowspan="5">Likelihood</th>
</ui:fragment>
<!-- Likelihoods going down the side -->
<th>
<h:outputText value="#{likelihood.name}"/>
</th>
<!-- The rating for each cell going across -->
<ui:repeat id="severitiesLoop" var="severity" value="#{severitiesBean.severities}">
<td class="#{riskRatingsBean.riskRatings.get(riskMatrixBean.riskMatrix[severity.id-1][likelihood.id-1]-1).cssClass}" style="text-align: center;">
<p:selectOneMenu
id="RiskRatingDropDown" effect="none"
value="#{riskMatrixBean.riskMatrix[severity.id-1][likelihood.id-1]}">
<f:selectItems value="#{riskRatingsBean.riskRatings}" var="rating" itemLabel="#{rating.name}" itemValue="#{rating.id}"/>
</p:selectOneMenu>
</td>
</ui:repeat>
</tr>
</ui:repeat>
</table>
</h:panelGroup>
<h:messages id="riskMatrixErrorMessages"/>
<p:commandButton id="SaveButton" value="Update" actionListener="#{riskMatrixBean.saveRiskMatrix}"
update="editArea"/>
In the riskMatrixBean
, the matrix is defined like this:
public int[][] getRiskMatrix()
{
return riskMatrix;
}
This all displays perfectly. However, I want to be able to update the values. When I click on the submit button, I get an exception:
javax.faces.component.UpdateModelException: java.lang.ClassCastException: Unable to add an object of type [java.lang.Integer] to an array of objects of type [int]
at javax.faces.component.UIInput.updateModel(UIInput.java:866)
at javax.faces.component.UIInput.processUpdates(UIInput.java:749)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:633)
at com.sun.faces.facelets.component.UIRepeat.processUpdates(UIRepeat.java:880)
at com.sun.faces.facelets.component.UIRepeat.process(UIRepeat.java:633)
at com.sun.faces.facelets.component.UIRepeat.processUpdates(UIRepeat.java:880)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1291)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1291)
at javax.faces.component.UIForm.processUpdates(UIForm.java:281)
at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1291)
at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1254)
at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.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:650)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:357)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:931)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCastException: Unable to add an object of type [java.lang.Integer] to an array of objects of type [int]
at javax.el.ArrayELResolver.setValue(ArrayELResolver.java:96)
at com.sun.faces.el.DemuxCompositeELResolver._setValue(DemuxCompositeELResolver.java:255)
at com.sun.faces.el.DemuxCompositeELResolver.setValue(DemuxCompositeELResolver.java:281)
at org.apache.el.parser.AstValue.setValue(AstValue.java:218)
at org.apache.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:253)
at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:131)
at javax.faces.component.UIInput.updateModel(UIInput.java:832)
... 33 more
I'm at a loss as to what I'm doing wrong. Obviously the updateModel
during the updateModelValuesPhase
doesn't know how to deal with the int[][]
and how I've specified the selectOneMenu
value
attribute. I suspect there is something wrong with the approach, but I'm not sure what. Maybe it's something to do with the nested ui:repeat
s? I tried to change to using Integer[][]
and to List<List<Integer>>
, and still no luck, although I probably did something else wrong along the way. I'm open to changing my data type as necessary.
Thanks in advance!
>` will fail for reasons explained here: http://stackoverflow.com/q/19872633
– BalusC Jan 06 '16 at 08:00