Friday, April 29, 2011

Managed Bean and Backing Bean @ADF

Managed Bean:

1) Represents a Java class which will be created dynamically during runtime of the JSF application. It can be defined for which scope the bean is valid (Session, Request, Application or none).
2) Simple java object which are declared in "faces-config.xml".
3) In JSF you can access the values of a managed bean via value binding.

Backing Bean:  A backing bean defines UI component properties, each of which is bound to either a component's value or a component instance. A backing bean can also define methods that perform functions associated with a component, including validation, event handling, and navigation processing.

If you are configuring a backing bean that is referenced by a component tag's binding attribute, you should define the bean with a request scope. If you placed the bean in session or application scope instead, the bean would need to take precautions to ensure thread safety because UIComponent instances depend on running inside of a single thread.

Binding a component instance to a bean property has these advantages:
           1) The backing bean can programmatically modify component attributes.
           2) The backing bean can instantiate components rather than let the page author do so.

For Ex:  <inputText binding="#{UserNumberBean.userNoComponent}" />

Binding a component's value to a bean property has these advantages:

           1) The page author has more control over the component attributes.
           2) The backing bean has no dependencies on the JavaServer Faces API (such as the UI component classes), allowing for greater separation of the presentation layer from the model layer.
           3) The JavaServer Faces implementation can perform conversions on the data based on the type of the bean property without the developer needing to apply a converter.

For Ex:     <h:inputText id="userNo"   value="#{UserNumberBean.userNumber}"
                 validator="#{UserNumberBean.validate}" />

Monday, April 18, 2011

What Scope to be used @ ADF

Page flow scope: When you need to pass data values between activities within a task flow.

View scope: Recommended for variables that are needed only within the current view activity, not across view activities.

Request scope: Should be used when the scope does not need to persist longer than the current request. It is the only scope that should be used to store UI component information.
Backing bean scope:  Must be used for backing beans in your task flow if there is a possibility that your task flow will appear in two region components or declarative components on the same page and you would like to achieve region instance isolations.

*Because Pageflow, Backing bean and View scope are not standard JSF scope, EL expression must explicitly include the scope to reference bean. For example, to reference the MyBean managed bean from the backing bean scope, your expression would be #{backingBeanScope.MyBean}.

Friday, April 15, 2011

Application Module Custom Methods @ADF

Once we have created the page and bean corresponding to it, its quite easy to Insert Record in the database table referred by EO. Following code can be used to insert the records:

ApplicationModule am = Configuration.createRootApplicationModule(AMName, ConfigName);
ViewObject myVO= am.findViewObject("MyViewObject1");
Row newEmp = myVO.createRow();
myVO.insertRow(newEmp);
newEmp.setAttribute("Ename","Steve");
newEmp.setAttribute("Empno", new Number(1234));
am.getTransaction().commit();

*You can simply write bc4jclient and press ctrl+Enter and Application module code will be generated automatically.

Another important feature is to provide your Application Module as a Webservice. This can easily be done using following line of codes.
Scenario: Suppose you want to provide a service method to find the Employee's year of service.We will create a new method in AM say 'EmpServiceYears'  and will bind the where clause of VO to employees id passed by employee.

public long EmpServiceYears(long empId) {
  ViewObject emps = findViewObject("Employee1");
  emps.setWhereClause("empno = :0");
  emps.setWhereClauseParam(0, new Number(empId));
  emps.executeQuery();
  Row emp = emps.first();
  return emp == null ? 0 : ((Number)emp.getAttribute("YearsOfService")).longValue();
}


After writting code, deploy it as J2EE web service and select the method to include in client interface panel of AM.

Following code can help to find an Entity object based on primary key:


// Custom method in AppModuleImpl.java
public String findServiceRequestStatus(long requestId) {
String entityName = "devguide.model.entities.ServiceRequest";
// 1. Find the entity definition for the ServiceRequest entity
EntityDefImpl svcReqDef = EntityDefImpl.findDefObject(entityName);
// 2. Create the key
Key svcReqKey = new Key(new Object[]{requestId});
// 3. Find the entity object instance using the key
EntityImpl svcReq = svcReqDef.findByPrimaryKey(getDBTransaction(),svcReqKey);
if (svcReq != null) {
// 4. Return the Status attribute of the ServiceRequest
return (String)svcReq.getAttribute("Status");
}
else {
return null;
}
}

To create a new Entity Row:

