Tuesday, March 17, 2015

ADF: Partial Rollback

Recently I developed a page where I provided edit functionality for a table row in a Popup with Dialog having Save/Cancel buttons.

If user add/edit/remove row and click Save, the data is getting saved. And if user clicks on Cancel button, the updated data/action inside popup needs to be revert back, but its not happening. af:resetActionListener won't help.

Initially I thought of execute rollback when user clicked on Cancel button, but it impacts other changes in the page. So I tried below steps to perform partial rollback to revert only changes done in Popup. Here I used similar save point concept explained in Link.

1. Add following methods to Bean class to create/restore/remove save point.

    public static DCBindingContainer getDCBindingContainer() {
        return (DCBindingContainer)getBindingContainer();
    }

    public static BindingContainer getBindingContainer() {
        return (BindingContainer)resolveExpression("#{bindings}");
    }

    public static Object resolveExpression(String expression) {
        FacesContext facesContext = getFacesContext();
        Application app = facesContext.getApplication();
        ExpressionFactory elFactory = app.getExpressionFactory();
        ELContext elContext = facesContext.getELContext();
        ValueExpression valueExp =
            elFactory.createValueExpression(elContext, expression,
                                            Object.class);
        return valueExp.getValue(elContext);
    }

    public static FacesContext getFacesContext() {
        return FacesContext.getCurrentInstance();
    }

    public void createSavePoint(ActionEvent actionEvent) {
        DCBindingContainer bindingContainer = getDCBindingContainer();
        DCDataControl dcDataControl = bindingContainer.getDataControl();
        String spID = (String)dcDataControl.createSavepoint();
        AdfFacesContext.getCurrentInstance().getPageFlowScope().put("spID",
                                                                    spID);
        System.out.println("Save Point Created: " + spID);
    }

    public void restoreSavePoint() {
        String spID =
            (String)AdfFacesContext.getCurrentInstance().getPageFlowScope().get("spID");
        DCBindingContainer bindingContainer = getDCBindingContainer();
        DCDataControl dcDataControl = bindingContainer.getDataControl();
        dcDataControl.restoreSavepoint(spID);
        System.out.println("Save Point Restored: " + spID);
    }

    public void removeSavePoint() {
        AdfFacesContext.getCurrentInstance().getPageFlowScope().put("spID",
                                                                    null);
        System.out.println("Save Point Removed");
    }

2. Add button and call createSavePoint method when clicked on it. Since popup and also actionListener to be called at same time, set the showPopupBehaviour's TriggerType as Click.

     <af:commandButton text="Edit" id="cbj4"
                                       partialSubmit="true"
                                      actionListener="#{pageFlowScope.editBean.createSavePoint}">
                          <af:showPopupBehavior triggerType="click"
                                                popupId="editPop"/>
      </af:commandButton>

3. Set ContentDelivery of the af:popup to lazyUncached to display value from the base attribute. Set af:dialog 'type' as 'yesNo' and 'closeIconVisible' to 'false'.Add dialogListener method to listen to actions from Dialog.

      <af:popup id="editPop"
                  contentDelivery="lazyUncached"
                 <af:dialog id="d451" type="yesNo" title="Edit Host"
                                   dialogListener="#{pageFlowScope.editBean.editDialogListener}"
                                   closeIconVisible="false"
                                   affirmativeTextAndAccessKey="Save"
                                   noTextAndAccessKey="Cancel">
 <af:table value=" ..../>
        </af:dialog>
     </af:popup>

4. Add following Dialog Listener method to Bean class to call restore/remove save point methods based on dialog action.

  public void editDialogListener(DialogEvent dialogEvent) {
        Outcome outcome = dialogEvent.getOutcome();
        System.out.println("Outcome: " + outcome);
        if (outcome == Outcome.yes) {
            removeSavePoint();
        } else {
            restoreSavePoint();
        }
    }

5. Add Dialog component id to table's Partial trigger property to refresh when Save/Cancel performed.

   <af:table partialTriggers="d451" value=" ..../>

1 comment:

  1. Hi,

    JDeveloper Version: Studio Edition Version 12.2.1.2.0

    Requirement: I have a popup which implements the concept of partial rollback on cancel button click. In that popup I have a radio button with value as Y or N. Now when user click on Y than there is an input text field which become editable. When user click on N the same input text will clear all the value and will become disabled.

    Now lets assume when the popup opens there radio button value is Y and there is some value in the input text. Now the user select N as the radio button value due to which the input text data gets cleared off and becomes disabled.

    Now the user decided to cancel the changes and clicks on Cancel, which in turn closes the popup.

    Next time when user opens the popup, he can see all the data is reverted to that savepoint. Mean the radio button value is Y and the input text has some value in it.

    But the problem is , though the radio button value is Y, but still the input text field is showing as disabled.

    Please note i tried printing the value that is set as the disabled condition and it returns false, but still the input text field is disabled.

    Thanks & Regards,
    Susanto

    ReplyDelete

Provide your thoughts !