当我继续研究我的JSF项目时,我已经达到了需要一些帮助才能让我更进一步的目标。
首先,我的整个项目都可以通过以下链接获得:https://github.com/vasigorc/rimmaproject它可以编译并运行。
总之,我有一个预约页面。到目前为止,约会的唯一领域是约会。它通过primefaces日历组件输入。支持会话约会bean实现了一个Observable接口(Observer设计模式的一部分)。只要日期值发生变化,就会通知观察者。观察者是依赖 bean,它调用REST客户端以获取所选日期的天气预报的对象表示。选择日期并且最终用户点击提交后,天气预报应显示在同一页面的右侧。
测试完成:我已对所有部分采集方法以及Observer和Observable实现之间的集成进行了单元测试。但是当我运行应用程序时,更改日期并单击“提交”日期不会出现。
我找不到描述相同问题的stackoverflow票证,但我找到了一篇IBM文章,描述了如何在JSF中实现不同的设计模式。他们的建议是使用事件监听器方法。在我的应用程序设计中掉头之前,我希望得到你的建议,试图找到我的应用程序现在构建方式的缺陷。
代码 前端 预约页面:
<div class="col-md-4">
<h:form>
<h:panelGrid columns="2">
<span>#{copy.pickadate}</span>
<p:calendar id="calendar" value="#{appointmentFormBean.selectedDate}" locale="fr"
mindate="today" maxdate="today+90" mode="popup"
pattern="yyyy-MM-dd">
</p:calendar>
<input id="requestButton" type="button" value="#{copy.submitButton}">
<f:ajax event="click" execute="calendar" render="out weatherwidget"></f:ajax>
</input>
</h:panelGrid>
</h:form>
</div>
<div class="col-md-4 col-md-offset-4">
<ui:include id="weatherwidget" src="restservice/weatherWidget.xhtml"/>
</div>
<div><h:outputText id="out" value="#{appointmentFormBean.selectedDate}"></h:outputText></div>
'天气小工具':
<ui:composition>
<h:panelGrid columns="3" class="table table-bordered">
<h:outputText rendered="#{appointmentFormBean.datePickerActivated}">#{forecastBeanTwo.forecast.day}</h:outputText>
</h:panelGrid>
</ui:composition>
约会支持bean的签名:
@Named(value = "appointmentFormBean")
@SessionScoped
public class AppointmentFormBean implements Serializable, Observed
负责调用Observer的方法
public void setSelectedDate(Date selectedDate) {
this.selectedDate = selectedDate;
notifyVGObservers();
setDatePickerActivated(true);
}
@Override
public void notifyVGObservers() {
observers.stream().map((observer1) -> (VGObserver) observer1).forEach((observer) -> {
observer.update(selectedDate);
});
}
'Observer'Bean的签名和托管属性声明:
@ManagedBean
@Dependent
public class WeatherForecastBean implements Serializable, VGObserver
@ManagedProperty(value = "#{appointmentFormBean}")
private AppointmentFormBean formBean;
注意观察点
//point of IoC
public void setFormBean(AppointmentFormBean formBean) {
this.formBean = formBean;
formBean.registerVGObserver(this);
}
最后,更新方法:
Override
public void update(Date selectedDate) {
/*
get the 15 days from today date object
and check whether the client requested day is not
after it.
*/
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, +15);
if (selectedDate.after(cal.getTime())) {
/*
So, if the selected date is after today+15 days
then we will tell the client that we cannot grab a weathe for him
i.e. DailyForecast = UnavailableForecast.class
*/
setForecast(new UnavailableForecast());
}else{
/*
Now that we know that the selected date is within the range
of available forecasts, we need to extract the requested day
forecast (represented by a Time object)
from the total of 16 available days
*/
java.sql.Date sqlDate = utilToSql(selectedDate);
Time requestedTime = findGoodTime(dwr.getDays(),
(Time t)->sqlDate.toString().equals(t.getDay()));
setForecast(new TimeAdapter(requestedTime));
}
}
这不是一个简单的问题。正如我所说,完整的代码可以在github上找到,但是也欢迎您提出任何问题。任何建议都会有所帮助。
答案 0 :(得分:0)
我放弃了我的旧设计,因为我需要继续推进该项目。我放弃了Observer-Observable对象关系,并且采用了IBM文章之前提到的路径:
观察者模式 Observer模式的目的是在主题中的状态发生变化时自动通知所有依赖对象(或观察者)。 JSF框架在UI组件中实现Observer模式。 JSF技术有两种内置事件:ActionEvent和ValueChangedEvent。 ActionEvent在确定用户界面组件(如按钮)的激活时非常有用。当用户单击该按钮时,JSF实现会通知添加到该按钮的一个或多个动作侦听器。按钮被激活或按钮(主体)的状态发生变化。所有监听器(或观察者)都会收到添加到按钮的主题状态变化的通知。同样,当输入UI组件中的值发生更改时,JSF实现会通知ValueChangeListeners。
来源:http://www.ibm.com/developerworks/library/wa-dsgnpatjsf/
这些是我所做的改变。
在前端我添加了PrimeFaces eventListener :
<p:calendar id="calendar" value="#{appointmentFormBean.selectedDate}" locale="fr"
mindate="today" maxdate="today+90" mode="popup"
pattern="yyyy-MM-dd">
<p:ajax event="dateSelect" listener="#{forecastBeanTwo.handleDateSelect}"/>
</p:calendar>
在后端,我使用handleDateSelect()方法更改了update()方法:
public void handleDateSelect(SelectEvent event){
/*
get the 15 days from today date object
and check whether the client requested day is not
after it.
*/
Date selectedDate= (Date)event.getObject();
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, +15);
if (selectedDate.after(cal.getTime())) {
/*
So, if the selected date is after today+15 days
then we will tell the client that we cannot grab a weathe for him
i.e. DailyForecast = UnavailableForecast.class
*/
setForecast(new UnavailableForecast());
}else{
/*
Now that we know that the selected date is within the range
of available forecasts, we need to extract the requested day
forecast (represented by a Time object)
from the total of 16 available days
*/
java.sql.Date sqlDate = utilToSql(selectedDate);
Time requestedTime = findGoodTime(dwr.getDays(),
(Time t)->sqlDate.toString().equals(t.getDay()));
setForecast(new TimeAdapter(requestedTime));
}
setBeanActivated(true);
}
然而一切正常......令我沮丧的是,因为这种设计看起来像是一种解决方法。