Monday, May 30, 2011

Working with JavaScript/Popups @Adf

1) To show popup on page load:  To show popup on page load simply assign clientlistener operation to document element. Chose type as 'load' and create a javascript method as follows:


     function ShowPopupOnPageLoad()
    {
      var popup= AdfPage.PAGE.findComponentByAbsoluteId('p1');
      popup.show();
    }


2) Call JavaScript from Java: We can use our backing bean to call java script as follows:


        StringBuilder script=new StringBuilder();
        script.append("var popup = AdfPage.PAGE.findComponentByAbsoluteId('p1');");
        script.append("if(popup != null) {");
        script.append("popup.show();");
        script.append("}");

        FacesContext fctx=FacesContext.getCurrentInstance();
        ExtendedRenderKitService erks= Service.getRenderKitService(fctx, ExtendedRenderKitService.class);
        erks.addScript(fctx, script);

 
3) Show Popup When Application is Busy: To show a popup when application is busy and prevent input from user in that time we can use following java script functions. In this, a callback method is called when application start getting busy. preventUserInput shows a glass pane to prevent user from interacting with UI. It gets removed automatically when application busy state changes. Also change the content Delivery option of the popup to Immediate.


    function ListenEvent(evt)
    {
      var popup= AdfPage.PAGE.findComponentByAbsoluteId('p2');
      if(popup != null)
      { 
        AdfPage.PAGE.addBusyStateListener(popup,handleBusyState);
        evt.preventUserInput();
      }
    }
    function handleBusyState(evt)
    {
      var popup= AdfPage.PAGE.findComponentByAbsoluteId('p2');
      if(popup != null)
      { 
        if(evt.isBusy())
         popup.show();
      }
      else
      {
        popup.hide();
        AdfPage.PAGE.removeBusyStateListener(popup,handleBusyState);
      }
    }

Sunday, May 29, 2011

Call Java script from Java

Following is a sample code for calling javascript from java:


import org.apache.myfaces.trinidad.render.ExtendedRenderKitService; import org.apache.myfaces.trinidad.util.Service; …

private void writeJavaScriptToClient(String script)
{
  FacesContext fctx = FacesContext.getCurrentInstance();
  ExtendedRenderKitService erks = Service.getRenderKitService(fctx, ExtendedRenderKitService.class);  
  erks.addScript(fctx, script);
}

A popular use case for calling JavaScript from a managed bean is to open a client-side ADF Faces popup dialog, as shown here:

StringBuilder script = new StringBuilder();
script.append( "var popup = AdfPage.PAGE.findComponentByAbsoluteId('p1');");
script.append("if(popup != null){"); script.append("popup.show();"); script.append("}"); writeJavaScriptToClient(script.toString());

Tuesday, May 24, 2011

Delete Rows using Managed Bean @ADF

In order to delete rows using managed bean that has component binding set for Table component, we can use a delete button with partial submit set to true and actionlistener property invoking the bean with following code:

public void onDelete(ActionEvent actionEvent) {
//access the RichTable from the JSF component binding
//created for the table component
RichTable _table = this.getTable1();
RowKeySet rks = _table.getSelectedRowKeys();
//iterate over the set of selected row keys and delete
//each of the found rows
Iterator selectedRowIterator = rks.iterator();
while (selectedRowIterator.hasNext()){
//get the first key
Object key = selectedRowIterator.next();
//make the row current
_table.setRowKey(key);
//the row is an instance of the ADF node binding class
JUCtrlHierNodeBinding rowWrapper = null;
rowWrapper = (JUCtrlHierNodeBinding) _table.getRowData();
//get the actual oracle.jbo.Row object
Row row = rowWrapper.getRow();

row.remove();
}
//partially update the ADF Faces Table
AdfFacesContext adfFacesContext = AdfFacesContext.getCurrentInstance();
adfFacesContext.addPartialTarget(_table);
}
However this is simple but not recommended always. Another way is to create delete method in View Object Impl taking list of keys as input and use managed bean returning that list as input parameter to that method. This can be done by droping the method in viewobjectimpl as action and then use the expression builder to refer the managed bean as input parameter.

