Friday 29 July 2011

ADF Security : JDeveloper 11g Release 2 (11.1.2.0)

Although I know about the bug with the anonymous role in JDeveloper 11.1.1.5, I used the standard wizard approach in applying ADF Security to my application. However that did not work at all. 
After Weblogic started up and my page should load, Weblogic seemed to be caught in an endless loop?!?!?!?

These were my steps to get it working:

  1. I only configured one (1) realm called: 'myrealm' and also made it the default realm (in other words, I deleted the realm named 'jazn'). After I did this and tried to test it, I got the known error (InvocationTargetException) which occurs when JDeveloper tries to migrate the security policies when your realm contains the 'anonymous-role'
  2. After deleting the 'anonymous-role' from my realm (<app-roles>-section in jazn-data.xml) the security policies were migrated successfully on the next startup of Weblogic.
Hooohooo!! :-)

My GO at creating a Menu Tree in ADF.

My steps:
  1. I created a SQL based View object called: MenuNodeVO.
  2. I created a View Object Link in order to setup a hierarchy that the ADF Tree can use.
  3. I created a root node View Criteria for MenuNodeVO to make it possible for only root nodes to be returned for the root nodes in the tree.
  4. I dragged and dropped my parent View Object from the Data Control to my page as an ADF Tree.
  5. I created a binding for the RichTree component in the page's backing bean.
  6. I implemented code to set the bind parameters on the view objects involved in the tree hierarchy. 
 1. I created a SQL based View object called: MenuNodeVO
This MenuNodeVO makes use of a hierarchical SQL query as such:
select id,
       parent_id,
       name,
       action,
       menu_type
from nodes
connect by prior id = parent_id
start with parent_id = -1
...(where 'nodes' denotes a table/select-statement containing all possible menuitems)

NB! After creation of MenuNodeVO set the key attribute for the view object. (i.e. id)

ALSO, I had bind parameters as part of the query amounting to 'nodes' in the query stated above and hence these bind parameters had to be set programmatically in order for the tree component to show up with the nodes and not be empty or break! So, be sure to set these bind parameters in the backing bean of your .jspx page.

Here's how to do it!

2. I created a View Link in order to setup a hierarchy that the ADF Tree can use.
There are a lot of examples out there which makes use of a different view object for each level in the tree. But, in order for the tree we're planning to create to be truly recursive and go from 1..n levels, one actually needs to use the same View Object for each level in the tree...I think it makes sense.
So, that's what I did. I created a View Link linking my MenuNodeVO to itself using id-to-parent_id as the source to destination view object attributes. Another important thing is to make sure that you specify the child view object accessor name as part of the View Link creation, as you might need it later on (In my case I did). I called it something like 'MenuChildNodes' as the name for the destination view object accessor.


3. I created a root node View Criteria for MenuNodeVO to make it possible for only root nodes to be returned for the root nodes in the tree.
This simply involved creating a View Criteria as you would usually do and adding a group item as criteria which specifies
that the parent_id should be equal to whatever the null parent id would be. (i.e parent_id = -1)
In other words, the criteria should ensure that only menu items with null parent ids should be returned by the MenuNodeVO execute query.
I named the criteria: "RootMenuNodeVOCriteria"

4. I dragged and dropped my parent View Object from the Data Control to my page as an ADF Tree.
Drag and drop is drag and drop. Nothing more to be said about that - LOL.
On the Edit Tree Binding Dialog (which appears when you drag and drop) however, you have to make sure of the following:

  • The parent node View Object iterator should be selected as your Root Data Source.
  • You should only have one Tree Level Rule specified as MenuNodeVO, with the destination child View Object accessor name in parenthesis next to it [i.e com.model.vo.MenuNodeVO(<MenuChildNodesVO>) ]
  • As usual make sure that you pick the display attributes for the Tree as you require.
