Hi Brian,
I use JBoss AS 7.1.1 and the JBoss JSF Implementation 2.0.9.
Honestly, I don't think it is because of different containers we are using. It is more a bug I produced myself..
Well, I have a suspicion..:
I posted only the relevant parts of my source code (what I thought are the relevant parts) , because I didn't want to confuse everybody with to much source code ;-). Now, I'd like to share the whole source code with you because there must be somewehere else a bug I cannot find. I guess something else causes the effect I am now asking for an idea. Actually, I guess some ui components gets rendered which should not be rendered.
The following xhtml page shows a calendar component and a data table initially. Whenever the user selects a date, a JPA query gets executed with the date as filter criteria. The datatable gets updated and rendered again. So far so good. This works as expected.
Now, I observed that the datatable gets rendered again when the user clicks on the command link to edit the selected row. And this should not be the case. Because this event loads the data again, but not for the selected date. It loads the data for the current date which is wrong! This jpa query, returns no result! So, I guess the empty data gets propagated via setpropertyActionListener and that is the reason for displaying no data in the popup panel. However, I can't explain why the log message of participationController.setEditedParticipation() will not be logged.
Any ideas on that ?
Here is the whole source code:
xhtml:
<?xml version="1.0" encoding="UTF-8"?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
template="/WEB-INF/templates/default.xhtml"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<ui:define name="content">
<h2>Calendar:</h2>
<h:outputStylesheet>
.tdc {
background-color: green;
}
.wdc {
font-weight: bold;
font-style: italic;
}
.even-row {
background-color: #FCFFFE;
}
.odd-row {
background-color: #ECF3FE;
}
.active-row {
background-color: #FFEBDA !important;
cursor: pointer;
}
</h:outputStylesheet>
<h:form id="calendar_form">
<rich:calendar id="trainingCalendar"
mode="ajax"
popup="false"
boundaryDatesMode="scroll"
locale="de/DE"
buttonLabel="Heute"
datePattern="dd.MM.yyyy"
dataModel="#{calendarModel}"
value="#{participationListProducer.trainingDate}"
valueChangeListener="#{participationListProducer.trainingDateChanged}">
<a4j:ajax event="change" render="trainingDate_output participation_table participationAttributes_output" />
</rich:calendar>
</h:form>
<h:outputText id="trainingDate_output" value="Training on #{participationListProducer.trainingDateAsFormattedString}:" />
<h:form id="table_form">
<rich:dataTable var="_participation" value="#{participationListProducer.participations}"
iterationStatusVar="it"
id="participation_table"
rowClasses="odd-row, even-row"
styleClass="stable">
<rich:column>
<f:facet name="header">Player</f:facet>
#{_participation.player.name}, #{_participation.player.firstname}
</rich:column>
<rich:column>
<f:facet name="header">Participates</f:facet>
<h:selectBooleanCheckbox value="#{_participation.participating}" readonly="true"/>
</rich:column>
<rich:column>
<f:facet name="header">Drives Forth</f:facet>
<h:selectBooleanCheckbox value="#{_participation.drivingForth}" readonly="true"/>
</rich:column>
<rich:column>
<f:facet name="header">Drives Back</f:facet>
<h:selectBooleanCheckbox value="#{_participation.drivingBack}" readonly="true"/>
</rich:column>
<rich:column>
<a4j:commandLink styleClass="no-decor" render="editGrid" execute="@this"
onclick="#{rich:component('editPane')}.show()">
<h:graphicImage value="/resources/icons/edit.gif" alt="edit" />
<a4j:param value="#{it.index}" assignTo="#{participationController.currentParticipationIndex}" />
<f:setPropertyActionListener target="#{participationController.editedParticipation}" value="#{_participation}" />
</a4j:commandLink>
</rich:column>
</rich:dataTable>
<rich:popupPanel header="Edit Participation" id="editPane" domElementAttachment="parent" width="400" height="170">
<h:panelGrid columns="3" id="editGrid">
<h:outputText value="Id" />
<h:outputText value="#{participationController.currentParticipationIndex}" />
<h:panelGroup />
<h:outputText value="Teilnahme" />
<h:outputText value="#{participationController.editedParticipation.participating}" />
<h:panelGroup />
<h:outputText value="Spieler" />
<h:outputText value="#{participationController.editedParticipation.player.firstname}" />
</h:panelGrid>
<a4j:commandButton value="Store" action="#{participationController.updateParticipation()}" render="participation_table" execute="editPane"
oncomplete="if (#{facesContext.maximumSeverity==null}) {#{rich:component('editPane')}.hide();}" />
<a4j:commandButton value="Cancel" onclick="#{rich:component('editPane')}.hide();
return false;" />
</rich:popupPanel>
</h:form>
<rich:jQuery selector=".stable tr:odd" query="addClass('odd-row')" />
<rich:jQuery selector=".stable tr:even" query="addClass('even-row')" />
<rich:jQuery selector=".stable tr" event="mouseover" query="jQuery(this).addClass('active-row')" />
<rich:jQuery selector=".stable tr" event="mouseout" query="jQuery(this).removeClass('active-row')" />
<h:panelGrid id="participationAttributes_output" >
<h:outputText value="#{participationListProducer.numberOfSeatsForthRequired} Seats required Forth!"
rendered="#{participationListProducer.numberOfSeatsForthRequired > 0}"/>
<h:outputText value="#{participationListProducer.numberOfSeatsBackRequired} Seats required back!"
rendered="#{participationListProducer.numberOfSeatsBackRequired > 0}"/>
<h:outputText value="#{participationListProducer.numberOfParticipators} Participations of training"/>
</h:panelGrid>
</ui:define>
</ui:composition>
Bean Code:
@RequestScoped
@Named
public class ParticipationListProducer {
@Inject
private ParticipationRepository participationRepository;
@Inject
private Logger log;
private List<Participation> participations;
private Date trainingDate = new Date();
private int numberOfParticipators;
private int numberOfDriversBack;
private int numberOfDriversForth;
private int numberOfSeatsForthAvailable;
private int numberOfSeatsBackAvailable;
private int numberOfSeatsBackRequired;
private int numberOfSeatsForthRequired;
public int getNumberOfParticipators() {
return numberOfParticipators;
}
public int getNumberOfDriversBack() {
return numberOfDriversBack;
}
public int getNumberOfDriversForth() {
return numberOfDriversForth;
}
public int getNumberOfSeatsBackRequired() {
log.info("return numberOfSeatsBackRequired" + numberOfSeatsBackRequired);
return numberOfSeatsBackRequired;
}
public int getNumberOfSeatsForthRequired() {
log.info("return numberOfSeatsForthRequired=" + numberOfSeatsForthRequired);
return numberOfSeatsForthRequired;
}
public int getNumberOfSeatsBackAvailable() {
return numberOfSeatsBackRequired;
}
public int getNumberOfSeatsForthAvailable() {
return numberOfSeatsForthRequired;
}
public List<Participation> getParticipations() {
log.info("GetParticipations called " + participations.size() + " Elements");
return participations;
}
public void setTrainingDate(Date x) {
log.info("setTrainingDate called " + x.toString());
trainingDate = x;
}
public void trainingDateChanged(ValueChangeEvent event) {
log.info("trainingDateChanged called !");
if (event.getNewValue() != null) {
log.info("New TrainingDate = " + event.getNewValue());
trainingDate = (Date) event.getNewValue();
retrieveAllParticipators();
calculateParticipationAttributes();
}
}
public Date getTrainingDate() {
return trainingDate;
}
public String getTrainingDateAsFormattedString() {
return DateUtil.getSelectedDateAsFormattedString(trainingDate);
}
@PostConstruct
public void retrieveAllParticipators() {
log.info("retrieveAllParticipators for " + trainingDate.toString());
participations = participationRepository.getAllForSpecificDateOrderedByName(trainingDate);
calculateParticipationAttributes();
}
private void calculateParticipationAttributes() {
numberOfParticipators = 0;
for (Participation p : participations) {
log.info(" Just read -> " + p.getId() + "; " + p.getTrainingItem().getCurrentDate());
if (p.isParticipating()) {
numberOfParticipators++;
}
if (p.isDrivingBack()) {
numberOfSeatsBackAvailable = numberOfDriversBack + p.getPlayer().getCarsize();
}
if (p.isDrivingForth()) {
numberOfSeatsForthAvailable = numberOfDriversForth + p.getPlayer().getCarsize();
}
}
numberOfSeatsBackRequired = numberOfParticipators - numberOfSeatsBackAvailable;
numberOfSeatsForthRequired = numberOfParticipators - numberOfSeatsForthAvailable;
log.info("Calculated NumberOfSeatsBackRequired = " + numberOfSeatsBackRequired);
log.info("Calculated NumberOfSeatsForthRequired = " + numberOfSeatsForthRequired);
log.info("Calculated NumberOfParticipators = " + numberOfParticipators);
}
}