View Object Impl code:

public void processEmployeeBulkDelete(List employees){
if (employees != null){
for (Object employee : employees) {
Key k = (Key)employee;
Row[] rowsFound = this.findByKey(k,1);
//if the key returns more than one row then the provided
//key obviously is not unique. Ignore in this sample
if (rowsFound != null && rowsFound.length == 1) {
//get the first entry in the array of rows found
Row employeeRow = rowsFound[0];
employeeRow.remove();
}
}
}
}

Managed Bean Code:


public List getSelectedAdfRowKeys() {
List<Key> retVal = new ArrayList<Key>();
//get the selected row keys from the table instance
for (Object rowKey : employeesTable.getSelectedRowKeys()) {
//make the row the current row
employeesTable.setRowKey(rowKey);
Object o = employeesTable.getRowData();
//table rows are represented by the JUCtrlHierNodeBinding
//binding class
JUCtrlHierNodeBinding rowData = (JUCtrlHierNodeBinding)o;
//add the row key to the list
retVal.add(rowData.getRow().getKey());
}
return retVal;
}
//JSF component binding of the table
public void setEmployeesTable(RichTable employeesTable) {
this.employeesTable = employeesTable;
}
public RichTable getEmployeesTable() {
return employeesTable;
}

Now drag the processEmployeeBulkDelete method entry from the Data Controls panel to the page and choose a command action component. Now we can refer getSelectedAdfRowKeys as the input component to the method.

Monday, May 23, 2011

Override af:dialog default Buttons @ADF


To allow the dialog’s OK, Yes, or No button to perform an operation such as a commit or rollback, you use a dialog listener. For example, the following pop-up dialog includes a backing bean method for handling when the pop-up is canceled via the Cancel button or close icon (popupCanceledListener) or the dialog is closed via the OK button (dialogListener):


<af:popup contentDelivery="lazyUncached"
popupCanceledListener="#{DialogBean.handlePopupCancel}">
<af:dialog dialogListener="#{DialogBean.handleDialogClose}">
<!-- Input form defined here -->
</af:dialog>
</af:popup>


The backing bean implements the handlePopupCancel and handleDialogClose methods, as shown in the following code sample. Note that to determine which button was clicked, the handleDialogClose method uses the getOutcome method of DialogEvent.

public void handleDialogClose(DialogEvent dialogEvent) {
if (dialogEvent.getOutcome().equals(DialogEvent.Outcome.ok)) {
BindingContext bindingctx = BindingContext.getCurrent();
BindingContainer bindings = bindingctx.getCurrentBindingsEntry();
OperationBinding operationBinding =
bindings.getOperationBinding("Commit");
Object result = operationBinding.execute();
}
}
---

public void handlePopupCancel(PopupCanceledEvent popupCanceledEvent) {
BindingContext bindingctx = BindingContext.getCurrent();
BindingContainer bindings = bindingctx.getCurrentBindingsEntry();
OperationBinding operationBinding =
bindings.getOperationBinding("Rollback");
Object result = operationBinding.execute();
}

Tuesday, May 10, 2011

Entity Object Custom Codes @ADF

Key Entity Objects Features and Events for Programmatic Business Logic


As Entity Object are supposed to be reused in many Application Modules, so they should not depend directly on a View Object Instance in any specific app module data control.To avoid this, entity object can use current application module instance's createViewObject() to create an instance of VO it requires.
Following code show how to access View object for validation.


