Avoid updating data in case of error while writing (JSF + Primefaces)

I have a web application in JSF 2.1 + Primefaces 5.1. I have a datatable with selectable rows. When I select a row and click the Edit button, a dialog box opens allowing the user to edit the values ​​for that record. When the user clicks the Save button, a procedure is called to update the row and update the data via Ajax. If the procedure fails due to some business logic requirement, the data should not be updated, it should retain the old values ​​for this row. But what happens is that the values ​​are updated on the client side, although they remain in the database with the old (and correct) values. After updating, datatable shows old values.

Datatable and edit button:

<h:form id="search_users_form_id">  
        <p:commandButton id="edit_user_button_id" value="#{msgs.edit}" disabled="#{usersBean.editUserButtonDisabled}" onclick="openDialog('edit_user_dlg')" update=":edit_user_form_id" actionListener="#{usersBean.populateDataForUserEdition}"/>

        <p:dataTable id="users_table_id" var="user" value="#{usersBean.users}" rowKey="#{user.id}" paginator="true"
            paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
               rowsPerPageTemplate="5,10,15" selection="#{usersBean.selectedUser}" selectionMode="single" emptyMessage="#{msgs.no_records}" sortBy="#{user.id}" 
               sortOrder="ascending" rows="15">
            <f:facet name="header">
                #{msgs.users}               
            </f:facet>
            <p:ajax event="rowSelect" listener="#{usersBean.onRowSelect}" update=":search_users_form_id:edit_user_button_id"/>
            <p:ajax event="rowUnselect" listener="#{usersBean.onRowUnselect}" update=":search_users_form_id:edit_user_button_id"/>
            <p:column headerText="#{msgs.id}" sortBy="#{user.id}" styleClass="centered-column">
                #{user.id}
            </p:column>          
            <p:column headerText="#{msgs.description}" sortBy="#{user.description}" styleClass="centered-column">
                #{user.description}
            </p:column>          
            <p:column headerText="#{msgs.password}" sortBy="#{user.password}" styleClass="centered-column">
                #{user.password}
            </p:column>
            <p:column headerText="#{msgs.sending_system}" sortBy="#{user.playerIn.description}" styleClass="centered-column">
                #{user.playerIn.description}
            </p:column> 
            <p:column headerText="#{msgs.receiving_system}" sortBy="#{user.playerOut.description}" styleClass="centered-column">
                #{user.playerOut.description}
            </p:column>                                     
            <p:column headerText="#{msgs.active}" sortBy="#{user.active}" styleClass="centered-column">
                <p:selectBooleanCheckbox value="#{user.active}" disabled="true"/>               
            </p:column>
            <f:facet name="footer">
            </f:facet>      
        </p:dataTable>
    </h:form>

      

Dialogue:

