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: