JSF 操作方法未被调用

标签 jsf methods action

我有一个 JSF View ,其中包含 Primefaces 数据表和其中的命令按钮,如下所示:

<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>

这是 Controller :

@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;
    }
}
}

此 View 已正确渲染。数据表和按钮看起来不错。问题是,当我第一次单击“addWellsite”命令按钮时,没有任何反应。页面似乎刚刚刷新。如果我再次单击它,则会发生异常:

java.lang.NumberFormatException:对于输入字符串:“null”

使用调试器,我发现“addWellsite”的操作不是第一次调用,因此不会生成结果(因此,页面刷新)。

异常可能是由于当前 View 或目标 View 中缺少初始化(因为这两个 View 都是通过页面刷新中未调用的操作方法显示的)

问题是:为什么操作方法没有第一次被调用?

this answer起:

Whenever an UICommand component fails to invoke the associated action, verify the following:

  1. UICommand components must be placed inside an UIForm component (e.g. h:form).

我有一个 h:form

  1. You cannot nest multiple UIForm components in each other (watch out with include files!).

只有一个。

  1. No validation/conversion error should have been occurred (use h:messages to get them all).

我的 h:messages 不显示任何错误。

  1. If UICommand components are placed inside an UIData component, ensure that exactly the same DataModel (the object behind the UIData's value attribute) is preserved.

commandButton 位于 dataTable 内部,但目标 View 不需要 dataModel。正如我的 Controller 代码所示,该对象是在 View 尝试检索它时构建的。下一个请求不使用这个数据表,我不再处理它。

  1. The rendered and disabled attributes of the component and all of the parent components should not evaluate to false during apply request values phase.

没有 rendereddisbled 属性。

  1. Be sure that no PhaseListener or any EventListener in the request-response chain has changed the JSF lifecycle to skip the invoke action phase.

没有定义phaseListener。

  1. Be sure that no Filter or Servlet in the same request-response chain has blocked the request fo the FacesServlet somehow.

没有定义其他 Servlet。我什至不知道 Filter 是什么。

为什么第一次没有调用操作方法?

最佳答案

<h:form> 的父级时,可能会发生这种情况由 另一个 发起的 ajax 请求呈现 <h:form>预先。渲染/更新的<h:form>然后将失去其 View 状态。这是由 JavaScript API 中的错误引起的,如 JSF issue 790 中所述。即将推出的 JSF 2.2 已修复该问题。

同时,对于 JSF 2.0/2.1,您需要显式指定 <h:form> 的客户端 ID。在 render (或者对于 PrimeFaces, update )其他形式的操作属性。

例如

<h:commandButton ...>
   <f:ajax ... render=":listForm" />
</h:commandButton>

<p:commandButton ... update=":listForm" />

或者只是将其设为普通(非 ajax)请求。

另请参阅:

关于JSF 操作方法未被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10586489/

相关文章:

java - Java5 中的方法公司在另一个泛型中带有一个泛型

java - 从其他未连接的类接收特定值

java - struts 2 : Action result. 如何在jsp上显示浏览器地址行链接?

c# - Linq方法返回一组随机记录

c# - 如何更改 MVC 中子 Action 的顺序

c# - 如何创建一个新线程来执行 Action<T>

javascript - 更新c :foreach/ui:repeat with javascript

javascript - 如何解决与 primefaces jquery 的冲突

jsf - JSF 中的条件重定向

jsf - <h :selectOneRadio> value not updated in bean