A classic use of MVC architecture I must say. You have a button (Delete), and you want to remove the record from view's cache and also post the changes by committing to the database.
In otherwords, #{bindings.Delete.execute} would delete the row just from the cache. We need to explicitly commit the changes to the database henceforth.
We have dragged and dropped a Delete action as a command button. When the user clicks on this, the selected row is just removed from the cache. In order to commit the changes, we need to somehow call #{bindings.Commit.execute} action.
How do we do both these actions (Delete and Commit) on just one user click of the button ?
For the af:commandButton, define an actionListener="#{backing_Delete.deleteEmployee}"
In your backing bean 'backing_Delete', your deleteEmployee method looks like this:
public void deleteEmployee{
try{
ADFUtils.executeOperation("pageDef","Delete");
ADFUtils.executeOperation("pageDef","Commit");
}
catch(Exception ex){
throw new RuntimeException (ex);
}
}
Make sure that, you have defined these operations(Delete and Commit) in your pageDef.
This way, from one user interaction (click on the Delete button), from the view layer, you are coming through the controller (backing bean) and executing two operations on the model. Naturally, controller should be able to perform more than one operation on the model.
Done !
Wednesday, July 23, 2008
Tuesday, July 22, 2008
ADF navigation - (master detail)
When you want to navigate to Employees page from Departments list, say on click of a hyperlink of the department name, you should set the rowKey of the clicked Department, so that, when the detail view (Employees) is rendered, the correct row is picked up, and corresponding list of Employees is rendered.
You can achieve it in atleast three different ways :
1. Refer to my previous blog
http://nattu4u.blogspot.com/2008/07/
navigating-to-new-page-from-adf-table.html
2. In your ADF table (Departments), your commandLink should look like this :
af:commandLink text="#{row.PgmName}" action="empList"
actionListener="#{bindings.setCurrentRowWithKey.execute}"/>
In the corresponding pageDef,
action IterBinding="ProgramViewIterator" id="setCurrentRowWithKey"
InstanceName="CoreApplicationModuleDataControl.ProgramView"
DataControl="CoreApplicationModuleDataControl"
RequiresUpdateModel="false" Action="96">
NamedData NDName="rowKey" NDValue="#{row.rowKeyStr}"
NDType="java.lang.String"/>
/action
Thats all, and you are set to visit correct set of associated employees, when you click on hyperlink of DeptName.
3. The problem I foresee with the 2nd approach is, suppose, the value rowKeyStr might be lost in transit while you are navigating from Departments to the Employees page. A fool proof method would be to make use of "processScope" object, to set and retrieve the rowKey.
You can do so like this:
In Dept page, for the commandLink:
af:setActionListener to="#{processScope.deptKey}"
from="#{row.rowKeyStr}"/>
In Emp PageDef
Under executables:
invokeAction id="setCurrentRowFromProgramId" Binds="setCurrentRowWithKey"
RefreshCondition="${adfFacesContext.postback==false}">
Under bindings
action IterBinding="DeptViewIterator" id="setCurrentRowWithKey"
InstanceName="CoreApplicationModuleDataControl.DeptView"
DataControl="CoreApplicationModuleDataControl"
RequiresUpdateModel="false" Action="96">
NamedData NDName="rowKey" NDValue="#{processScope.deptKey}"
NDType="java.lang.String"/>
/action>
So, you are setting the deptKey when you click on department name, and you are retrieving when you execute the setCurrentRowWithKey action. This would get executed, when you navigate to the Employees page and the invokeAction gets executed during the page launch.
So, you are setting it before and getting it when you launch this page. Logical rite ?
You can achieve it in atleast three different ways :
1. Refer to my previous blog
http://nattu4u.blogspot.com/2008/07/
navigating-to-new-page-from-adf-table.html
2. In your ADF table (Departments), your commandLink should look like this :
af:commandLink text="#{row.PgmName}" action="empList"
actionListener="#{bindings.setCurrentRowWithKey.execute}"/>
In the corresponding pageDef,
action IterBinding="ProgramViewIterator" id="setCurrentRowWithKey"
InstanceName="CoreApplicationModuleDataControl.ProgramView"
DataControl="CoreApplicationModuleDataControl"
RequiresUpdateModel="false" Action="96">
NamedData NDName="rowKey" NDValue="#{row.rowKeyStr}"
NDType="java.lang.String"/>
/action
Thats all, and you are set to visit correct set of associated employees, when you click on hyperlink of DeptName.
3. The problem I foresee with the 2nd approach is, suppose, the value rowKeyStr might be lost in transit while you are navigating from Departments to the Employees page. A fool proof method would be to make use of "processScope" object, to set and retrieve the rowKey.
You can do so like this:
In Dept page, for the commandLink:
af:setActionListener to="#{processScope.deptKey}"
from="#{row.rowKeyStr}"/>
In Emp PageDef
Under executables:
RefreshCondition="${adfFacesContext.postback==false}">
Under bindings
InstanceName="CoreApplicationModuleDataControl.DeptView"
DataControl="CoreApplicationModuleDataControl"
RequiresUpdateModel="false" Action="96">
NamedData NDName="rowKey" NDValue="#{processScope.deptKey}"
NDType="java.lang.String"/>
/action>
So, you are setting the deptKey when you click on department name, and you are retrieving when you execute the setCurrentRowWithKey action. This would get executed, when you navigate to the Employees page and the invokeAction gets executed during the page launch.
So, you are setting it before and getting it when you launch this page. Logical rite ?
Sunday, July 20, 2008
Navigating to a new page from an ADF table, on click of a hyper link
You have an ADF table, with one of the colums containing hyperlinks. You may want to navigate to another page, when you click on the hyperlink.

