Story:
I'm working on a accommodation website. I want to do some Ajax render in a page based on day change. If i use a JSF command component like command button, the WebSocket Push will work. But if i use observable bean to ask observer bean to invoke the pushContext.send
method, the onDayChange method get called after one minute and there is no exception in this method but the accommodationSearchFields element isn't rendered and thus the data-currentDate attribute doesn't change and when i look at Web Developer Tools > Network > XHR, there is no record.
What I've done:
The EJB Bean:
@Singleton @Lock(LockType.READ)
public class DateScheduled implements NextDayObservable{
// Other member variables
private final ScheduledExecutorService scheduledExecutorService;
private final List<NextDayObserver> dateObservers;
public DateScheduled(){
/*this.now = LocalDateTime.now();
this.nextDay = LocalDateTime.now()
.withHour(00)
.withMinute(0)
.withSecond(1)
.withNano(0);
scheduledExecutorService.scheduleAtFixedRate(
() -> { notifyObserversOfDayChange(); },
now.until(nextDay, ChronoUnit.MILLIS),
TimeUnit.DAYS.toMillis(1),
TimeUnit.MILLISECONDS
);*/
this.scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(
() -> { notifyObserversOfDayChange(); },
10000,
TimeUnit.DAYS.toMillis(1),
TimeUnit.MILLISECONDS
);
this.dateObservers = new ArrayList<>();
}
@Override @Lock(LockType.WRITE)
public void registerObserver(final NextDayObserver dateObserver){
if(dateObservers.indexOf(dateObserver) < 0){
dateObservers.add(dateObserver);
}
}
@Override @Lock(LockType.WRITE)
public void removeObserver(final NextDayObserver dateObserver){
dateObservers.remove(dateObserver);
}
@Override
public void notifyObserversOfDayChange(){
dateObservers.forEach(
dateObserver -> { dateObserver.onDayChange(); }
);
}
}
The Backing Bean:
@Named @ApplicationScoped
public class MainTemplateMB extends BaseManagedBean implements Serializable, NextDayObserver{
private static final long serialVersionUID = 1L;
// Other member variables
private String currentDate;
@EJB
protected NextDayObservable nextDayObservable;
@Inject @Push
private PushContext pushContext;
// Other member variables
public MainTemplateMB(){
// Other Initializations
this.currentDate = "";
}
@PostConstruct
private void initialization(){
// Other Initializations
nextDayObservable.registerObserver(this);
currentDate = DateUtility.getCurrentYear() + "." + (DateUtility.getCurrentMonth() -1) + "." + DateUtility.getCurrentDay() + "." + DateUtility.getMonthFirstDay()+ "." + DateUtility.getLastMonthMaximumDays();
}
// Other Methods
@Override
public void onDayChange(){
// currentDate has changed for testing
currentDate = DateUtility.getCurrentYear() + "." + ( DateUtility.getCurrentMonth() + 1 ) + "." + DateUtility.getCurrentDay() + "." + DateUtility.getMonthFirstDay()+ "." + DateUtility.getLastMonthMaximumDays();
pushContext.send("dayChange");
}
}
The MainTemplate.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:jsf="http://xmlns.jcp.org/jsf"
xmlns:jsfc="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
lang="#{sessionTools.language}" xml:lang="#{sessionTools.language}">
<jsfc:view locale="#{sessionTools.locale}" contentType="text/html">
<head>
.
.
.
</head>
<body>
<div id="wrapper">
.
.
.
<section jsf:id="accommodationSearchFields" data-currentDate="#{mainTemplateMB.currentDate}">
<form jsf:id="accommodationSearchForm" method="GET" autocomplete="off">
.
.
.
<input class="button field roundedCorners4" type="submit" value="#{mainTemplateProp.search}" jsf:action="#{mainTemplateMB.goToTheCity()}" />
<!-- <input class="button field roundedCorners4" type="submit" value="#{mainTemplateProp.search}" jsf:action="#{mainTemplateMB.onDayChange()}">
<jsfc:ajax />
</input> -->
.
.
.
</form>
</section>
.
.
.
</div>
<form jsf:id="dayChangeWebSocket">
<jsfc:websocket channel="pushContext">
<jsfc:ajax event="dayChange" render=":accommodationSearchFields" />
</jsfc:websocket>
</form>
</body>
</jsfc:view>
</html>
After switching to JEE Observer Pattern:
The EJB Bean:
@Singleton @Startup @Lock(LockType.READ)
public class DateScheduled{
// Other member variables
private final ScheduledExecutorService scheduledExecutorService;
@Inject
private BeanManager beanManager;
public DateScheduled(){
/*this.now = LocalDateTime.now();
this.nextDay = LocalDateTime.now()
.withHour(00)
.withMinute(0)
.withSecond(1)
.withNano(0);
scheduledExecutorService.scheduleAtFixedRate(
() -> { notifyObserversOfDayChange(); },
now.until(nextDay, ChronoUnit.MILLIS),
TimeUnit.DAYS.toMillis(1),
TimeUnit.MILLISECONDS
);*/
this.scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(
() -> { notifyObserversOfDayChange(); },
60000,
TimeUnit.DAYS.toMillis(1),
TimeUnit.MILLISECONDS
);
}
public void notifyObserversOfDayChange(){
beanManager.fireEvent("Hello");
}
}
The Backing Bean:
@Named @ApplicationScoped
public class MainTemplateMB extends BaseManagedBean implements Serializable{
private static final long serialVersionUID = 1L;
// Other member variables
private String currentDate;
@Inject @Push
private PushContext pushContext;
// Other member variables
public MainTemplateMB(){
// Other Initializations
this.currentDate = "";
}
@PostConstruct
private void initialization(){
// Other Initializations
currentDate = DateUtility.getCurrentYear() + "." + (DateUtility.getCurrentMonth() -1) + "." + DateUtility.getCurrentDay() + "." + DateUtility.getMonthFirstDay()+ "." + DateUtility.getLastMonthMaximumDays();
}
// Other Methods
public void onDayChange(@Observes String message){
// currentDate has changed for testing
currentDate = DateUtility.getCurrentYear() + "." + ( DateUtility.getCurrentMonth() + 1 ) + "." + DateUtility.getCurrentDay() + "." + DateUtility.getMonthFirstDay()+ "." + DateUtility.getLastMonthMaximumDays();
pushContext.send("dayChange");
}
}
Work Tools:
. Apache TomEE Plus 8.0.3
. Apache NetBeans IDE 12.0
Questions:
- Did i something wrong?
- What is the problem?
- How to solve the problem?