Friday, May 6, 2011

Bit #30 - Displaying the current row on an af:table

You can display the current record number as you navigate an af:table by using certain information available on the table's iterator binding, namely the currentRowIndexInRange and rangeStart attributes. The current row can be calculated by the following EL expression: #{bindings.Iterator.rangeStart+bindings.Iterator.currentRowIndexInRange+1}, where Iterator is the table's bound iterator identifier. We add one because the row index is 0-based. You will need to surround the af:table with an af:panelCollection and use one of its facets - I suggest using the secondaryToolbar facet - to add an af:toolbar with an af:outputText inside it. For the current record count to be updated as you navigate the table, you will need to setup a partialTrigger on the af:outputText to the af:table. The example below shows this implementation.

Example:

<af:panelcollection ... >
<af:table id="tbl1" ... >
  </af:table>

    <f:facet name="secondaryToolbar">
      <af:toolbar id="t1">
        <af:group id="g1">
          <af:outputtext id="ot24" value="#{bindings.Employees1Iterator.rangeStart+bindings.Employees1Iterator.currentRowIndexInRange+1}/#{bindings.Employees1Iterator.estimatedRowCount} records">
                                         visible="#{bindings.Employees1Iterator.currentRow ne null}"
                                         partialTriggers="tbl1 ::qryId1"/>
        </af:group
>
      </af:toolbar>
    </f:facet>
  </af:panelcollection>

Here is what the output looks like:


Context:

JSF page

Thursday, March 24, 2011

Bit #29 - Dynamically configure ADF trace logs in WebLogic

ADF-specific logging can be dynamically configured in WebLogic via the wlst script. Ensure that you run the wlst script that is located in oracle common directory (and not the one in the WebLogic server home). Then connect to the administration server and use the setLogLevel() command to change the appropriate logger's level. To configure Business Components logs specify oracle.jbo as the logger. Similarly to configure the ADF Controller and ADF Faces logs use the oracle.adf.controller and oracle.adf.faces loggers respectively. For the example below, the ADF application is deployed on ManagedServer1. As mentioned, these changes to the logging configuration can be done at run-time without the need to re-start the server.


Example:

wlst
connect('weblogic','weblogic1', 't3://192.168.5.134:7001')
setLogLevel(target='ManagedServer1', logger='oracle.jbo', level='FINEST')


Context:

ADF BC
ADF Faces
ADF Controller


References:

http://jdeveloperfaq.blogspot.com/2011/03/faq-33-how-to-configure-adf-diagnostics.html

Tuesday, December 14, 2010

Bit #28 - Using findDefObject() to load a BC definition object from its metadata XML

If you ever thought of parsing any of the ADF Business Components (BC) metadata XML files for the sake of extracting various metadata information, you might want to think twice. The ADF framework offers higher level APIs to do this routine job. Case in point: take a look at the findDefObject() methods available in a number of definition classes such as oracle.jbo.server.EntityDefImpl and oracle.jbo.server.ViewDefImpl for example. By calling this method, the metadata is parsed and loaded for you into the corresponding EntityDefImpl or ViewDefImpl. Neat! Then extracting metadata information is as easy as calling the corresponding methods. For example, to get all the attributes defined for a View Object, you can call ViewDefImpl.getAttributeDefs(). When calling findDefObject() ensure that the location of your BC definition files is listed in the class path. Here is an example:

Example:

import oracle.jbo.AttributeDef;
import oracle.jbo.server.AttributeDefImpl;
import oracle.jbo.server.EntityDefImpl;
import oracle.jbo.server.ViewDefImpl;


public class ADFMetaDataTester {

    public static void main(String[] args) {

      // load EO definition from Employee.xml
      EntityDefImpl eoDef = EntityDefImpl.findDefObject("Employee");
      // now, you can for example get the unique keys defined by the EO
      AttributeDefImpl[] uniqueKeys = eoDef.getUniqueKeys();

      // load VO definition from EmployeesVO.xml
      ViewDefImpl  voDef = ViewDefImpl.findDefObject("EmployeesVO");
      // get the VO attributes
      AttributeDef[] attributes = voDef.getAttributeDefs();
    }
}