5. I created a binding for the RichTree component in the page's backing bean.
The following are important:

  • You go to the binding property in the Property Inspector in JDeveloper while your RichTree component is selected.
  •  You click the down arrow next to the property and then 'Edit'.
  •  Then you select your managed bean and the property in the 'Edit Property: Binding' dialog as shown below:

6. I implemented code to set the bind parameters on the view objects involved in the tree hierarchy.
For completeness sake I've provided the getter and setter for the RichTree property binding as I've implemented in my backing bean:

public void setMenuTree(RichTree menuTree) {
    DCIteratorBinding iter = ADFUtils.findIterator("ParentNodeIteratorName");
    ViewObject parentVO = iter.getViewObject();
    parentVO.ensureVariableManager().setVariableValue("BindVariableName", "bindVarValue");

    ViewCriteria vc = parentVO.getViewCriteriaManager().getViewCriteria("RootMenuVOCriteriaName");
    vc.ensureVariableManager().setVariableValue("BindVariableName", "bindVarValue");
    parentVO.applyViewCriteria(vc, false) /* do not append the view criteria */;

    ViewObject childVO = ADFUtils.getChildViewObjectFromParent(parentVO, "ChildNodeVOAccessorName");
    childVO.ensureVariableManager().setVariableValue("BindVariableName", "bindVarValue");

    // then only set reference to given RichTree
    this.menuTree = menuTree;
}

public RichTree getMenuTree() {
    return menuTree;
}

Thursday 28 July 2011

ADF Tree : Setting Bind Parameters on a hierarchy of View Objects in your backing bean code

I was faced with the scenario of a hierarchical View Object defined in a View Link in order to make use of it in an ADF Tree component. The re-used/recursive View Object has bind parameters which are required and have to be set.

It was easy enough to get to the "parent" View Object in the hierarchy by using the Iterator binding as in the code sniplet below:

// get reference to the parent view object via the iterator binding
DCIteratorBinding iter = ADFUtils.findIterator("IteratorName");
ViewObject parentVO = iter.getViewObject();

// set bind parameter value on parent view object
parentVO.ensureVariableManager().setVariableValue("BindParameterName",      "BindParameterValue");

However, the "child" View Object in the hierarchy remained without its bind parameters set. Eventually, I got to the following solution (PLEASE NOTE: You have to use the destination view object accessor name as it is defined in the View Link you've created):

// get reference to the child view object via the parent view object binding
ViewObject childVO = ADFUtils.getChildViewObjectFromParent(parentVO, "ChildVOAccessorName");

// set bind parameter value on child view oibject
childVO.ensureVariableManager().setVariableValue("BindParameterName", "BindParameterValue");

The ADFUtils utility methods used above were implemented as follow:

public static DCIteratorBinding findIterator(String name) {
    DCIteratorBinding iter = getDCBindingContainer().findIteratorBinding(name);
    if(iter == null) {
      throw new RuntimeException("Iterator '" + name + "' not found");
    }
    return iter;
}

public static ViewObject getChildViewObjectFromParent(ViewObject parentVO, String childAccessorName) {
    AttributeDef attrDef = parentVO.findAttributeDef(childAccessorName);
    if(attrDef == null) {
      throw new RuntimeException("Attribute Definition '" + childAccessorName + "' not found on parent view object");
    }   
    return attrDef.getAccessorVO(parentVO);
}

Thursday 21 July 2011

The same old Time Zone error resurrects itself

This time I got it when I tried to create a View Object (JDeveloper 11g release 2 - 11.1.2.0). Or rather let me specify. I tried to create a View Object of a SQL query and on validation of the query obviously it probed the data source and it was exactly then when I got an "ORA"-error moaning about the time zone.

After trying the usual Project Settings --> Run/Debug Profile --> Launch Settings and setting the Java time zone variable there, it only started working once I've put the following line in the file "jdev.conf" (located in: /Middleware/jdeveloper/jdev/bin):

AddVMOption  -Duser.timezone="+2.00"  (it was "+2.00" in my case... :-) )

Then after a restart of JDeveloper it was working fine!