<p:dialog modal="true" appendTo="@(body)" header="#{msgs.edit_user}" widgetVar="edit_user_dlg" closeOnEscape="true" resizable="false">
            <h:form id="edit_user_form_id">
                <h:panelGrid columns="3">
                    #{msgs.description}: <p:inputText value="#{usersBean.selectedUser.description}"/>
                    <h:panelGroup layout="block">
                        <p:graphicImage id="edit_user_description_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
                        <p:tooltip id="edit_user_description_tooltip_id" for="edit_user_description_tooltip_image_id" value="#{msgs.tooltip_users_description}"/>
                    </h:panelGroup>

                    #{msgs.password}: 
                    <p:inputText value="#{usersBean.selectedUser.password}" maxlength="50"/>
                    <h:panelGroup layout="block">
                        <p:graphicImage id="edit_user_password_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
                        <p:tooltip id="edit_user_password_tooltip_id" for="edit_user_password_tooltip_image_id" value="#{msgs.tooltip_users_password}"/>
                    </h:panelGroup>

                    #{msgs.sending_system}: 
                    <p:selectOneMenu styleClass="edit-user-selectonemenu" id="user_sending_system_id" value="#{usersBean.selectedUser.playerIn}" effectSpeed="fast" filter="true" filterMatchMode="contains" converter="#{playerConverter}">
                        <f:selectItem itemLabel="#{msgs.select_option}" itemValue="#{null}" noSelectionOption="true"/>
                        <f:selectItems value="#{usersBean.players}" var="player" itemValue="#{player}" itemLabel="#{player.description}"/>
                    </p:selectOneMenu>
                    <h:panelGroup layout="block">
                        <p:graphicImage id="edit_user_sending_system_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
                        <p:tooltip id="edit_user_sending_system_tooltip_id" for="edit_user_sending_system_tooltip_image_id" value="#{msgs.tooltip_users_sending_system}"/>
                    </h:panelGroup>

                    #{msgs.receiving_system}:
                    <p:selectOneMenu styleClass="edit-user-selectonemenu" id="user_receiving_system_id" value="#{usersBean.selectedUser.playerOut}" effectSpeed="fast" filter="true" filterMatchMode="contains" converter="#{playerConverter}">
                        <f:selectItem itemLabel="#{msgs.select_option}" itemValue="#{null}" noSelectionOption="true"/>
                        <f:selectItems value="#{usersBean.players}" var="player" itemValue="#{player}" itemLabel="#{player.description}"/>
                    </p:selectOneMenu>
                    <h:panelGroup layout="block">
                        <p:graphicImage id="edit_user_receiving_system_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
                        <p:tooltip id="edit_user_receiving_system_tooltip_id" for="edit_user_receiving_system_tooltip_image_id" value="#{msgs.tooltip_users_receiving_system}"/>
                    </h:panelGroup>

                    #{msgs.active}: <p:selectBooleanCheckbox id="edit_user_active_id" value="#{usersBean.selectedUser.active}"/>
                    <h:panelGroup layout="block">
                        <p:graphicImage id="edit_user_active_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
                        <p:tooltip id="edit_user_active_tooltip_id" for="edit_user_active_tooltip_image_id" value="#{msgs.tooltip_users_active}"/>
                    </h:panelGroup>
                </h:panelGrid>
                <h:panelGroup styleClass="edit-user-main-tooltip" layout="block">
                    <p:graphicImage id="edit_user_main_tooltip_image_id" library="images" name="icon-tooltip.jpg"/>
                    <p:tooltip id="edit_user_main_tooltip_id" for="edit_user_main_tooltip_image_id" value="#{msgs.tooltip_users_edit}"/>
                </h:panelGroup>
                <h:panelGroup styleClass="edit-user-dialog-buttons" layout="block">
                    <p:commandButton id="edit_user_save_button_id" value="#{msgs.save}" action="#{usersBean.updateUser}" onclick="closeDialog('edit_user_dlg')" update=":search_users_form_id:users_table_id"/>
                    <p:commandButton id="edit_user_cancel_button_id" value="#{msgs.cancel}" type="button" onclick="closeDialog('edit_user_dlg')"/>
                </h:panelGroup>
            </h:form>
        </p:dialog>

      

The update method simply takes an object selectedUser

and passes it to the stored procedure.

public void updateUser() {
        logger.entry();
        this.selectedUser.setPlayerInId(this.selectedUser.getPlayerIn().getId());
        this.selectedUser.setPlayerOutId(this.selectedUser.getPlayerOut().getId());
        this.updateUser(this.selectedUser);
        this.clearData();
        logger.exit();
    }

public void updateUser(DtoUser dtoUser) { 
        try {
            logger.entry(dtoUser);
            DtoBoUsers dtoBoUsers = dtoUser.toDtoBoUsers();
            DtoTypeGenericResponse genericResponse = usersService.updateUser(backofficeUserBean.getCurrentSessionId(), dtoBoUsers);
            if (genericResponse.getVResponse().equals(startupBean.getProperty(BackofficeProperties.RESPONSE_NOK))) {
                BigDecimal id = this.selectedUser.getId();
                logger.info(this.users.get(id.intValue()-1));
            } else {

            }
            logger.exit(dtoUser);
        } catch (BackofficeException | RuntimeException e) {
            logger.error(ExceptionUtils.getStackTrace(e.fillInStackTrace()));           
        } 
    }

      

How can I solve this? Should I force repopulate the data again using a DB query? Or do I have a cleaner way to do this?

+3


source to share


1 answer


Basically you update=":search_users_form_id:users_table_id"

only want to execute when the business service call succeeded. You could achieve this by removing this attribute from <p:commandButton>

and executing it programmatically in your action method with RequestContext#update()

.



try {
    // ...
    RequestContext.getCurrentInstance().update("search_users_form_id:users_table_id");
}
catch (Exception e) {
    // ...
}

      

+5


source







All Articles