//Custom method in AppModuleImpl.java
public long createProduct(String name, String description) {
String entityName = "devguide.model.entities.Product";
// 1. Find the entity definition for the Product entity
EntityDefImpl productDef = EntityDefImpl.findDefObject(entityName);
// 2. Create a new instance of a Product entity
EntityImpl newProduct = productDef.createInstance2(getDBTransaction(),null);
// 3. Set attribute values
newProduct.setAttribute("Name",name);
newProduct.setAttribute("Description",description);
try {
// 4. Commit the transaction
getDBTransaction().commit();
}
catch (JboException ex) {
getDBTransaction().rollback();
throw ex;
}
// 5. Access the database trigger assigned ProdId value and return it
DBSequence newIdAssigned = (DBSequence)newProduct.getAttribute("ProdId");
return newIdAssigned.getSequenceNumber().longValue();



To access the Application Module Client Interface in a JSF Backing Bean:


public class YourBackingBean {
public String commandButton_action() {
// 1. Access the FacesContext
FacesContext fc = FacesContext.getCurrentInstance();
// 2. Create value binding for the #{data} EL expression
ValueBinding vb = fc.getApplication().createValueBinding("#{data}");
// 3. Evaluate the value binding, casting the result to BindingContext
BindingContext bc = (BindingContext)vb.getValue(fc);
// 4. Find the data control by name from the binding context
DCDataControl dc = bc.findDataControl("SRServiceDataControl");
// 5. Access the application module data provider
ApplicationModule am = (ApplicationModule)dc.getDataProvider();
// 6. Cast the ApplicationModule to its client interface
SRService service = (SRService)am;
// 7. Call a method on the client interface
service.doSomethingInteresting();
return "SomeNavigationRule";
}
}


To get Application module instance independent of EO or VO::

 /***
     * This method returns the current instance of the session DBTransaction object.
     * The method below is implemented from a Singleton Object for utilitarian purposes.
     */
    public static synchronized DBTransaction getDBTransaction(){
   
       FacesContext ctx = FacesContext.getCurrentInstance();
       ValueBinding vb            = ctx.getApplication().createValueBinding("#{data}");
       BindingContext bc          = (BindingContext)vb.getValue(ctx.getCurrentInstance());
       DataControl dc             = bc.findDataControl("MyApplicationModuleControl");
       ApplicationModuleImpl am   = ((ApplicationModuleImpl)(ApplicationModule)dc.getDataProvider());
      
       return am.getDBTransaction(); 
      
   }


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

What Happens in ADF and Database for New, Update and Delete?

Thursday, April 14, 2011

Some Important Property Attribute @ADF

1) Rendered: this looks an important property attribute. we can use it to make components visible/hidden based on EL expression in it.
For Eg.: If our search result have only one result, then we can remove the Next and Previous buttons. We need to add those button inside a panel container and change its renderes property to

#{bindings.MyIterator.estimatedRowCount >1}

2) FacetName: If we have two facets named 'Found' and 'NotFound' inside switcher, then we can set the facetname to following

#{bindings.TechniciansIterator.estimatedRowCount > 0 ? 'Found' : 'NotFound'}

Bindings Creation at Runtime @ADF

As part of configuring your project for working with Oracle ADF data binding, JDeveloper registers an additional handler that is triggered whenever a client requests a JSP page. This handler is listed in the standard J2EE web application configuration file (web.xml) of your ViewController project. It sets up the correct binding container for the current page based on the related ADF Model XML configuration files, and makes it accessible using the EL expression #{bindings}. During the subsequent handling of the web page request, the JSF standard dictates a predictable set of processing steps known as the page "lifecycle". 


At runtime, multiple objects (i.e., binding context, binding containers, and binding objects) are created in memory to hold binding information. The ADF binding context is a runtime map of all data controls and page definitions within the application. The binding context is the one object that lives in the HttpSession for each end user, accessible using the EL expression #{data}.

The group of bindings supporting the UI components on a page are described in a page definition file. The ADF Model layer uses this file at runtime to instantiate the page's bindings. These bindings are held in a request-scoped map called the binding container, accessible during each page request using the EL expression #{bindings}. This expression always evaluates to the binding container for the current page.



  • Binding Context
    • The binding context provides the data environment for your application. It contains all of the data controls and binding containers that your application can access.
    • The ADF lifecycle creates the ADF binding context from the application module,DataBindings.cpx, and page definition files. Binding context contains references that become data control or binding container objects on demand.
    • You can look up ApplicationModule from a managed bean using the BindingContext:
      BindingContext bc = BindingContext.getCurrent();
      DCDataControl dc = bc.findDataControl("AppModuleDataControl");
      ApplicationModule am = (ApplicationModule)dc.getDataProvider();
    • You can retrieve a ControlBinding named "producerMethod" via BindingContext in this way:
      DCBindingContainer bc = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
      JUCtrlActionBinding actionBnd =
      (JUCtrlActionBinding)bc.getControlBinding("producerMethod");
  • Binding Containers
    • A binding container holds value bindings and iterator bindings (or binding objects) for a page. It provides runtime access to all the ADF binding objects for a page.
At runtime, a web request for http://yourserver/yourapp/faces/some.jsp arrives from the client to the application server. The ADFBindingFilter (defined in web.xml) object looks for the ADF binding context in the HTTP session, and if it is not yet present, initializes it for the first time. If the appropriate binding container for the page has never been used before during the user's session, it is created. Also, if it is the first time an application module data control is referenced during the request, it acquires an instance of the application module from the application module pool. Then the control is forwarded to the page to be rendered. The UI components on the page access value bindings and iterator bindings in the page's binding container and render the formatted output to appear in the browser. Finally, the user sees the resulting page in the browser.