Context:

ADF Business Components (BC)

Wednesday, November 24, 2010

Bit #27 - Setting a View Object attribute's Queryable property

Expanding on Bit #26 - Overriding getAttributeDef() to conditionally set an attribute property, you can set a View Object's attribute queryable property simply by calling setQueriable() on its ViewAttributeDefImpl. As explained in Bit #26, you can get the AttributeDef attribute definition by calling getAttributeDef() and passing the attribute index as a parameter. In order to call any of the attribute set...() methods, you will have to cast the AttributeDef interface to an ViewAttributeDefImpl implementation. By the way, did you know that by setting an attribute's queryable property will show or hide a View Criteria Item (i.e. the criterion) based on the attribute on the af:query dialog? Another way to hide the criterion was outlined in Bit #25 - Hiding a View Criteria item based on some condition. It will also show or hide the attribute from the Add Fields drop-down in the Advanced mode of af:query. One last thing: check-out the plethora of set...() methods available in the ViewAttributeDefImpl. As you may have guessed it, pretty much everything that is available declaratively on the Edit Attribute dialog, can be set (or reset) dynamically in your code based on some business condition. For a complete use case, check out the reference listed below.

Example:

  /**
   * Helper to set an attribute's queriable property.
   * Example:
   *    setQueriable(ViewRowImpl.SOMEFIELDINDEX, something.equals(somethingElse));
   *
   * @param attribIndex the attribute index
   * @param condition the condition (true/false)
   */
  protected void setQueriable(int attribIndex, boolean condition) {
      // set the attribute queryable as needed
      AttributeDef def = super.getAttributeDef(attribIndex);
      boolean queryable = condition;

      // set/reset queriable only if needed
      if (def != null && def.isQueriable() != queryable) {
          ViewAttributeDefImpl attributeDef = (ViewAttributeDefImpl)def;
          attributeDef.setQueriable(queryable);
      }
  }


Context:

View Object Implementation Class

References:

http://dstas.blogspot.com/2010/03/set-queryable-property-on-attribute.html

Tuesday, November 23, 2010

Bit #26 - Overriding getAttributeDef() to conditionally set an attribute property

You can override ViewObjectImpl's getAttributeDef() method to update an attribute setting, control hint or a custom property. getAttributeDef() is called by the framework each time the attribute's definition needs to be accessed, for example prior to opening an af:query search dialog. In such a case, this may be the ideal place to set a conditional queryable property for example. The argument that is passed to the method indicates the index of the attribute being accessed. You modify the attribute definition by calling super.getAttributeDef() to get the AttributeDef and then call any of its set...() methods. Here is an example:

Example:

   @Override
   public AttributeDef getAttributeDef(int attribIndex) {
        // check for some specific attribute

        if (attribIndex == SOME_ATTRIBUTE_INDEX) {
                //get the attribute's definition
               AttributeDef def = super.getAttributeDef(attribIndex);

               // conditionally update some attribute value

               // if (someCondition) {
               //((ViewAttributeDefImpl)def).set...()

               //}

               return def;
        }

        return super.getAttributeDef(attribIndex);
   }


Context:

View Object Implementation Class

Monday, November 22, 2010

Bit #25 - Hiding a View Criteria item based on some condition

You can hide or show a View Criteria item (i.e. a criterion), based on some business logic condition by calling setProperty() on an oracle.jbo.ViewCriteriaItem. The method accepts a ViewCriteriaItemHints parameter indicating the view criteria item property to set - in this case CRITERIA_RENDERED_MODE - and a second ViewCriteriaItemHints parameter indicating the property value - in this case any of the CRITERIA_RENDERED_MODE_BOTH, CRITERIA_RENDERED_MODE_BASIC, CRITERIA_RENDERED_MODE_ADVANCED, CRITERIA_RENDERED_MODE_NEVER, CRITERIA_RENDERED_MODE_DEFAULT. To hide or show a criterion, you will have to look for it by iterating through all the criteria rows and all the criteria items for each row. Once found, call setProperty() to set its render mode. Here is an example helper method that illustrates this case.