Naturally, If you click on 'name1', you want to see details related to name 1, and not that of the first record (Bug hunt ... TP4). So, you should be able to tell the browser through the framework that, you have clicked on name1 and not some other record. You can achieve it through the following piece of code.
// replace with your iterator.
ValueBinding vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{bindings.ProgramView1Iterator}"); DCIteratorBinding progIter= (DCIteratorBinding)vb.getValue(FacesContext.getCurrentInstance()); //the command link is a child of af:column, which is a child of af:table
// In case of 11g TP3 / TP4 onwards , its RichTable.
CoreTable ct = (CoreTable)actionEvent.getComponent().getParent().getParent(); //access the row data, to obtain the Row object and the formatted key string //oracle.adfinternal.view.faces.model.binding.FacesCtrlHierNodeBinding in 11g TP3 / TP4 JUCtrlValueBindingRef facesCtrlHierNodeBinding = (JUCtrlValueBindingRef)ct.getRowData(); String rowKey = facesCtrlHierNodeBinding.getRow().getKey().toStringFormat(true); prog.setCurrentRowWithKey(rowKey);

Naturally, If you click on 'name1', you want to see details related to name 1, and not that of the first record (Bug hunt ... TP4). So, you should be able to tell the browser through the framework that, you have clicked on name1 and not some other record. You can achieve it through the following piece of code.
// replace with your iterator.
ValueBinding vb = FacesContext.getCurrentInstance().getApplication().createValueBinding("#{bindings.ProgramView1Iterator}"); DCIteratorBinding progIter= (DCIteratorBinding)vb.getValue(FacesContext.getCurrentInstance()); //the command link is a child of af:column, which is a child of af:table
// In case of 11g TP3 / TP4 onwards , its RichTable.
CoreTable ct = (CoreTable)actionEvent.getComponent().getParent().getParent(); //access the row data, to obtain the Row object and the formatted key string //oracle.adfinternal.view.faces.model.binding.FacesCtrlHierNodeBinding in 11g TP3 / TP4 JUCtrlValueBindingRef facesCtrlHierNodeBinding = (JUCtrlValueBindingRef)ct.getRowData(); String rowKey = facesCtrlHierNodeBinding.getRow().getKey().toStringFormat(true); prog.setCurrentRowWithKey(rowKey);
Troubleshooting oracle.jbo.InvalidOwnerException: JBO-25030
You can encounter this exception in different scenarios. One such scenario is explained by Steve. This is useful while you are already in a form, and you have entered values to be posted to the database.
However, I have seen a few cases, where you encounter this error during navigation to the detail form (ADF create form, for example) in a master-detail scenario.
Suppose you have a Department Master and Employee detail. Employee table has Foriegn key relationship with Department master. If you create ADF business components out of these two tables, entity, view, and AppModule gets created.
Assume that you are displaying department details as a an ADF table. You might want to navigate to a new page that contains list of employees for a particular department. You could navigate via hyperlink to department name, or select a department record, and have a button to navigate to the new page. In this new page, you would want to see list of employees for a department, and also want to add new employees on click of, say, an Add button.
I encountered InvalidOwnerException while navigating to the new page, that has an ADF create form for Employee. I troubleshooted layer by layer. If you test your application module, without changing any of its properties, you will see this error. In 10.1.3.3 of Jdev, you can right click on AppModule and say Test. In 11g TP3 / TP4, you can right click on AppModule and say Run. It will show you the data model. You can double click the view link that connects Department and Employee, and add a department, and commit. If you click on the + sign of below window (to create an employee for the newly created department, You will see this error :
oracle.jbo.InvalidOwnerException: JBO-25030.
You might think that this should not cause any issue. So, your next step would be to look at your DB. Carefully examine your datamodel, to check everything is fine. Look at the constraints. Still, if you are unable to figure out, just create 2 simple tables 'Master' and 'Detail', with Detail having Foreign key relationship with master. Now Go to Jdeveloper, create business components, and test app module as elaborated earlier. This error could have disappeared. Now replicate you application's Department and Employee tables with these Master - Detail tables. Synch BC4J entities with database, and test AppModule. Oooaah. You have done it !
Well, after the above mentioned trial and errors, I again hit this issue which tormented me for one full day. I went through the same set of steps as mentioned above. I had a different use case though. I had a table with 2 foriegn keys (pointing to 2 different tables). I had 3 entities, a, b,c. Entity a was based on this table with 2 fks. The composition was marked on b, but the owner of a was marked as c in the app module. Hence, when I tested the app module, when I wanted to create a record on view a (based on entity a), it gave InvalidOwnerException. Naturally, becoz, u are trying to create a without its parent b which composes it. Got it ? :)
However, I have seen a few cases, where you encounter this error during navigation to the detail form (ADF create form, for example) in a master-detail scenario.
Suppose you have a Department Master and Employee detail. Employee table has Foriegn key relationship with Department master. If you create ADF business components out of these two tables, entity, view, and AppModule gets created.
Assume that you are displaying department details as a an ADF table. You might want to navigate to a new page that contains list of employees for a particular department. You could navigate via hyperlink to department name, or select a department record, and have a button to navigate to the new page. In this new page, you would want to see list of employees for a department, and also want to add new employees on click of, say, an Add button.
I encountered InvalidOwnerException while navigating to the new page, that has an ADF create form for Employee. I troubleshooted layer by layer. If you test your application module, without changing any of its properties, you will see this error. In 10.1.3.3 of Jdev, you can right click on AppModule and say Test. In 11g TP3 / TP4, you can right click on AppModule and say Run. It will show you the data model. You can double click the view link that connects Department and Employee, and add a department, and commit. If you click on the + sign of below window (to create an employee for the newly created department, You will see this error :
oracle.jbo.InvalidOwnerException: JBO-25030.
You might think that this should not cause any issue. So, your next step would be to look at your DB. Carefully examine your datamodel, to check everything is fine. Look at the constraints. Still, if you are unable to figure out, just create 2 simple tables 'Master' and 'Detail', with Detail having Foreign key relationship with master. Now Go to Jdeveloper, create business components, and test app module as elaborated earlier. This error could have disappeared. Now replicate you application's Department and Employee tables with these Master - Detail tables. Synch BC4J entities with database, and test AppModule. Oooaah. You have done it !
Well, after the above mentioned trial and errors, I again hit this issue which tormented me for one full day. I went through the same set of steps as mentioned above. I had a different use case though. I had a table with 2 foriegn keys (pointing to 2 different tables). I had 3 entities, a, b,c. Entity a was based on this table with 2 fks. The composition was marked on b, but the owner of a was marked as c in the app module. Hence, when I tested the app module, when I wanted to create a record on view a (based on entity a), it gave InvalidOwnerException. Naturally, becoz, u are trying to create a without its parent b which composes it. Got it ? :)
Monday, July 7, 2008
Migrating ADF security settings from Embedded oc4j to Webcenter preconfigured / standalone oc4j
I first created a sample application with simple authentication, deployed and tested successfully against preconfigured oc4j. I always believed that copying the system-jazn-data.xml from C:\Documents and Settings\\Application Data\JDeveloper\system11.1.1.0.22.47.96\o.j2ee\embedded-oc4j\config (for embedded oc4j) to C:\Documents and Settings\\Application Data\JDeveloper\oracle.adfp.seededoc4j.11.1.1.0.0.071218.1800\j2ee\home\config (for preconfigured oc4j), which made it stronger, especially after few experts responded that I was on the right track.
After careful comparison of my actual project with the sample application, I did find that, jps-config.xml and orion-application.xml in the/src/META-INF, did not contain key information like realm, identity store and policy store information. I was particularly surprised to learn that, the same set of files did not have any issues while being used with embedded-oc4j. Hence, I replicated the same onto my main project, after which the authentication was fine.
I had expected that, since system-jazn-data.xml contains the permission information at the pageDef level, authorization should be fine after migration. I verified that authorization was fine too, after migrating to preconfigured oc4j.
I have deployed and tested these on a standalone oc4j using ant script, and it works fine there as well.
After careful comparison of my actual project with the sample application, I did find that, jps-config.xml and orion-application.xml in the
I had expected that, since system-jazn-data.xml contains the permission information at the pageDef level, authorization should be fine after migration. I verified that authorization was fine too, after migrating to preconfigured oc4j.
I have deployed and tested these on a standalone oc4j using ant script, and it works fine there as well.
Thursday, June 26, 2008
Subscribe to:
Posts (Atom)