Thursday, June 9, 2011

Random ADF Notes

* If request couldn't be satisfied by ADF navigation handler, it will pass to JSF navigation handler, if a navigation case matches, current view will be changed by call to FacesContext.setViewRoot(). A null outcome value will never match any navigation rule, current view will be redisplayed.
  ADF navigation handler is: oracle.adfinternal.controller.application.NavigationHandlerImpl extends javax.faces.application.NavigationHandler
  code:
  FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(ctx, fromAction, outcome);

 
 * ADF bounded task flows could pass parameters when call another bounded task flow, can also define listeners to intercept before/after task flow call, refer to task flow call property inspector in Jdeveloper.


 * adfc-config.xml file
  1. bootstrapping config file for unbounded task flow, not define convertor, validators, language settings, they are still in the standard faces-config.xml file.
  2. can have multiple such file, in WEB-INF or META-INF of the ADF library files. Pay attention to ensure there's no naming conflicts.

 
 
  * adf-settings.xml file
  1. shared config file in .adf\META-INF directory
  2. multiple such files will be merged to a single file at runtime

 
  * f:view, jsp:root
  1. page fragments (file extention ".jsff") use jsp:root as first markup element, can be embedded in a page using "jsp:include" inside a "f:subview" element
    eg:
  2. recommendation on how to include page fragments: use ADF region to reference a bounded task flow which contains these page fragments, these fragments could have own page definition.
 
 
View Activity
* input-page-parameter
  in page flow def file (note that the view id must not configured as redirect, otherwise the input param will not work, i.e. can't change postback to redirect):
  ... 
        /Page2.jspx
       
         #{requestScope.message}
         #{Page2Bean.txtValue}
       

      
...
  in page2.jspx, can display message as following:
 
  Assume page2 is navigated from page1 via a button click:
 
 
 
  Note that the prop listener here will set the value to requestScope instead of the managed bean which is used more often.
* bookmark
  Optional property for view activities in unbounded task flow. Default behaviour of JSF is that page don't show their request URL, so couldn't bookmark it. Adding this bookmark property will show the URL.
 
      
 

 
      function setBookmark(evt){
        evt.cancel();
        var agentName = navigator.userAgent.toLowerCase();
        if(agentName.indexOf("msie")!=-1) window.external.AddFavorite(document.URL,document.title);
        else
            alert("Press Ctrl+D to bookmark this page");
    }
 


 
* redirect
  set redirect flag to true will change the page request type from postback to redirect

 
Method Call Activity
* return-value
  Optional, but could save the return value in somewhere for future use, eg: #{pageFlowScope.message}

 
Task Flow Call Activity
* task-flow-reference
  this can be dynamically bind to EL expression, the value must be type TaskFlowId, eg: ... public TaskFlowId getDynamicTaskFlowId(){ return TaskFlowId.parse("/WEB-INF/...xml#taskflow-def";}   ...

 
* remote-app-url
  Call a task flow on a remote server
  http://foo-server:7101/deptedit/faces/adf.task-flow?, can suppress the splash screen using skinning:
  af|document::splash-screen{display:none;}

 
 * input-parameter, before-listener, after-listener
  nothing special
* run-as-dialog
  If set to true, will shown the taskflow in pop-up window (either inline or external window).
  The "return-value-definition" could set the return value to a managed bean attribute and then refresh the page. To refresh the page, need to add a reutrn event listener that triggered this task flow call, eg: (there's also launchListener) In return listener method, use adfCtx.adPartialTarget to refresh the field. The scenario for this could be pop up a window to for user to choose a value from.

ADF Specific Scopes:
1) View Scope
View Scope stores objects used by a single page adn retains the objects as long as the user works within the page
2) PageFlow Scope
exist for the duration of a task flow, after which the allocated memory is released. If task flow calls another bounded task flow, then the pageFlow scope of the caller flow is suspended and activated again upon return from the called task flow. The pageFlow scope of the called task flow is not available until after the JSF "Restore View" phase.
3) Backing Bean Scope
Special case of request scope narrowed down to a specific managed bean instance.

Customizing Lifecycle for Operation, Method and Router Activities
*Developers who want to customize the ADF lifecycle for non-view activities can do this by referencing a custom lifecycle class that implements the RegionController interface from the ControllerClass property of the associated page definition file.



Task flow state tracking
* Do this by automatically adds the _adf.ctrl-state request parameter



ControllerContext
* Provide per-request information abt the controller state for a web application. Use .getInstance() to get the context which includes: ViewPortContext (current view rendered in a browser window, a modal dialog or a region); Global ViewActivity URL (url of a view activity in an unbounded task flow); local view activity url; task flow url; view activity view id; savepoint restore url.