Example:

    /**
     * Hides a view criterion.
     * Example: The following will hide the SourcePolicyNbr criterio if the condition
     *          is true. If the condition is false, it will show the criterio in BOTH basic and
     *          advanced.
     *        
     *          hideCriteriaItem("SomeCriteria", "SomeCriteriaItem",
     *             someCondition==true, ViewCriteriaItemHints.CRITERIA_RENDERED_MODE_BOTH);
     *
     *
     * @param viewCriteriaName the view criteria name
     * @param criteriaItemName the criterio name
     * @param condition the HIDE condition
     * @param showHint the SHOW hint
     */
     protected void hideCriteriaItem(String viewCriteriaName,
                                    String criteriaItemName, boolean condition,
                                    String showHint) {
        if (viewCriteriaName != null) {
            ViewCriteria v = this.getViewCriteria(viewCriteriaName);
            if (v != null) {
                boolean found = false;
                while (v.hasNext() && !found) {
                    ViewCriteriaRow vcr = (ViewCriteriaRow)v.next();
                    if (vcr != null) {
                        ViewCriteriaItem[] vcis = vcr.getCriteriaItemArray();
                        if (vcis != null && vcis.length > 0) {
                            for (int j = 0; j < vcis.length && !found; j++) {
                                ViewCriteriaItem vci = vcis[j];
                                if (vci != null && criteriaItemName != null &&
                                    criteriaItemName.equals(vci.getName())) {
                                    found = true;
                                    vci.setProperty(ViewCriteriaItemHints.CRITERIA_RENDERED_MODE,
                                                    condition ?
                                                    ViewCriteriaItemHints.CRITERIA_RENDERED_MODE_NEVER :
                                                    showHint);
                                    v.saveState();
                                }
                            }
                        }
                    }
                }
            }
        }
    }


Context:

View Object Implementation Class

Thursday, November 18, 2010

Bit #24 - Displaying Application Module Pool Statistics

You can display statistics related to your Application Module Pools by calling dumpPoolStatistics() on a oracle.jbo.common.ampool.ApplicationPool object. You can acquire an ApplicationPool object by calling getResourcePool() on a oracle.jbo.common.ampool.PoolMgr object and specifying the name of the application module pool name. So, how do you get a PoolMgr object? Just call the static PoolMgr.getInstance(). Finally, you can get the pool name by calling getResourcePoolKeys() on the PoolMgr and enumerating the pools managed by the pool manager. Here is an example:

Example:


    // helper to dump pool statistics to log
    private void dumpAMPoolStatistics() {
        // get the pool manager
        PoolMgr poolMgr = PoolMgr.getInstance();
        // get the pools managed
        Enumeration keys = poolMgr.getResourcePoolKeys();
        if (keys != null) {
            if (keys.hasMoreElements()) {
                // may manage many pools, we will get the name of first one managed
                String poolname = (String)keys.nextElement();
                System.out.println("AM pool name: " + poolname);
                // get the AM pool
                ApplicationPool pool =
                    (ApplicationPool)poolMgr.getResourcePool(poolname);
              
                // log AM pool diagnostics
                PrintWriter out = new PrintWriter(System.out, true);
                pool.dumpPoolStatistics(new PrintWriter(out));
                out.flush();
            }
        }
    }


The helper function above, when added to your application module will display - upon calling it, the AM statistics in the log window as it is shown below.



Context:

BC Implementation Class


References:
83. Dump Application Module Pooling Statistics Servlet

Tuesday, September 7, 2010

Bit #23 - Using findAndSetCurrentRowByKey() to set the View Object currency