// Sample entity-level validation method
public boolean validateSomethingUsingViewObject() {
Number numVal = getSomeEntityAttr();
String stringVal = getAnotherEntityAttr();
// Get the view object instance for validation
// Create a new name for the VO instance being used for validation
String name = "Validation_" + viewObjectDefName.replace('.', '_');
// Try to see if an instance of this name already exists
ViewObject vo = getDBTransaction().getRootApplicationModule()
.findViewObject(name);
// If it doesn't already exist, create it using the definition name
if (vo == null) {
vo = getDBTransaction().getRootApplicationModule()
.createViewObject(name,viewObjectDefName);
}
// Set it's bind variables (which it will typically have!)
vo.setNamedBindWhereClauseParam("BindVarOne",numVal);
vo.setNamedBindWhereClauseParam("BindVarTwo",stringVal);
vo.executeQuery();
if ( /* some condition */) {
/*
* code here returns true if the validation succeeds
*/
}
return false;
}

..............................
Reference: Developer’s Guide For Forms/4GL Developers

Saturday, May 7, 2011

Adding View Criteria @ADF

Following are the line of codes that can be used to add view criteria programmatically  in an application:


ApplicationModule am = Configuration.createRootApplicationModule(UserAppMod,UserAppModLocal);
ViewObject vo = am.findViewObject("User");
// 1. Create a view criteria rowset for this view object
ViewCriteria vc = vo.createViewCriteria();
// 2. Use the view criteria to create one or more view criteria rows
ViewCriteriaRow vcr1 = vc.createViewCriteriaRow();
ViewCriteriaRow vcr2 = vc.createViewCriteriaRow();
// 3. Set attribute values to filter on in appropriate view criteria rows
vcr1.setAttribute("UserId","> 304");
vcr1.setAttribute("Email","d%");
vcr1.setAttribute("UserRole","technician");
vcr2.setAttribute("UserId","IN (324,326)");
vcr2.setAttribute("LastName","Baer");
// 4. Add the view criteria rows to the view criteria rowset
vc.add(vcr1);
vc.add(vcr2);
// 5. Apply the view criteria to the view object
vo.applyViewCriteria(vc);
// 6. Execute the query
vo.executeQuery();
while (vo.hasNext()) {
Row curUser = vo.next();
System.out.println(curUser.getAttribute("UserId") + " " +
curUser.getAttribute("Email"));
}
Configuration.releaseRootApplicationModule(am, true);

Thursday, May 5, 2011

JSF Page Life Cycle

Following are the steps involved in JSF page life cycle.

The life cycle handles both Initial and Postback event.(For a page having input text field with value coming fron a bean say #{bean.name}, then Initial request is the request that the browser does in order to display the page with the ${bean.name} tag and Postback happens when the browser posts some or all page values and then the same page that was posted in the first place is returned to the client). When the life cycle handles an initial request, it only executes the restore view and render response phases because there is no user input or actions to process. Conversely, when the life cycle handles a postback, it executes all of the phases.

1) Restore View Phase: Begins when a link or button is clicked.the JSF implementation builds the view of the page, wires event handlers and validators to components in the view, and saves the view in the FacesContext instance.
For Initial request JSF creates an empty view and phase changes to Render response phase. The empty view will be used when page is processed during postback request.
For postback request, a view corresponding to page already exists. The JSF implementation restore the view by using state information saved on client or server.

Phase Result: Component Tree created/restored.

2) Apply Request value phase: Each component in the tree extract its value from decode method. The decode method looks like:
public void decode(FacesContext context, UIComponent component) {
       /* Grab the request map from the external context */
     Map requestMap = context.getExternalContext().getRequestParameterMap();
       /* Get client ID, use client ID to grab value from parameters */
     String clientId = component.getClientId(context);
     String value = (String) requestMap.get(clientId);

     FieldComponent fieldComponent = (FieldComponent)component;
       /* Set the submitted value */
     ((UIInput)component).setSubmittedValue(value);

}
The value is then stored locally on the component. If the conversion of the value fails, an error message associated with the component is generated and queued on FacesContext. This message will be displayed during the render response phase, along with any validation errors resulting from the process validations phase.

Phase Result: The components are set to their new values, and messages and events have been queued.

3) Process Validation Phase: All the validators registered on the component are processed in this phase. These rules are implemented on the local values stored. If local value is invalid, then error message is added to facescontext and phase changes to render phase. If events have been queued during this phase, the JavaServer Faces implementation broadcasts them to interested listeners.

