0

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>
Community
  • 1
  • 1
Richard Barker
  • 1,161
  • 2
  • 12
  • 30
  • From your code, the problem cannot be reproduced. Please provide the content of template.xhtml for further analysis of the problem. – Luiggi Mendoza Dec 25 '14 at 07:28
  • @LuiggiMendoza, I added the template file. I hope it helps. – Richard Barker Dec 25 '14 at 16:11
  • You again affixed the tag "java-ee" to the question. Not invoking an action/action listener associated with a command link/command button apparently implies that the problem is strictly restricted to JSF (and/or some advanced JSF component libraries, if any). The tag "java-ee" is more commonly used while using/referring to advanced Java EE things such as JAX-RS, JAX-WS, Weld, CDI, JMS, WebSockets etc and maybe some Java EE container related things. Apology, if I did something disrespectful. – Tiny Dec 26 '14 at 00:31
  • You said, "*The last (update) button isn't calling the action*". There is namely no button which can intuitively be taken into consideration. That last button is labelled "Save" on "Form 2". – Tiny Dec 26 '14 at 00:32
  • 1
    You may want to consider different action methods for different actions/action listeners associated with different command buttons in the associated backing bean. Identifying which command button is clicked using that plain ugly `if-else if-else` ladder in the same single method (for different actions/action listeners associated with different command buttons) does not appear to be a good practice (sure, there are also some use-cases where this sort of thins are beneficial/appropriate/needed). – Tiny Dec 26 '14 at 00:52
  • @Tiny, You are right, it is very, very, extremely ugly. Considering this is my first java web app, it suits my purposes. Again, it is hard to intuitively determine which button I'm having problems, you are right. I should be more clear next time. There is no apology needed if criticism is constructive and aimed at improving your fellow stackers' questions, tagging, and programming abilities -- so there is no disrespect. – Richard Barker Dec 26 '14 at 03:10
  • But the problem still stands -- the actionlistener is not being invoked. I did as you suggested and tried to use a separate event for that one button but to no avail as that action wasn't invoked either. I'm going to try to use an actionlistener that doesn't take an ActionEvent and see if that's invoked -- but something tells me it won't be. Thank you, @Tiny, for your help. And your criticism. – Richard Barker Dec 26 '14 at 03:13

0 Answers0