You can set the currency on a View Object (VO) by calling its findAndSetCurrentRowByKey() method. The method accepts two arguments: a Key object that is used to locate the row in the VO and an integer indicating the range position of row (for VOs configured with Range Paging Access Mode). Below is an example. The example saves the VO currency, queries the VO and finally restores its currency. Click on the references below to get all the details on the example.

Example:

   /**
   * Helper to requery the view.
   */
   public void requery() {
      Row currentRow = getCurrentRow();
      Key currentRowKey = currentRow.getKey();
      int rangePosOfCurrentRow = getRangeIndexOf(currentRow);
      int rangeStartBeforeQuery = getRangeStart();
      executeQuery();
      setRangeStart(rangeStartBeforeQuery);
      findAndSetCurrentRowByKey(currentRowKey,rangePosOfCurrentRow);
}

Context

View Object Implementation Class
Application Module Implementation Class

References
http://radio-weblogs.com/0118231/2004/11/22.html


Wednesday, July 14, 2010

Bit #22 - Using getPostedAttribute() to determine the posted attribute's value

Call getPostedAttribute() anywhere in your Entity Object implementation class to retrieve the posted value of an Entity attribute. The example below calls getPostedAttribute() and getAttribute() to determine the attribute value in the database (posted) and in the Entity cache (not posted yet) respectively. They are called from within an overridden doDML(). Then based on the result of comparing them, certain business logic decisions can be made. Note that we call getPostedAttribute() before calling super.doDML(). This is done because calling super.doDML() will in effect post the attribute value in the Entity cache to the database, so will not make much sense to compare them afterwards: They will be the same!

Example:

    // in your Entity Object Implementation class

    @Override
    protected void doDML(int operation, TransactionEvent e) {

        final String EMPLOYEE_ID = "EmployeeId";
      
        // get posted value of EmployeeId attribute
        Object postedEmployeeId = getPostedAttribute(this.getAttributeIndexOf(EMPLOYEE_ID));
      
        // get value of EmployeeId before re-posting
        Object employeeId = this.getAttribute(EMPLOYEE_ID);
      
        // compare and take some action based on the results of comparison
        if (employeeId != null && employeeId.equals(postedEmployeeId)) {
          // do something here
        }
      
        // finally re-post by calling super.doDML()
        super.doDML(operation, e);
    }


Context

Entity Object Implementation Class

Saturday, June 26, 2010

Bit #21 - Overriding prepareSession() to do session-specific initializations

You can override prepareSession() in your custom Application Module class to do session-specific initializations, such as invoking a stored procedure to initialize the database state for the specific user, store user information, set application-wide configuration parameters based on the user and so on. The framework invokes prepareSession() when the Application Module is first checked-out from the Application Module pool for a new user session.

Example:

     @Override
     protected void prepareSession(Session session) {


          super.prepareSession(session);

         // do session-specific initializations
     }


Context:

Application Module Implementation Class

Wednesday, June 23, 2010

Bit #20 - Overriding beforeCommit() to execute custom code before commit

Override the Application Module beforeCommit() method in your custom Application Module implementation class to execute any custom code that depends on data already posted to the database. Such code may include - but not limited to - validations done in the database via a stored procedure for example. The framework calls this method after doDML() which means that posted data are available but not yet committed.

Example:

// in your Application Module Implementation class

@Override
public void beforeCommit(TransactionEvent transactionEvent) {

        // call some stored procedure here

       super.beforeCommit(transactionEvent);
}


Context:

Application Module Implementation Class

Saturday, June 12, 2010

Bit #19 - Downloading a file

Use an af:fileDownloadActionListener Rich Faces component to download data from the server to a client machine. Add the listener inside the component that will initiate the download, an af:commandButton for example, and specify the content type and the name of the file. Also specify a method in a backing bean that will be called to perform the download. In the backing bean method get the formated data to be saved from the model and use the supplied OutputStream to write the data.


