Monday, April 7, 2008

Automatically save transactions with ADF Taskflow

ADF Taskflow has the option to automatically save all the transactions in bounded critical taskflows. This is called an implicit save. This save action happens when there is a timeout or when the user closes the browser and the transaction is still open. In this blog entry I will show what you have to do to enable this and I will show how you can restore it with a select one choice with the saved transaction. My previous blog give an example for an explicit save. With an explicit save the user decide to save the transaction so he or she can continu the transaction later.
The first step is to edit the adf-config.xml to enable automatically save in bounded taskflows.

<?xml version="1.0" encoding="windows-1252" ?>
<adf-config xmlns="http://xmlns.oracle.com/adf/config"
xmlns:sec="http://xmlns.oracle.com/adf/security/config">
<sec:adf-config-child xmlns="http://xmlns.oracle.com/adf/security/config">
<CredentialStoreContext credentialStoreClass="oracle.adf.share.security.providers.jps.CSFCredentialStore"
credentialStoreLocation="../../src/META-INF/jps-config.xml"/>
<sec:JaasSecurityContext initialContextFactoryClass="oracle.adf.share.security.JAASInitialContextFactory"
jaasProviderClass="oracle.adf.share.security.providers.jps.JpsSecurityContext"
authorizationEnforce="true"
authenticationRequire="true"/>
</sec:adf-config-child>
<adfc-controller-config xmlns="http://xmlns.oracle.com/adf/controller/config">
<savepoint-datasource>jdbc/scottDS</savepoint-datasource>
<savepoint-manager>DATABASE</savepoint-manager>
<savepoint-expiration>86400</savepoint-expiration>
<enable-implicit-savepoints>true</enable-implicit-savepoints>
</adfc-controller-config>
</adf-config>

Now we can create two taskflows the first is unboundend taskflow with the restore savepoint functionality and the second is the bounded taskflow where ADf will save the open transactions. The unbounded taskflow looks like this. Here you see I call the bounded taskflow and I added a savepoint restore component which restores the session with this variable #{pageFlowScope.saveId}. I added also ADF security with the wizard so I only save and restore my own sessions.

The unbounded taskflow looks like this. It is very important to set critical on true else your transactions won't be saved.

The bounded taskflow jsf page has a submit button else the webapp doesn't detect the changes to the record.

We are ready to add the restore functionality to the main page in the unbounded taskflow. For this I use a selectOneChoice with his own saved transactions, I also added a clear transactions button.


<af:panelGroupLayout layout="horizontal">
<af:selectOneChoice label="Savepoints" value="#{pageFlowScope.saveId}">
<f:selectItems value="#{savepoints.savepoints}"/>
</af:selectOneChoice>
<af:commandButton text="Restore" action="restore"/>
<af:commandButton text="Clear savepoints" action="#{savepoints.clearSavepoints}"/>
</af:panelGroupLayout>

I had to use a session bean to fill the selectonechoice, It didn't work with #{controllerContext.savePointManager.listSavePointIds}.

package nl.ordina.bean;

import java.util.ArrayList;
import java.util.List;

import javax.faces.model.SelectItem;
import oracle.adf.controller.ControllerContext;
import oracle.adf.controller.savepoint.SavePointAttributes;
import oracle.adf.controller.savepoint.SavePointManager;

public class Savepoint {

private ControllerContext cc;
private SavePointManager save;

public Savepoint() {
cc = ControllerContext.getInstance();
save = cc.getSavePointManager();
}

public List getSavepoints()
{
List options;
options = new ArrayList();
List saves = save.listSavePointIds();
SelectItem option;
int size = saves.size();
for ( int i = 0 ; i < saves.size() ; i++) {
SavePointAttributes att = save.getSavePointAttributes(saves.get(i));
option = new SelectItem(saves.get(i),saves.get(i)+att.getName());
options.add(option);
}
return options;
}
public String clearSavepoints() {
save.clearSavePoints();
return null;
}
}

Now we are ready to save and restore transactions.
Here you can download the example project Make sure you re-enable the security on the main pagedef else your system-jazn-data.xml isn't updated with the needed permissions.

12 comments:

  1. hi
    i have tried the example for the Save for later functionality in ADF.
    but i am getting following error,
    Can you please help me?

    ReplyDelete
  2. Hi,

    I don't see the error, if it is a xml then please convert it with a html encoder.

    thanks Edwin

    ReplyDelete
  3. sorry i forgot to paste.
    what did, i just deployed your application and when i ran the update.jspx page and i did the some chages in textboxes values on page. And when clicked on back button
    I am getting following error

    oracle.adf.controller.ControllerException: ADFC-00008: The ADF Controller is unable to find DataControlFrame for a task flow.
    at oracle.adfinternal.controller.util.Utils.createAndLogControllerException(Utils.java:208)
    at oracle.adfinternal.controller.util.model.DCFrameImpl.makeCurrent(DCFrameImpl.java:128)
    at oracle.adfinternal.controller.state.ViewPortContextImpl.makeCurrent(ViewPortContextImpl.java:1006)
    at

    ReplyDelete
  4. Ok,

    I will check this in the new JDev. I will keep you updated

    thanks

    ReplyDelete
  5. Hi Edwin,
    can you please reply to my thread,

    http://forums.oracle.com/forums/thread.jspa?threadID=1092315&tstart=0

    ReplyDelete
  6. Hi
    I updated the sample to JDev 11g R1 PS2 ( download it again ) and everything is working fine on my laptop ( also the back button ), just log in as weblogic and edit an emp , submit and close the browser
    open the application again and restore the session.

    thanks Edwin

    ReplyDelete
  7. And can you check if you have the following table oradfcsavpt in your db schema

    and if it contains records

    ReplyDelete
  8. Hi,
    This post helped me a lot thanks for the same.

    I have one doubt.. How can we restore the savepoint on page load,instead of restore button?

    I have been trying to do the same but was unable to do it.can you please help me.

    ReplyDelete
  9. Hi,

    you can do this in the Task Flow. as first action.

    ReplyDelete
  10. Hi Edwin,

    I can see savepoint in database but when I try to select the one and click on restore I am getting oracle.jbo.AlreadyLockedException: JBO-26030: Failed to lock the record, another user holds the lock.

    now if I run the application again it works fine.
    can you give me any idea on this?


    ReplyDelete
  11. Hi nikhil,
    Can you please check lock mode? whether is it optimistc or pessimistic.
    try to keep lock as optimistic.

    ReplyDelete
  12. Thanks Kiran. Issue resolved by checking checkbox for optmistic mode in adf-config.xml

    ReplyDelete