Home » General

Create an ADF ViewObject based on BPEL’s HumanWorkflow Tasklist

Written By: Pascal Alma on January 18, 2007 No Comment

A few posts ago I blogged about how you can access BPEL HumanWOrkflow with a standalone Java program. In this post I will go one step further and show you how you can create a viewobject based on the HumanWorkFlowReader. You can use this viewobject for example in your JHeadstart Application Definition file so you can generate a JSF page to browse through the HumanWorkflow tasks.

The base for this post is this one, to create a standalone HumanWorkflowReader. If you have this in place (or something similar) then it is time to create the view object (I have based this viewobject on an example of Steve Muench. It is based on the class ‘SRStaticDataViewObjectImpl’, which is supplied with this example of Steve).

The most important thing is that the viewobject is not based on a query, but is programmaticaly supplied with rows, as shown in the next figure:
Create VO step1
As an example I have created 3 attributes for this viewobject:

Create VO step2a
Create VO step2b

Create VO step2c

After the viewobject is created, open the Java class of the ViewObject, in this example called TaskListViewObjImpl.java. The following methods must be implemented:


protected void executeQueryForCollection(Object rowset, Object[] params, int UserParams)
protected void create()
protected ViewRowImpl createRowFromResultSet(Object rowset, ResultSet rs)
public long getQueryHitCount(ViewRowSetImpl viewRowSet)

