actionListener associated with an h:commandLink/h:commandButton is not invoked

875 Views Asked by At

I have a 2 forms that contain 4 buttons with each button having a an actionListener property set to call a single method in a request scoped bean. This method checks to determine what button is performing the action and then does a few things based on that information (Create, Read, Update, or Delete). The problem is that, out of these four buttons, three work. The last (update) button isn't calling the action.

This question helped a little bit as, after reading it, I managed to get the fourth button to work once (breakpoints and variable watching determined that) -- but then I stopped the program, made a small change because the page failed to not render a portion of the page (dependent of the 'editing' variable), watched it fail again, and then forgot what I did to make it work. I've determined that the problem is not nested forms, that I'm importing the right event class, that there are no validation errors, that there are no iterating tags, that the buttons are rendering and are not disabled, or any of the other points mentioned in @BalusC 's answer to that question except one -- when I use a <h:commandLink>, JS is rendered on the page that returns false although changing to a <h:commandButton> still fails to invoke the actionListener. But what's weird is that the one time is worked and the action was invoked I was using a <h:commandLink>.

Does anyone see what I'm doing wrong?

Form 1 (create; works):

    <html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
      xmlns:f="http://xmlns.jcp.org/jsf/core">

    <h:head></h:head>

    <h:body>
        <ui:composition template="../../template.xhtml">
            <ui:define name="top">
                New Location View
            </ui:define>

            <ui:define name="left"></ui:define>

            <ui:define name="content">
                <f:view>
                    <h:form>
                        <h2><h:outputText value="Create a Location"/></h2>
                        <h:panelGrid columns="2">
                            <h:outputLabel for="locationName" value="Name:"/>
                            <h:inputText id="locationName" value="#{locationBean.locationName}"/>
                            <h:outputLabel for="locationDesc" value="Description:"/>
                            <h:inputText id="locationDesc" value="#{locationBean.locationDescription}"/>
                            <h:commandButton value="Add Location" id="createact" actionListener="#{locationBean.doAction}"/>
                        </h:panelGrid>
                    </h:form>
                </f:view>
            </ui:define>
        </ui:composition>
    </h:body>
</html>