Example:

In .jsf page:

<af:commandbutton id="buttonid"  " text="Download" ...
    <af:filedownloadactionlistener contenttype="application/octet-stream"
                method="#{backingBean.doDownload}"  filename="defaultFilename.txt"/>          
</af:commandButton>


In backing bean:

  public void doDownload(FacesContext facesContext, OutputStream outputStream) {
      // write the neccessary code to get the download data from the Model
      String data = getDownloadData();

      // save to the output stream
      try {
          OutputStreamWriter writer = new OutputStreamWriter(outputStream,"UTF-8");
           writer.write(data);
           writer.close();
          outputStream.close();
      } catch (IOException e) {
          // handle I/O exceptions
      }
  }


Context:

JSF Page
Backing Bean

Saturday, May 15, 2010

Bit #18 - Dynamically changing the View Object's query WHERE clause

You can dynamically change the View Object's (VO) query WHERE clause by overriding the buildWhereClause() VO method. When doing so, ensure that you call the base class' buildWhereClause() first, to let the framework do its processing before making your own changes. The StringBuffer parameter that is passed to the method is the complete query SQL statement. Do your changes directly onto it. When done, make sure that you return appropriately a true/false boolean to indicate whether a WHERE clause was appended to the query or not. Here is an example.

Example:


    @Override
    protected boolean buildWhereClause(StringBuffer sqlBuffer, int noBindVars) {

        // call ViewObjectImpl's buildWhereClause() to allow the framework to do its processing
        boolean hasWhereClause = super.buildWhereClause(sqlBuffer, noBindVars);

        if (hasWhereClause) { // framework added a WHERE clause
            // modify the WHERE clause as needed
        }
        else { // framework did not add a WHERE clause, so we need to add it ourselves
            // add a WHERE clause here
            hasWhereClause = true; // ensure that is set to notify the framework
        }

        return hasWhereClause; // return true/false to indicate whether a WHERE clause was added
    }


Context:

View Object Implementation

Monday, May 10, 2010

Bit #17 - Using the securityContext bean in a JSF page

To acess the user's authentication information from within a JSF page, use the securityContext bean and any of its available methods. For instance, using Expression Language (EL), the following will return true/false indicating whether the user is authenticated or not: #{securityContext.authenticated}. Similarly, to determine whether the user has been assigned a specific role, use the following EL snippet #{securityContext.userInRole['SomeRole']}. It will return true if the user has been assigned the specific role.


Example:

    // in the context of a JSF page

    <af:commandLink id="login_logout" action = "#{securityContext.authenticated ? 'logout' : 'login'}" text="#{securityContext.authenticated ? 'Logout' : 'Login'}/>

    <af:commandToolbarButton id="delete"  actionListener="#{backingBean.delete}" disabled="#{securityContext.userInRole['CanDelete']==false}" text="Delete"/>



Context:

JSF Page

Tuesday, May 4, 2010

Bit #16 - Removing a row from a query collection without deleting it from the database

There are times when you want to remove a row from a query collection (the query result) without actually removing it from the database. The query collection - oracle.jbo.server.QueryCollection - gets popullated each time the View is executed - when the View's associated query is run, and represents the query result. While the Row.remove() will remove the query collection row it will also remove the underlying Entity row - for an Entity-based View - and post a deletion to the database. If your programming task requires that the row is removed from the query collection only, i.e. removing a table row in the UI without actually posting a delete to the database, use the Row method removeFromCollection() instead. Just be aware that each time the View is re-executed the Row will show up once again!

Example:

        // in the context of the ApplModuleImpl

        // remove the current row from the query collection
        EmployeesRowImpl employee = (EmployeesRowImpl)(this.getEmployees().getCurrentRow());
        employee.removeFromCollection();

        // the employee row has been removed from the result set and cannot be used anymore


Context:

Application Module Implementation Class
View Object Implementation Class

Related Posts Plugin for WordPress, Blogger...