The following apparently straightforward code caused me quite a bit of grief:
First, the usual 'service' class:
@DataModel private List<Thing> things; @DataModelSelection("things") private Thing selectedThing; public List<Thing> getThings() { ThingRepository repository = new ThingRepository(); things = repository.getThings(); return things; } public String selectThing() { log.info("Selected: " + selectedThing); return null; } public String selectThing(Thing thing) { selectedThing = thing; log.info("Selected: " + selectedThing); }
Followed by an (unsuccessful) attempt to access this by various means within a JSF page. I tried accessing it via s:link and via h:commandButton with and without a parameter but only one approach returned 'correct' results.
<h:form> <h:dataTable value="#{accountService.things}" var="thing"> <h:column> <f:facet name="header">Name</f:facet> <h:outputText id="name" size="10" required="true" value="#{thing.name}"></h:outputText> </h:column> <h:column> <f:facet name="header">Size</f:facet> <h:outputText id="size" size="10" required="true" value="#{thing.size}"></h:outputText> </h:column> <h:column> <s:link value="Select" action="#{accountService.selectThing(thing)}" ></s:link> </h:column> <h:column> <h:commandButton value="Select" action="#{accountService.selectThing(thing)}" ></h:commandButton> </h:column> <h:column> <s:link value="Select (dsm)" action="#{accountService.selectThing()}" ></s:link> </h:column> <h:column> <h:commandButton value="Select (dsm)" action="#{accountService.selectThing()}" ></h:commandButton> </h:column> </h:dataTable> <h:commandButton value="Show Choices" action="#{accountService.getThings()}" ></h:commandButton> </h:form>
The repository spits out the following ordered sequence:
One_1
Two_22
Three_333
Four_4444
Five_55555
Size_666666
Selecting the second, third, fourth and fifth lines (in that order) gave the following surprising (to me at least) results:
16:54:43,322 INFO AccountService Selected: null
16:54:44,665 INFO AccountService Selected: Three_333 - this is 'correct'
16:54:45,931 INFO AccountService Selected: One_1
16:54:47,353 INFO AccountService Selected: One_1
Eventually, the errors of my ways was pointed out to me.
Section 27.10.1. of the Seam Reference Guide - Annotations for use with dataTable
states that @DataModel outjects a property of type List, Map, Set or Object{FOOTNOTE DEF } as a JSF DataModel into the scope of the owning component (or the EVENT scope if the owning component is STATELESS).
Therefore,
@DataModel private List<Thing> things;
outjects a DataModel context variable called 'things' into the same scope as the bean that it is contained within.
Herein lies the problem. Attempting to access this data model via:
<h:dataTable value="#{accountService.things}" var="thing">
refers to a list not to a DataModel.
Changing it to
<h:dataTable value="#{things}" var="thing">
makes it work fine!
Comments