Form 2 (Read (a details button clicked from a listing page which redirects to this one) works, Update; doesn't work, Delete; works):

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>

    </h:head>
    <h:body>
        <ui:composition template="../../../template.xhtml">
            <ui:define name="top">
                Location Details View
            </ui:define>

            <ui:define name="left">

            </ui:define>

            <ui:define name="content">
                <c:set var="location" value="#{locationBean.l}"/>

                <h:form>
                    <h:panelGrid columns="2" rendered="#{not locationBean.editing}" >
                        <h:outputLabel value="Name:"/>
                        <h:outputText  id="nameout" value="#{location.locationname}"/>
                        <h:outputLabel value="Description:" />
                        <h:outputText  id="descout" value="#{location.description}"/>
                        <h:commandButton id="delact"  actionListener="#{locationBean.doAction}" value="Delete"/>
                        <h:commandButton id="editact"  actionListener="#{locationBean.doAction}" value="Edit"/>
                    </h:panelGrid>
                    <h:panelGrid columns="2" rendered="#{locationBean.editing}">
                        <h:outputLabel value="Name:" />
                        <h:inputText   id="namein" value="#{location.locationname}" required="true" requiredMessage="There must be a name."/>
                        <h:outputLabel value="Description:" />
                        <h:inputText  id="descin" value="#{location.description}" required="true" requiredMessage="There must be a description."/>
                        <h:commandLink id="cancelact" actionListener="#{locationBean.doAction}" value="Cancel"/>
                        <h:commandLink id="saveact" actionListener="#{locationBean.doAction}" value="Save"/>
                    </h:panelGrid>
                    <h:inputHidden value="#{location.identifier}" id="viewid" />
                    <c:catch var="error">
                        <h:outputLabel value="#{error.message}" />
                    </c:catch>
                </h:form>
                <h:outputText value="will also show location hours and days open and employees at this location."/>
            </ui:define>
        </ui:composition>
    </h:body>
</html>

doAction method (called from all four buttons):

public void doAction(ActionEvent e) {
    String callingID = e.getComponent().getId();
    try {
        if (callingID.isEmpty()) {//id is empty
            FacesContext.getCurrentInstance().addMessage(callingID, new FacesMessage(
                    "What are you doing wrong? Actions must have a valid id.",
                    "Empty Strings are not a valid id."));
        } else if (callingID.endsWith("delact")) {//component id is delete
            this.l = lsb.getLocationToView();
            lsb.delete(l);
            FacesContext.getCurrentInstance().getExternalContext().redirect("/EmployeeScheduler-war/webpages/view/locations.xhtml");
        } else if (callingID.endsWith("editact")) {//component id is edit
            this.editing = true;
            this.l = lsb.getLocationToView();
        } else if (callingID.endsWith("saveact")) {//component id is save, usually after an edit action
            this.editing = false;
            lsb.edit(l);
        } else if (callingID.endsWith("cancelact")) {//component id is cancel. usuallys after edit action
            this.editing = false;
        } else if (callingID.endsWith("createact")) {//component id is create. always create a new location
            FacesContext.getCurrentInstance().getExternalContext().redirect("/EmployeeScheduler-war/webpages/view/locations.xhtml");
            lsb.create(l);
        } else if (callingID.endsWith("detailsact")) {//component id is details. alwas from list view
            this.l = lsb.getLocationToView();
        } else {
            FacesContext.getCurrentInstance().addMessage(callingID, new FacesMessage(
                    "What are you doing wrong? Actions must have a valid id.",
                    callingID + " is not not valid."));
        }
        //catch any failures
    } catch (RollbackFailureException ex) {
        FacesContext.getCurrentInstance().addMessage(callingID, new FacesMessage(
                "An error occured trying to rollback the deletion of the location: " + ex.getMessage(),
                "Details: " + ex.getCause().getMessage()));
    } catch (Exception ex) {
        FacesContext.getCurrentInstance().addMessage(callingID, new FacesMessage(
                "An error occured trying to delete the location: " + ex.getMessage(),
                "Details: " + (ex.getCause() == null ? "none" : ex.getCause().getMessage())));
    }
}

Template file:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">

    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>Employee Scheduler</title>
        <link href="resources/styles/main.css" rel="stylesheet" type="text/css"/>
        <ui:insert name="head"/>
    </h:head>

    <h:body style="margin-right:15%;margin-left:15%">

        <div id="container">
            <div id="header">
                <div style="float: left;width:50%;margin-right: auto;">
                    Welcome to the BMS Employee Scheduler
                </div>
                <div style="float:right;width:50%;margin-left: auto;">
                    <h:form id="loginForm">
                        <h:panelGrid columns="2" cellspacing="2px" style="text-align: right">
                            <h:outputLabel for="usernameInput">
                                Username
                            </h:outputLabel>
                            <h:inputText disabled="#{login.loginDisabled}" id="usernameInput" value="#{login.username}" 
                                         required="true" />
                            <h:outputLabel for="passwordInput">
                                Password
                            </h:outputLabel>
                            <h:inputSecret disabled="#{login.loginDisabled}" id="passwordInput" value="#{login.password}" 
                                           required="true" />
                        <h:commandButton disabled="#{login.loginDisabled}" value="Login" action="#{login.login}" style="float: right"/>
                        </h:panelGrid>
                    </h:form>
                </div>
                <ui:insert name="top"/>
            </div>

            <div id="body">
                <div id="sidebar">
                    <h:panelGrid columns="1" style="text-align: left">
                        <h:outputLink value="./index.xhtml" >Home</h:outputLink> 
                        <h:outputLink value="./webpages/view/users.xhtml">Users</h:outputLink>
                        <h:outputLink value="./webpages/view/locations.xhtml">Locations</h:outputLink>
                        <ui:insert name="left" />
                    </h:panelGrid>
                </div>
                <div id="content">
                    <ui:insert name="content" />
                </div>
            </div>

            <br style="clear:both"/>
        </div>

    </h:body>
</html>
0

There are 0 best solutions below