I have the code for the complete class here (with several helper methods):

  1. package com.test.model.dataaccess;
  2.  
  3. import base.util.DateUtils;
  4. import java.sql.ResultSet;
  5. import java.util.List;
  6. import net.pascalalma.bpel.HumanWorkflowServices;
  7. import oracle.bpel.services.workflow.task.model.Task;
  8. import oracle.bpel.services.workflow.verification.IWorkflowContext;
  9. import oracle.jbo.server.ViewRowImpl;
  10. import oracle.jbo.server.ViewRowSetImpl;
  11.  
  12. // ———————————————————————
  13. // — File generated by Oracle ADF Business Components Design Time.
  14. // — Custom code may be added to this class.
  15. // — Warning: Do not modify method signatures of generated methods.
  16. // ———————————————————————
  17. public class TaskListViewObjImpl extends ViewObjectImpl
  18. {
  19.   private int _rows = -1;
  20.   private List _list = null;
  21.  /**This is the default constructor (do not remove)
  22.   */
  23.   public TaskListViewObjImpl()
  24.   {
  25.   }
  26.  
  27. /**
  28. * Overridden framework method
  29. *
  30. * This is the framework "pinch point" for all query execution.
  31. * The fact that we have nulled out all traces of a query
  32. * in the create() method will mean that the framework doesn’t actually
  33. * perform any query during this setup.
  34. *
  35. * @param rowset the query collection about to execute the query.
  36. * @param params the bind parameters that will be applied to the query.
  37. * @param noUserParams the number of user bind parameters supplied
  38. * through the setWhereClauseParam calls.
  39. */
  40.   protected void executeQueryForCollection(Object rowset, Object[] params, int noUserParams)
  41.   {
  42.     // Initialize our fetch position for the query collection
  43.     initializeData();
  44.     // Set indicator if rows are available
  45.     _rows = (_list != null) ? _list.size() : 0;
  46.     // Set the curRec position
  47.     setFetchPos(rowset, 0);
  48.    
  49.     super.executeQueryForCollection(rowset, params, noUserParams);
  50.   }
  51.  
  52. /**
  53. * Overridden framework method
  54. *
  55. * The framework calls this method to support the hasNext() method on
  56. * the rowset iterator for a rowset created from this view object.
  57. * We return true if our fetchPosition is still less than the _rows in
  58. * our in-memory data arrays
  59. *
  60. * @param rowset The current query collection based on this view object
  61. * @return true if there are more _rows still to fetch.
  62. */
  63.   protected boolean hasNextForCollection(Object rowset)
  64.   {
  65.     return getFetchPos(rowset) <_rows;
  66.   }
  67.  
  68. /**
  69. * Overridden framework method.
  70. *
  71. * Populates the "fetched" data for one row when the framework asks us to.
  72. * We get the data from the list with ‘BpelTasks’ and create a TakenlijstViewRowImpl
  73. * for it. We ignore the resultSet passed in which will be null
  74. * since there is no real query going on here to get the data.
  75. *
  76. * @param rowset The current query collection based on this view object
  77. * @param rs The JDBC result set being used to fetch data from
  78. * @return Next view row fetched from this rowset
  79. */
  80.   protected ViewRowImpl createRowFromResultSet(Object rowset, ResultSet rs)
  81.   {
  82.     // Create and populate a new row
  83.     ViewRowImpl r = createNewRowForCollection(rowset);
  84.     int pos = getFetchPos(rowset);
  85.     // Get the task for the current row
  86.     Task currentTask = (Task)_list.get(pos);
  87.     // Now copy the fields from the task to the viewobject row.
  88.     populateAttributeForRow(r, TaskListViewObjRowImpl.ID, currentTask.getSystemAttributes().getTaskId());
  89.     populateAttributeForRow(r, TaskListViewObjRowImpl.TASKNUMBER ,Integer.toString(currentTask.getSystemAttributes().getTaskNumber()));
  90.     populateAttributeForRow(r, TaskListViewObjRowImpl.CREATIONDATE, DateUtils.getOraDate(currentTask.getSystemAttributes().getCreatedDate()) ) ;
  91.    
  92.     setFetchPos(rowset, pos + 1);
  93.     return r;
  94.   }
  95.  
  96. /**
  97. * Overridden framework method.
  98. *
  99. * When this VO component is created, we load the data from properties file.
  100. *
  101. * This method is called once when the VO is first instantiated.
  102. */
  103.   protected void create()
  104.   {
  105.     super.create();
  106.     // Setup string arrays of codes and values from VO custom properties
  107.     // Wipe out all traces of a query for this VO
  108.     getViewDef().setQuery(null);
  109.     getViewDef().setSelectClause(null);
  110.     setQuery(null);
  111.   }
  112.  
  113. /**
  114. * Overridden framework method.
  115. *
  116. * If anyone asks for a getEstimatedRowCount() on this VO, we’ll return
  117. * the number of _rows we read from the property file.
  118. *
  119. * @param viewRowSet The current set of view _rows
  120. * @return Count of _rows read from the properties file
  121. */
  122.   public long getQueryHitCount(ViewRowSetImpl viewRowSet)
  123.   {
  124.     return _rows;
  125.   }
  126.  
  127. /**
  128. * Override to initialize the static data for this view object.
  129. */
  130.   protected void initializeData()
  131.   {
  132.     IWorkflowContext ctx = HumanWorkflowServices.authenticate(“oc4jadmin”,“ias_admin1″,“jazn.com”, null);
  133.     _list = HumanWorkflowServices.getTaskList( ctx );
  134.   }
  135.  
  136. /**
  137. * Set the current fetch position for the query collection
  138. *
  139. * Since one view object can be used to create multiple rowsets, we
  140. * need to keep track our current position in the rowset in the
  141. * per-rowset "user data" that the framework allows us to store as
  142. * context information.
  143. */
  144.   private void setFetchPos(Object rowset, int pos)
  145.   {
  146.     if (pos == _rows)
  147.     {
  148.       setFetchCompleteForCollection(rowset, true);
  149.     }
  150.     setUserDataForCollection(rowset, new Integer(pos));
  151.   }
  152.  
  153. /**
  154. * Get the current fetch position for the query collection
  155. *
  156. * This returns the fetch position for the current rowset in question
  157. * by retrieve the user data we stored in the context.
  158. */
  159.   private int getFetchPos(Object rowset)
  160.   {
  161.     return ((Integer)getUserDataForCollection(rowset)).intValue();
  162.   }
  163. }

Although this will work there are a few improvements possible and maybe necessary.
The first one is the call to the authenticate method to obtain a context. It would be better if we cache the obtained context in the session scope so next time the query is performed the context is taken from the cache. This will improve the performance and reduce the network traffic.
The second one is the addition of a bind parameter with which we can determine whose tasks are shown in the viewobject. Now we will see all tasks belonging to oc4jadmin, but in real life you probably just want to show the task belonging to the logged-in web user (or his group).
For now I stop at this point. Next time I will show you how you can implement the two improvements.

Tags: ,

Digg this!Add to del.icio.us!Stumble this!Add to Techorati!Share on Facebook!Seed Newsvine!Reddit!Add to Yahoo!

Comments are closed.

Copyright © 2009 Pascal’s Blog, All rights reserved.| Powered by WordPress