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,
        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();
        System.out.println("Save Point Created: " + spID);

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

    public void removeSavePoint() {
        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"
                          <af:showPopupBehavior triggerType="click"

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"
                 <af:dialog id="d451" type="yesNo" title="Edit Host"
 <af:table value=" ..../>

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) {
        } else {

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

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