These objects in the ADF model layer provide runtime access to business services:
binding context object ( oracle.adf.model.BindingContext)
Defines a common namespace for use by the client application and allows all model objects to be exposed through a convenient root name. Each web page or Java panel registers with the binding context using the definition for the variable name binding.
data control interfaces ( oracle.adf.model.binding.DCDataControl)
Provides the client application with an interface into the model objects. One data control is needed to wrap the model objects of each business service configuration. Also, in the case of a JavaBeans model object, provides developers with direct access to the native object, when programmatic access is desired.
binding container objects ( oracle.adf.model.binding.DCBindingContainer)
Defines a container for data binding objects, including iterator bindings and control bindings. One binding container is created for each web page or Java panel, but may be reused in multiple pages and panels when they share the same data. The binding container object also lets you specify whether the page or panel is to be used in data entry mode or query mode.
iterator binding objects ( oracle.adf.model.binding.DCIteratorBinding)
Handles the events generated from the associated business service row iterator and sends the current row to individual control bindings to display current data. Iterator bindings can specify the number of rows to display in a web page.
control binding objects ( oracle.jbo.uicli.binding.JUControlBinding)
Defines the way a specific UI component interacts with the corresponding business service. For example, depending upon the control binding selection, a text field may be bound to an Oracle ADF Business Components view object attribute and display as an editable field or a static label. Or, if the business service attribute defines an enumerated list of values, the bound UI component might display a static list, a single-selection list, or a multi-selection list. Other, more complex UI components, such as table and graphs, are also supported by their own control bindings.
action binding objects ( oracle.jbo.uicli.binding.JUCtrlActionBinding)
At runtime, when the user initiates the action, using a button control, the action binding accesses the Oracle ADF binding context and initiates the specified action on the data objects of the selected collection. Action bindings can take parameters that will be passed to the controller to handle.


Random Codes @ADF

1) This method set Resolved Date to current date when status changes to resolved.
    public String EmpMyTasks_SubmitAction() {
        BindingContainer bindings = getBindings();
        DCIteratorBinding itrbinding = (DCIteratorBinding)bindings.get("EmpMyTasksTroubleView1Iterator");
        Row row=itrbinding.getCurrentRow();
        if(row.getAttribute("Status").toString().equals("Resolved"))
        {
          row.setAttribute("Resolveddate", new Date());  
        }
        OperationBinding operationBinding = bindings.getOperationBinding("Commit");
        Object result = operationBinding.execute();
        if (!operationBinding.getErrors().isEmpty()) {
            return null;
        }
        return null;
    }

2) Initialize AssignedDate to current date
      DCIteratorBinding itrbinding = (DCIteratorBinding)bindings.get("TroubleView1Iterator");
      Row row=itrbinding.getCurrentRow();
      System.out.println("Location is"+row.getAttribute("Location"));
      row.setAttribute("Assigneddate", new Date());

3) To add popup with message like welcome or error:

        FacesMessage msg=null;
        FacesContext fc=FacesContext.getCurrentInstance();

        msg=new FacesMessage("Error While Submit");
        fc.addMessage(null, msg);

4) To find task assigned to logged in user

        String troubleassignedto=ADFContext.getCurrent().getSecurityContext().getUserName();
        ApplicationModule appMod =Configuration.createRootApplicationModule("model.BC.App_Mod.AppModule", "AppModulelocal");
        ViewObject troubleview= appMod.findViewObject("EmpMyTasksTroubleView1");
        troubleview.setWhereClause("ASSIGNEDTO =: assignedtoname");
        troubleview.defineNamedWhereClauseParam("assignedtoname", null, null);
        troubleview.setNamedWhereClauseParam("assignedtoname", troubleassignedto);
        troubleview.executeQuery();
        AdfFacesContext fc= AdfFacesContext.getCurrentInstance();
        fc.addPartialTarget(emp_MyTasks_CompBinding);

Class Hierarchy@ADF


SQL Query based View Objects@ADF

while creating the View object based on sql query (read only access) i got two errors:

1) In the query "select * from suppliers where suppliers.supplier_id = :sid" i am getting
Error: missing in or out parameter at index:1
i don't know whts wrng. however just as a work around i used following query "select * from suppliers where suppliers.supplier_id = ?" and it worked.

2) Error: <Utils><buildFacesMessage> ADF: Adding the following JSF error message: Invalid column index java.sql.SQLException: Invalid column index
Solution: I got this error when i created two bind variables that i used in my query from VO->Query tab. The problem was, for first bind variable i used 1 as bind position. However bind position must start from zero (as per developer's logic :) ).

Monday, April 11, 2011

Pass parameter to beam using EL @ ADF

this is a nice article on how to pass parameters to managed bean using EL. Three different options have been specified:

1) Memory attributes, 2) The ADF binding layer, 3) A setter/getter method on a managed bean that sets an internal variable.

http://blogs.oracle.com/jdevotnharvest/2011/04/passing_parameters_to_managed_bean_method_using_el.html