未调用JSF操作方法 [英] JSF Action Method not being called
问题描述
我有一个带有Primefaces数据表的JSF视图,并在其中有一个命令按钮,如下所示:
I have a JSF view with a Primefaces data table and a command button insite it, as fallows:
<p:messages id="statusMessages" showDetail="true" />
<h:form id="listForm">
<p:panel header="Wellsite List">
<br />
<h:outputLabel value="Welcome, #{wellsiteController.loggedUser.login}" />
<br />
<br />
<p:dataTable id="dataTable" var="wellsite" value="#{wellsiteController.wellsiteDataTableModel}"
paginator="true" rows="10" selection="#{wellsiteController.wellsite}">
<p:column selectionMode="single" style="width:18px" id="radioSelect" />
<p:column sortBy="#{wellsite.reference}" headerText="Wellsite ID">
<h:outputText value="#{wellsite.reference}" />
</p:column>
<p:column headerText="Allowed Groups">
<h:outputText value="#{wellsite.allowedGroups.toString()}" />
</p:column>
<f:facet name="footer">
<h:panelGrid columns="3">
<p:commandButton id="addWellsite" value="Add New Wellsite" icon="ui-icon-flag" ajax="false" action="#{wellsiteController.showAddWellsite}"/>
<p:commandButton id="editWellsite" value="Edit Selected Wellsite" icon="ui-icon-wrench" ajax="false" action="#{wellsiteController.showEditWellsite}"/>
<p:commandButton id="deleteWellsiteButton" value="Remove Selected Wellsite" icon="ui-icon-trash" onclick="confirmation.show()" type="button"/>
</h:panelGrid>
</f:facet>
</p:dataTable>
<p:spacer height="20" />
</p:panel>
<p:confirmDialog id="confirmDialog" message="Are you sure you want to remove the selected Wellsite along with all it's data?" header="Confirmation" severity="alert" widgetVar="confirmation">
<p:commandButton id="confirm" value="Yes" ajax="false" oncomplete="confirmation.hide()" action="#{wellsiteController.deleteWellsite}" />
<p:commandButton id="decline" value="Cancel" onclick="confirmation.hide()" type="button" />
</p:confirmDialog>
</h:form>
这是控制器:
@ManagedBean(name = "wellsiteController")
@RequestScoped
public class WellsiteController implements Serializable {
private static final long serialVersionUID = 1L;
@ManagedProperty("#{wellsiteDao}")
private WellsiteDao wellsiteDao;
@ManagedProperty("#{userDao}")
private UserDao userDao;
@ManagedProperty("#{groupDao}")
private GroupDao groupDao;
@ManagedProperty("#{userController.loggedUser}")
private UserEnt loggedUser;
private WellsiteEnt wellsite;
private List<WellsiteEnt> wellsiteList;
DualListModel<GroupEnt> pickGroupsModel;
public WellsiteController(){
}
@PostConstruct
public void build(){
wellsite = new WellsiteEnt();
wellsite.setAllowedGroups(new ArrayList<GroupEnt>());
}
/*some getters & setters*/
public WellsiteDataTableModel getWellsiteDataTableModel(){
return new WellsiteDataTableModel(getWellsiteList());
}
public void setPickGroupsModel(DualListModel<GroupEnt> model){
pickGroupsModel = model;
}
public DualListModel<GroupEnt> getPickGroupsModel() {
if(pickGroupsModel == null){
List<GroupEnt> allGroups = groupDao.getAll();
List<GroupEnt> currentGroups = wellsite.getAllowedGroups();
for(GroupEnt g : currentGroups){
allGroups.remove(g);
}
pickGroupsModel = new DualListModel<GroupEnt>(allGroups, currentGroups);
}
return pickGroupsModel;
}
public String listWellsites(){
getWellsiteList();
return "listWellsites";
}
public String showAddWellsite(){
FacesContext context = FacesContext.getCurrentInstance();
setWellsite(new WellsiteEnt());
wellsite.setAllowedGroups(new ArrayList<GroupEnt>());
pickGroupsModel = null;
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,
"Fields annotated with a ' * ' are mandatory",""));
return "addWellsite";
}
public String addWellsite(){
FacesContext context = FacesContext.getCurrentInstance();
wellsite.setDate(new Date());
wellsite.setLastUpdate(wellsite.getDate());
try {
wellsiteDao.addWell(wellsite);
for(GroupEnt g : pickGroupsModel.getTarget()){
GroupEnt group = groupDao.getOne(g.getGroupId());
group.getGroupWellsites().add(wellsite);
groupDao.update(group);
}
return listWellsites();
} catch (Exception ex) {
Logger.getLogger(WellsiteController.class.getName()).log(Level.SEVERE, null, ex);
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR,
ex.getMessage(),""));
return null;
}
}
}
此视图正确呈现.数据表和按钮看起来不错.问题是,当我第一次单击"addWellsite"命令按钮时,什么也没发生.该页面似乎只是刷新.如果我再次单击它,则发生异常:
This view gets rendered correctly. The datatable and buttons looks fine. The problem is that when first i click the "addWellsite" commandButton, nothing happens. The page just seems to refresh. If i click it again, as exception happens:
java.lang.NumberFormatException: For input string: "null"
使用调试器,我发现第一次没有调用"addWellsite"的动作,因此,不会生成任何结果(因此,页面刷新).
Using a debugger, i found out that the "addWellsite"'s action is NOT called the first time, and so, not outcome is generated (thus, the page refresh).
该异常可能是由于当前视图或目标视图中缺少初始化而造成的(因为这两个视图都是通过页面刷新中未调用的操作方法显示的)
The exception is probably comming from the lack of initialization in the current or the target views (since both view are displayed from action methods that were not called in the page refresh)
问题是:为什么不第一次调用该操作方法?
自此答案:
只要
UICommand
组件未能调用关联的操作,请验证以下内容:
Whenever an
UICommand
component fails to invoke the associated action, verify the following:
-
UICommand
组件必须放置在UIForm
组件(例如h:form
)内部.
UICommand
components must be placed inside anUIForm
component (e.g.h:form
).
我确实有一个h:form
I do have a h:form
- 您不能互相嵌套多个
UIForm
组件(当心包含文件!).
- You cannot nest multiple
UIForm
components in each other (watch out with include files!).
只有一个.
- 应该不会发生任何验证/转换错误(使用
h:messages
可以全部获取).
- No validation/conversion error should have been occurred (use
h:messages
to get them all).
我有一个不会显示任何错误的h:messages.
I have a h:messages that does not display any error.
- 如果将
UICommand
组件放置在UIData
组件内部,请确保保留完全相同的DataModel
(UIData
的value
属性后面的对象).
- If
UICommand
components are placed inside anUIData
component, ensure that exactly the sameDataModel
(the object behind theUIData
'svalue
attribute) is preserved.
commandButton在dataTable内部,但是目标视图不需要dataModel.如我的控制器代码所示,该对象是在视图尝试检索它时生成的.下一个请求不使用此dataTable,我不再处理它.
The commandButton is inside the dataTable, but the target view does not need the dataModel. As my controller code shows, the object is built as the view tries to retrive it. The next request is not using this dataTable, to i do not handle it anymore.
- 该组件以及所有父组件的
rendered
和disabled
属性在应用请求值阶段不应评估为false
.
- The
rendered
anddisabled
attributes of the component and all of the parent components should not evaluate tofalse
during apply request values phase.
没有rendered
或disbled
属性.
- 请确保请求-响应链中没有任何
PhaseListener
或任何EventListener
更改了JSF生命周期以跳过调用操作阶段.
- Be sure that no
PhaseListener
or anyEventListener
in the request-response chain has changed the JSF lifecycle to skip the invoke action phase.
未定义phaseListener.
No phaseListener is defined.
- 请确保同一请求-响应链中没有
Filter
或Servlet
阻止了FacesServlet
的请求.
- Be sure that no
Filter
orServlet
in the same request-response chain has blocked the request fo theFacesServlet
somehow.
未定义其他Servlet.我什至都不知道过滤器是什么.
No other Servlet is defined. I don't even know what a Filter is.
为什么不第一次调用该操作方法?
推荐答案
当预先由另一个 <h:form>
发起的ajax请求呈现了该<h:form>
的父级时,可能会发生这种情况.然后,渲染/更新的<h:form>
将丢失其视图状态.这是由 JSF问题790 中所述的JavaScript API中的错误引起的已针对即将推出的JSF 2.2进行了修复.
This can happen when a parent of this <h:form>
was been rendered by an ajax request initiated by another <h:form>
beforehand. The rendered/updated <h:form>
would then lose its view state. This is caused by a bug in the JavaScript API as described in JSF issue 790 which is already fixed for the shortly upcoming JSF 2.2.
同时,对于JSF 2.0/2.1,您需要以另一种形式在操作的render
(或对于PrimeFaces,update
)属性中明确指定<h:form>
的客户机ID.
In the meanwhile, with JSF 2.0/2.1, you need to explicltly specify the client ID of the <h:form>
in the render
(or for PrimeFaces, the update
) attribute of the action in the other form.
例如
<h:commandButton ...>
<f:ajax ... render=":listForm" />
</h:commandButton>
或
<p:commandButton ... update=":listForm" />
或者只是将其设为普通(非ajax)请求.
Or just make it a normal (non-ajax) request instead.
这篇关于未调用JSF操作方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!