Phase Result: Ensure that the data is valid.

4) Update Model Value Phase: This phase set the object properties to local values. JSF implementation updates only the bean properties pointed at by input component value attribute. If local data can't be converted to type specified by bean propeties and error message is added to facescontext and phase chages to render phase.

Phase Result: The properties of the bean are set to the local variable of the UI component.

5) Invoke Application Phase: This phase deals with invoking application level events like submitting forms or redirecting to other page. While processing redirecting event, if any, a default ActionListener implementation retrive the outcome from component action attribute and passed the outcome to default NavigationHandler. The JSF implementation then set view to new page as per the navigation rule.Otherwise, JSF implementation passes control to render phase.

Phase Result: Change of view in case of any navigation or application's invoke.

6) Render Response Phase: The JSP container is now assigned the authority to render the jsp pages.
If the request is Initial request, the components represented on the page will be added to the component tree as the JSP container executes the page.
If the request is a postback and errors were encountered during the apply request values phase, process validations phase, or update model values phase, the original page is rendered during this phase. If the pages contain message or messages tags, any queued error messages are displayed on the page.
After the content of the view is rendered, the state of the response is saved so that subsequent requests can access it and it is available to the restore view phase.

Phase Result: You have what you want to see :).

The Life cycle of a Page Request in an ADF Application Using ADF Faces Components:


Tuesday, May 3, 2011

Contextual Event @ADF

Below article will help to get some concept about how contextual events work.

af:region tag has a property that require pointer to region model which determine the current View to be displayed. The region model is exposed by bounded task flow through a specific task flow binding added to the page definition file of the page that contains the af:region tag.
Contextual event is functionality of binding layer. The communication allows to pass message object from a producing event to a listening method.

The Event Producer can be defined by event binding element that we declaratively create in page definition file of the page that contains the component region event or the event producer can be defined on the attribute binding that either listen for value change or for currency change if user select different row in table. A producer has a name that identify producer when it map to listening part and optionaly it may have a custom payload defined which over write the native event that is passed by default. The producer consis of a Rasie condition that specify when the event should be raised. The DCBindingContainerValueChangeEvent is native event object for all adf boud input field component.

The Event Consumer is a method that we expose in adf binding layer, that means exposes in data control, that means either in VO or AM. This methos may have zero, one or multiple argument. Once we have a method binding defined on a page definition file of the view that is suppose to listen for the produced event then we can use it for the dispatched event.

Now once we have producer event and consumer method, its time to bind them together. We do this using adf binding medium. The task flow binding is a binding container. The page definition file of the view exposing the bounded task flow is also a binding container. The page definition file of the parent page that contains the region also represent a binding container.Now the parent page binding container has a refrence to task flow binding which has a refrence to the container used by the fragment of the page fragment. So we have heirarchy like tree of conncted active container that we can use the binding layer to navigate to or point to. This is what the dispatching does. Dispatchnig has the ability to connect an event producer in an active binding container with an event listner in an active container.

When an event is first raised it is propogated to local container which also has refrence to component rasing the event. On that container it will looke for the event method. If that event method is available then event will be propagted. Else, next it goes to parent container and looks for event method and continues this way till it reaches the top most binding container.On its way up it broadcat the event to all named producer configuration. Then on the way back it broad cast the event to all the other active binding container that are not directly in the parent chain of raising event. 

Hmmm...enough theory its time for some hands on..Good Luck!!!!

*Please don't forget to post any correction, as i am also a newbie :) ....

Display message on Login @ADF

This is a simple way of displaying message when a user login (if validating using backing bean).

1) Drag and drop a Message component on the page.
2) Under the action listener method of the login button add following code
          FacesMessage msg=null;
          FacesContext fc=FacesContext.getCurrentInstance();
    If login successful :
          msg= new FacesMessage("Welcome");
          fc.addMessage(null,msg);
   If login failed:

          msg= new FacesMessage("Invalid Username/Password");
          fc.addMessage(null,msg);
3) Now just run the app and test.