Im using Primefaces 3.4.1, Glassfish 3.1.1 and Netbeans 7.2.
I have a calendarAdmin.xhtml page which contains one primefaces schedule. Upon clicking on the schedule time slot it'll pop up a dialog asking for a new event information such as duration and event name, etc.
<h:form id="forminput" prependId="false">
<p:messages autoUpdate="true"/>
<p:growl id="growl" showDetail="true" sticky="false"/>
<p:ajaxStatus>
<f:facet name="start">
<h:graphicImage value="images/loading.gif" />
</f:facet>
<f:facet name="complete">
<h:outputText value="" />
</f:facet>
</p:ajaxStatus>
<h:panelGrid columns="1" style="width: 100%;">
<p:selectOneMenu id="som_room"
value="#{calendarAdmin.selectedroomid}"
effect="fold"
validator="#{calendarAdmin.validateRoom}"
binding="#{calendarAdmin.somRoom}"
style="width:260px">
<p:ajax event="change"
update="@form"/>
<f:selectItem itemLabel="#{bundle.AllRoomsLabel}" itemValue="100"/>
<f:selectItems value="#{calendarAdmin.rooms}" />
</p:selectOneMenu>
<p:schedule value="#{calendarAdmin.lazyEventModel}"
widgetVar="myschedule"
firstHour="6">
<p:ajax event="dateSelect"
listener="#{calendarAdmin.onDateSelect}"
update="newEventDetails"
oncomplete="newEventDialog.show()" />
<p:ajax event="eventSelect"
listener="#{calendarAdmin.onEventSelect}"
update="viewEventDetails"
oncomplete="viewEventDialog.show()" />
</p:schedule>
</h:panelGrid>
<p:dialog widgetVar="newEventDialog" header="#{bundle.AddLabel} #{bundle.EventLabel} #{bundle.NewLabel}?"
showEffect="clip"
hideEffect="clip"
modal="true">
<h:panelGrid id="newEventDetails" columns="3">
<h:outputText value="#{calendarAdmin.startDate}"
style="font-style: italic; font-weight: bold;">
<f:convertDateTime type="date" pattern="EEE, dd MMM, yyyy HH:mm"/>
</h:outputText>
<h:outputText value="#{bundle.UntilLabel}" style="font-weight: bold;"/>
<h:outputText id="endtime" value="#{calendarAdmin.endDate}"
style="font-style: italic; font-weight: bold;">
<f:convertDateTime type="date" pattern="EEE, dd MMM, yyyy HH:mm"/>
</h:outputText>
<h:outputText value=""/>
<h:outputText value=""/>
<h:outputText value=""/>
<h:outputText value="#{bundle.NameLabel} #{bundle.RoomLabel}"/>
<h:outputText value=""/>
<p:selectOneMenu id="som_roomnewevent"
value="#{calendarAdmin.neweventroomid}"
effect="fold"
validator="#{calendarAdmin.validateRoom}"
binding="#{calendarAdmin.somRoomNewEvent}"
style="width:200px;">
<f:selectItems value="#{calendarAdmin.rooms}" />
</p:selectOneMenu>
<h:outputText value="#{bundle.NameLabel} #{bundle.EventLabel}"/>
<h:outputText value=""/>
<p:inputText value="#{calendarAdmin.neweventname}"
required="true"
size="22"/>
<h:outputText value="#{bundle.DurationLabel} (#{bundle.MinuteLabel})"/>
<h:outputText value=""/>
<p:selectOneMenu id="som_newduration"
value="#{calendarAdmin.neweventduration}"
binding="#{calendarAdmin.somNewDuration}"
style="width:200px;">
<p:ajax update="forminput:endtime"
event="change"
listener="#{calendarAdmin.addTime}"/>
<f:selectItem itemLabel="30 Minit" itemValue="30"/>
<f:selectItem itemLabel="1 Jam" itemValue="60"/>
<f:selectItem itemLabel="1 Jam 30 Minit" itemValue="90"/>
<f:selectItem itemLabel="2 Jam" itemValue="120"/>
<f:selectItem itemLabel="2 Jam 30 Minit" itemValue="150"/>
<f:selectItem itemLabel="3 Jam" itemValue="180"/>
<f:selectItem itemLabel="3 Jam 30 Minit" itemValue="210"/>
<f:selectItem itemLabel="4 Jam" itemValue="240"/>
<f:selectItem itemLabel="4 Jam 30 Minit" itemValue="270"/>
<f:selectItem itemLabel="5 Jam" itemValue="300"/>
<f:selectItem itemLabel="5 Jam 30 Minit" itemValue="330"/>
<f:selectItem itemLabel="6 Jam" itemValue="360"/>
<f:selectItem itemLabel="6 Jam 30 Minit" itemValue="390"/>
<f:selectItem itemLabel="7 Jam" itemValue="420"/>
<f:selectItem itemLabel="7 Jam 30 Minit" itemValue="450"/>
<f:selectItem itemLabel="8 Jam" itemValue="480"/>
<f:selectItem itemLabel="8 Jam 30 Minit" itemValue="510"/>
<f:selectItem itemLabel="9 Jam" itemValue="540"/>
<f:selectItem itemLabel="9 Jam 30 Minit" itemValue="570"/>
<f:selectItem itemLabel="10 Jam" itemValue="600"/>
<f:selectItem itemLabel="10 Jam 30 Minit" itemValue="630"/>
</p:selectOneMenu>
<h:panelGroup>
<p:commandButton value="#{bundle.OnLabel}"
action="#{calendarAdmin.addEventEx}"
oncomplete="myschedule.update(); newEventDialog.hide();"
update="growl"/>
<p:commandButton value="#{bundle.OffLabel}"
oncomplete="myschedule.update(); newEventDialog.hide();"/>
</h:panelGroup>
</h:panelGrid>
</p:dialog>
I am using a LazyScheduleModel to populate the schedule with events from database; here's my PostConstruct from the backing bean calendarAdmin ViewScoped bean.
@PostConstruct
public void init() {
try {
LogController.log.info("Initializing viewRoomBookingSchedule bean");
fc = FacesContext.getCurrentInstance();
bundle = fc.getApplication().getResourceBundle(fc, "bundle");
LogController.log.info("Loading room names for the select one box");
wfrooms = wfRoomFacade.selectAll();
LogController.log.info("Putting all other room labels into the select one box");
for (WfRoom wfr : wfrooms) {
rooms.put(wfr.getWfRoomName(), wfr.getIdWfRoom());
}
LogController.log.info("Initialize selected room id to all rooms with value 100");
selectedroomid = 100;
lazyEventModel = new LazyScheduleModel() {
@Override
public void loadEvents(Date start, Date end) {
LogController.log.info("Loading events for room " + selectedroomid + " starting from " + start.toString() + " until " + end.toString());
List<WfRoombookingschedule> wfroombookingschedules = loadSchedules(start, end);
if (wfroombookingschedules != null) {
for (WfRoombookingschedule wfrbs : wfroombookingschedules) {
Date combinedDateAndTime = workflowUtil.getDateTime(wfrbs.getWfRoombookingscheduleDate(), wfrbs.getWfRoombookingscheduleTime());
Date eventEndDate = workflowUtil.addMinutes(combinedDateAndTime, wfrbs.getWfRoombookingscheduleDuration());
String styleClass;
if (wfrbs.getIdWfRoombooking().getIdWfRoom().getIdWfRoom() == applicationConfig.getRoomEdit1()) {
styleClass = "edit1";
} else if (wfrbs.getIdWfRoombooking().getIdWfRoom().getIdWfRoom() == applicationConfig.getRoomEdit2()) {
styleClass = "edit2";
} else if (wfrbs.getIdWfRoombooking().getIdWfRoom().getIdWfRoom() == applicationConfig.getRoomSuaraMalaysia()) {
styleClass = "suaramalaysia";
} else if (wfrbs.getIdWfRoombooking().getIdWfRoom().getIdWfRoom() == applicationConfig.getRoomStudioMusic()) {
styleClass = "studiomusic";
} else if (wfrbs.getIdWfRoombooking().getIdWfRoom().getIdWfRoom() == applicationConfig.getRoomTalkMusic()) {
styleClass = "talkmusic";
} else {
styleClass = "defaultroom";
}
if (wfrbs.getIdWfRoombooking().getIdWfEventtype().getIdWfEventtype() != 2) {
addEvent(new DefaultScheduleEvent(wfrbs.getIdWfRoombooking().getIdWfSpecialevent().getWfSpecialeventName(), combinedDateAndTime, eventEndDate, styleClass));
} else {
addEvent(new DefaultScheduleEvent(wfrbs.getIdWfRoombooking().getIdWfStudiobooking().getWfStudiobookingTitle(), combinedDateAndTime, eventEndDate, styleClass));
}
}
}
}
};
} catch (Exception ex) {
LogController.log.fatal(ex.toString());
}
}
I the user click YES button on the new event dialog, managed bean will redirect him to createEventBooking.xhtml where he will be able to modify/confirm the new event details and he can click save button to save the new event into database. Upon successfull persistence into database the backing bean createEventBooking bean will redirect the user back to calendarAdmin.xhtml like this:
public String saveEvent() {
try {
......
**return "/calendarAdmin?faces-redirect=true";**
And here's when the problem occurs, it goes back to calendarAdmin.xhtml alright, but the schedule is empty and that little ajax status gif file that I put on top of calendarAdmin.xhtml keeps spinning indefinitely. If I rerun the application from within Netbeans run button, and I try to open calendarAdmin.xhtml the same thing happen again. That ajax status icon keep spinning indefinitely. I try refreshing the page with F5 but still the same problem.
When checking from MySQL Workbench, I see the new event is created successfully without any issue. But why does the page with primefaces schedule failed to load the events including the newly created event?
I did further testing and I restarted the glassfish 3.1.1 server, stop and start the server glassfish, rerun the application, reopen calendarAdmin.xhtml and voila the page open correctly and the events including the newly created event loads correctly.
I just got the answer. It was more of a parent-child entity jpa relationship problem. Anyway here's the database saving code (before) in my ejb facade object.
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public int addEvent(WfRoombooking wfroombooking, List<WfRoombookingschedule> wfroombookingschedules, WfSpecialevent wfspecialevent) {
try {
int res = 0;
LogController.log.debug("Beginning transaction");
LogController.log.debug("Create the wf room booking object");
create(wfroombooking);
LogController.log.debug("Refreshing the entity manager to get the new room booking id");
getEntityManager().flush();
LogController.log.debug("New booking id " + wfroombooking.getIdWfRoombooking());
//ROOM BOOKING SCHEDULE PERSISTENCE
if (wfroombookingschedules.size() > 0) {
LogController.log.debug("Saving the room booking schedules for this room booking");
LogController.log.debug("Assigning room booking with id " + wfroombooking.getIdWfRoombooking() + " to all the room booking schedule objects");
for (WfRoombookingschedule wfrbs : wfroombookingschedules) {
LogController.log.debug("Assigning room booking id for start date " + wfrbs.getWfRoombookingscheduleDate().toString() + " with duration " + wfrbs.getWfRoombookingscheduleDuration().toString());
wfrbs.setIdWfRoombooking(wfroombooking);
}
LogController.log.debug("Calling room booking schedule facade to persist the room booking schedules");
res = wfRoombookingscheduleFacade.addRoombookingschedules(wfroombookingschedules);
if (res == 0) {
LogController.log.debug("Room booking schedules information successfully persisted");
} else {
LogController.log.error("Error in persisting room booking schedules information");
}
} else {
res = 0;
LogController.log.debug("Room booking schedule not defined for this room booking");
}
//SPECIAL EVENT PERSISTENCE
LogController.log.debug("Saving the special event object for this room booking");
LogController.log.debug("Assigning room booking with id " + wfroombooking.getIdWfRoombooking() + " to the special event object");
wfspecialevent.setIdWfRoombooking(wfroombooking);
LogController.log.debug("Persisting the special event object");
wfSpecialeventFacade.addSpecialEvent(wfspecialevent);
LogController.log.debug("Ending transaction");
return res;
} catch (Exception ex) {
context.setRollbackOnly();
LogController.log.fatal(ex.toString());
return -1;
}
}
And here's the code after, please note that WfRoombookingschedule and WfSpecialevent are both child entity of WfRoombooking. Then I added association from parent to child like these;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public int addEvent(WfRoombooking wfroombooking, List<WfRoombookingschedule> wfroombookingschedules, WfSpecialevent wfspecialevent) {
try {
int res = 0;
LogController.log.debug("Beginning transaction");
LogController.log.debug("Create the wf room booking object");
create(wfroombooking);
LogController.log.debug("Refreshing the entity manager to get the new room booking id");
getEntityManager().flush();
LogController.log.debug("New booking id " + wfroombooking.getIdWfRoombooking());
//ROOM BOOKING SCHEDULE PERSISTENCE
if (wfroombookingschedules.size() > 0) {
LogController.log.debug("Saving the room booking schedules for this room booking");
LogController.log.debug("Assigning room booking with id " + wfroombooking.getIdWfRoombooking() + " to all the room booking schedule objects");
for (WfRoombookingschedule wfrbs : wfroombookingschedules) {
LogController.log.debug("Assigning room booking id for start date " + wfrbs.getWfRoombookingscheduleDate().toString() + " with duration " + wfrbs.getWfRoombookingscheduleDuration().toString());
wfrbs.setIdWfRoombooking(wfroombooking);
***LogController.log.debug("Setting room booking schedules into room booking");
wfroombooking.setWfRoombookingscheduleCollection(wfroombookingschedules);***
}
LogController.log.debug("Calling room booking schedule facade to persist the room booking schedules");
res = wfRoombookingscheduleFacade.addRoombookingschedules(wfroombookingschedules);
if (res == 0) {
LogController.log.debug("Room booking schedules information successfully persisted");
} else {
LogController.log.error("Error in persisting room booking schedules information");
}
} else {
res = 0;
LogController.log.debug("Room booking schedule not defined for this room booking");
}
//SPECIAL EVENT PERSISTENCE
LogController.log.debug("Saving the special event object for this room booking");
LogController.log.debug("Assigning room booking with id " + wfroombooking.getIdWfRoombooking() + " to the special event object");
wfspecialevent.setIdWfRoombooking(wfroombooking);
***LogController.log.debug("Setting room special event into room booking");
wfroombooking.setIdWfSpecialevent(wfspecialevent);***
LogController.log.debug("Persisting the special event object");
wfSpecialeventFacade.addSpecialEvent(wfspecialevent);
LogController.log.debug("Ending transaction");
return res;
} catch (Exception ex) {
context.setRollbackOnly();
LogController.log.fatal(ex.toString());
return -1;
}
}
I apologize to the mod if answering my own question is inappropriate, but I just feel the need to share so that others like me may benefit. TQ.