Save Points(SP) (SP created by use or application logic is called explicit SP, if by ADF framework for task flow marked as critical is called implicit SP)
* No state from default scopes such as request,session or application is persisted.
* SavePointManager: use ControllerContext.getInstance().getSavePointManager().  Developer then could create/remove/access the SavePoint using the manager's methods.
* Save Point feature is not enabled by default, need to change adf-config.xml to enable this.
* enable-implicit-savepoints: if set true, enables implicit save points being created by framework. Save points are set for the entire stack if one of its bounded task flow is marked as critical. Note that need to setup jndi db connection to use save point feature.
* single save point is created for a user that repeatedly create explicit save points within the same browser window and session. SP are deleted when top level bounded task flow is exited or in the case of implicit save points, the lowest task flow that is marked as critial is exited. Not all SP are automatically deleted from DB, Oracle recommends application developers to implement a strategy, a script or application code, to frequently delete obsolete save points from DB.
* could create own customized SavePointListener implements SavePointListener. Create services folder and create listener text file, will be loaded during startup




Execute Binding operations:
  ...
  BindingContext bindingCtx = BindingContext.getCurrent();
  BdiningContext bindings = bindingCtx.getCurrentBindingsEntry();
  OperationBinding setCurrentRowWithKey = bindings.getOperationBinding("setCurrentRowWithKey");
  setCurrentRowWithKey.getParamsMap().put("rowKey",rowKey);
  setCurrentRowWithKey.execute();
  ...

 
 
Obtain request URL of a view activity
1) String viewId = ControllerContext.getInstance().getCurrentViewPort().getViewId(); String url = ControllerContext.getInstance().getGlobalViewActivityURL(viewId);
2) String viewId = "/hello"; String url = ControllerContext.getInstance().getGlobalViewActivityURL(viewId);
* Note that AdfcIllegalArgumentException is thrown if viewId is not contained in the ubounded task flow. Developer need to ensure or handle this.

Multiple unbounded task flow definitio files are merged into a single file at runtime.

Use #{controllerContext.currentViewPort.taskFlowContext} to get the TaskFlowContext. Upon exiting a bounded task flow, Oracle Controller calls the release() method on the context to free the DataControl resources used by the task flow.




Bounded Task Flow
* template-reference: allow bounded task flow to be created from templates. For example, all bounded task flows should have a view to handle exceptions, this could be made a part of the template.
* data-control-scope: determines whether bounded task flow uses a shared data control frame or its own, isolated data control frame. The latter creates a new application module connection. The default setting is shared.
* initializer: managed bean method reference invoked when the bounded task flow is entered. finalizer: mgd bean method ref invoked when bounded task flow is exited by a return activity or exception.
* Critical: Indicate framework to create an implicit save point when exiting a bounded task flow. Also helps to prevent users from closing the browser window or brower tab if unommitted data is present.
* no-save-point: if critical is set, an ADFm save point is set when entering a task flow. This allows the rollback of any data chagnes upon exiting the task flow. Unlike task flow save point, ADFm save point doesnot restore viewFlowScope and pageFlowScope states.
* allow/disallow reentry: (this is unlike the ReentryLock in multithreadding) it's whether allow the browser's back button re-enter the bounded task flow




Get exception data (In exception handler mgd bean):
* Exception e = ControllerContext.getInstance().getCurrentViewPort().getExeptionData();...



To register an Custom Exception Handler
1) Create class that extends from AdfcExceptionHandler eg: public class CustomExceptionHandler extends AdfcExceptionHandler{... //or extends ExceptionHandler
2) register it in a text file named oracle.adf.view.rich.context.ExceptionHandler, put in folder .adf/META_DATA/services



Open bounded task flow in dialog
1) Open in external window browser window: Must use .jspx file extension. Cannot be changed to run in lightweight dialogs
2) Open in lightweight dialog: appear on top of the current page. Developers use ADF regions to add a bounded task flow to display in a lightweight dialig. Use this option to avoid pop-up blockers. It's more commonly used.

On dialog return listener:

* public void onDialogReturn(ReturnEvent returnEvent){
    System.out.println(returnEvent.getReturnValue());
  }

 
 
Navigate programmatically among view activities:
* ControllerContext.getInstance().getCurrentViewPort().setViewId("Employee");  //Ensure "Employee" is a valid view id in current task flow otherwise an exception is thrown.




Restore save point:
1) via save-point-restore declarative way:
   #{pageFlowScope.this_save_point}
2) via programming way:
   String restoreURL = AdfFacesContext.getCurrentInstance().getSavePointRestoreURL("savePoint1");
   FacesContext ctx = FacesContext.getCurrentInstance();
   ctx.getExternalContext().redirect(restoreURL);
   ctx.responseComplete();


 
 Create/Restore Data Control Save Point
* Create:  BindingContext bctx = BindingContext.getCurrent(); String sph = (String)bctx.findDataControl("HRAppLocal").createSavePoint();...
* Resotre: ... bctx.findDataControl("HRAppLocal").restoreSavepoint(sph);...
Protected by Copyscape Unique Content Check