Wednesday, November 23, 2011

Programmatically create new row of View Object in Application Module. ADF bc 11g

Hi,

this is yet another example of showing hwo to create a new row of view object in an Application Module method.

Download Sample Application.

We will use the Departments table of the HR Schema in this example.
First we are generating the BC through the JDeveloper wizard.



Then, we generate the java class of the Application Module:



Inside the java class we place the following code:




The usage of this method varies.. In this example we are going to use page button in a page.

We have to do one more thing for that, expose our method in the client interface of the Application Module:
We go to the java section of the Application module and we press the pencil icon in the client panel:
In the new window, we select our method and shuttle it to right panel:



For that we create a page in our unbounded task flow:



Then we double click on the page, this will show us a wizard to help us create the page. This happens the first time only, the time that we want to actually generate the page.



In this example, we are going to use a jspx..

Then, from the dataControls, we are draging and droping the DepartmentsView onto the page as a form:



we just accept the default options from the wizard:


and press ok. The result looks something like this:



Now, what we want to create a button that will call our Application Module method.
All we have to do is to drag and drop our  method from the dataControl and select  ADF  Button:



And That is it.
If we run the page now, and press the button a new row will be shown.

Download Sample Application.

Friday, November 18, 2011

Master-Detail-Detail. Using Tree Table and Table. Using Target Data Source featrue. ADF BC 11g

Hi,
This is an example demonstrating the usage of treeTable and table of ADF all together.


Download Sample Application.


We are going to use the HR Schema and more specifically the following tables:
Departmens,
Employees,
EmployeesViewDetails.

Departments and Employees are going to be the Master detail that will be displayed in the Tree Table
the EmployeesViewDetails will be the detail table shown below the tree Table.

After generating the appropriate Business Components through JDeveloper wizard, we are going to create an additional association and a viewLink.
Because the EmployeesViewDetails is a database view, the associations are not provided by JDeveloper wizard.
Furthermore, we are changing the the Primary Key of the EmployeesViewDetails from RowId to EmployeeId.


Association:


ViewLink based on that association:


Finally we reach to a point where we will create the Application Module hierarchy:
This is the tricky part. at this point, we have to understand two things:
One, we are going to use the Target Data Source feature. This feature according to the following documents
http://www.oracle.com/technetwork/developer-tools/adf/master-detail-moredetail-154767.html

http://www.oracle.com/technetwork/developer-tools/adf/learnmore/sept2011-otn-harvest-508189.pdf

needs to point value that corresponds to a key of the other iterator..
Additionally the JDeveloper documentation for this feature says:

 So, what we have to do is to point the right value to the right Key..

Two, Our hierarchy is not going to be the following:


Is going to be the following:


Now, why is that???
Simply because, we want to use the target Data Source feature, and for that reason, we need to map the same key attributes.
Further more, we do not want to show the details on our tree.... We just want to show it on a separate table.

The concept is simple: We have to have the same keys to synchronize properly.
Now, to our case, apparently, we cannot synchronize Employees and EmployeesViewDetails directly, for the simplest reason that we are on a master-detail-detail situation...

In fact, our example is a very special case, because it is a pure coincidence that Employees and EmployeeViewDetails have the same attribute as a primary key.

According to documentation, a draft and general explanation would be the following:

the targeted Data Source iterator, will find a row where it's key value is the same as the key value of the selected row of the iterator that invokes the target Data Source iterator and will set this row to current.

well, reading it again, it is not simple at all!! :D
ok lets try again...

The targeted iterator will simply search for a row in the list and make it current. 
The key of that row, will have the same value as the key of the selected row in the tree.

hmm... still not good..

The iterator that uses the target Data Source  feature, will force the specified iterator to find a row with the same key value as the previous one.

I give up.... :D
Well, so if we had just added the EmployeesViewDetail without having it as a detail under Employees... we should have seen all employees and every time we selected an employee, the employeesViewDetail table would simply change the current row.
And of course, we do not want that..
So, the best approach is the one showed in the screen.
Why? Well, when we select an employee from the tree, the target Data Source feature will invoke the other employees iterator, which in turn will invoke the employeesViewDetails iterator to refresh because, after all, it is a detail right?..


Next, we are going to Create our page.
First, we will create a task flow and a jspx on it.
Onto jspx, we drag and drop the departments Iterator from the dataControl and we select, treeTable.
Then, we add a rule for the Employees as shown in the Screen below.



For Departments rule, we shuttle DepartmentId and Department Name attributes.
For Employees rule, we shuttle EmployeesId, firstName and lastName.
Next, we surround our treeTable with a panelCollection.  We Simply right click on the tree table component and we select panelCollection.



Since treeTable component, does not create other than the node column, we will create them ourselves.



After that, we surround the panelCollection with a panelGroupLayout with type Scroll. This will be the parent Container of both, our treeTable and table.


At this point, we have to apply the target Data Source feature. As we explained earlier, we are going to set this feature for the Employees detail iterator of the Departments master iterator. This Employees iterator will point to "other" Employees iterator.
But first, we have to add this iterator. So in our page definition we add the other Employees as iterator.

Then, we are going to set our Target Data Source value.
We simply select the tree of Departments and then the rule of Employees,
after that, we expand the target data source option and open the help wizard to choose our iterator. The iterator would be the "other" Employees iterator.


Now, every time we select an employee from our tree, the "other" employees iterator will change the current row to the same as the selected in the tree.
All we have to do now is to drag and drop the EmployeesViewDetails from our Data Control


After that, we surround the table with a panelCollection (the usual best practice..) and set partial triggers to table from the tree table.

And that is it!
When you run the page you will see a row in the empsDetailsView ofcourse, since it is querying, but this is not the scope of this post.. When ever you select an employee the table will be refreshed with the employee's details.


Download Sample Application

Regards.

Wednesday, November 16, 2011

Create new Record after Search Criteria (Using Search Form) returns no Results. ADF BC 11g

Hi,

In this post, we are going to immediately create a row when we have no search results.
This is usually the case in oracle forms. Forms have a different out of the box approach.
When a Form opens, it open in a mixed mode. This means that no data are fetched. The user is able to insert some data and press enter, if there are no data in the DB with a given primary key, then, Forms are entering insert mode. This means that they create a new row. If the data are there, the record is Queried.

We are going to do the same with the following example.

Download Sample Application.

We will use, as usual, the HR schema of Oracle XE and more specifically we are going to use the Regions table. We choose the Regions table because it is the simplest table regarding dependencies and fits the scope of this example.

First, we generate the Business Components from tables with the help of JDeveloper's wizard.
Next, we are going to use the Search Form  feature ADF BC provides.
We create a page called index.
So, we drag and drop the Regions iterator onto our page and



Ok. After dropping the Search Form, we can simply run and test our page. We will see that the default mode of the page is the fetch data mode. In other words, it queries and shows the first row.
If we press the find button, the page will enter into the find mode, where all fields are search criteria.
We can insert some data and press the execute button. Then the execute operation will be invoked and search for records that have those data we entered earlier.

Well, this out of the box functionality is not exactly what we want... So lets try to change it a bit.
First, let's try to open the page in find mode.
To do that, we are going to  create an invoke action, as mentioned in this post:

http://dstas.blogspot.com/2010/09/adf-11g-methodaction-and-invokeaction.html

Our invoke action is going to invoke the Find Operation.
Additionally we are going to change the refresh property. Our Refresh property is going to be: prepareModel
For further reading please check the following links:

http://groundside.com/resources/DuncanMills/S298736_bindings.pdf 
http://download.oracle.com/docs/html/B25947_01/bcdcpal005.htm#sthref837

Additionally, we are going to set a Refresh Condition. This is to avoid executing the invokeAction in every postBack.



If we now run and test our page, we will see that our page is entering in find mode! We are ready to set criteria and press execute!
Up to now, we are half way through. We have to enter in insert mode.
When? right after knowing that the execute operation returned no results.

So, at this point we can understand when we should invoke an insert operation. When our iterator has no rows.. No rows can be produced by many cases, one of them is when we enter non existing criteria and search.. Another reason might be the fact that there are not any records in the DB... What ever the case, we are fully covered.
Since we are opening the page in find mode.. we have to search..
Additionally, it would be great if we could enter in insert mode even if we issue a rollback and the DB has no rows..

Last but no least, is that we want to create a new row if the search has no results, but, we want to use those search criteria values in the new row.

For that, we are going to alter a bit the Execute operation. We are going to create our own actionListener method.
But First, we have to apply our logic. Our logic says that if we do not have any records fetched by the execute operation, we should immediately create a new Row, with initial values, those values we did the execute on the first place.
One thing at the time:

Getting the values from find mode:
We will override the create(AttributeList attributeList) method of the Regions View Row java class:



Then, we will create a method in our application module, that will check if there are any rows fetched (Since it will be invoked right after the Execute) and if not, it will create a new Row in the Regions view Object. We do not have to worry about the initial values since we have done some coding in the create method as mentioned above.



Then we expose this method to the client interface and add it as a methodAction in the pageDef of the



And that is it.
When we run the page, it will open in find mode. If we set criteria that will bring any data, the page will enter in insert mode with initial values those data.

Download Sample Application.

Regards.

Conditionally Displaying Table Records Based on Another records's attribute value. Conditionally making required attributes of those rows. ADF BC 11g

Hi,

In this example we are going to create a small application demonstrating the following case:

Using a table, a value of  an attribute of a row, will determine if some other rows will be visible or not.
Furthemore, on those rows, specific attributes will be required or not.

Download Sample Application.

Lets get into the details.
We have a table, that we want to filter it's data. Ok, so far so good. We can do that by using the iterator's filter property in the pageDef. Additionally we are going to use a transient attribute that will keep the value we want to filter with.

Then, we want to have some attributes of those hidden rows to be mandatory only when those rows are visible.
The condition that will determine wether those attributes will be required or not will be based on a value of an attribute of another row.

Example.

We Have Row A, Row B, Row C and Row D which they are visible.
We have Row E, Row F which are not visible.

When we will set value to attribute d of  Row D, row E and row F will be visible with the same attributes to be required.

In fact we are going to make things a bit more difficult. We want to have validation erros only when pressing commit. This is due to ease of use reasons. Simply put, we do not want mandatory field messages to be thrown every time we change a row.
Last but not least, the attribute that will determine the visibility of other rows, will be a Yes/No radio Button.
So, this means that, when the user selects Yes on a RadioButton of a row, there will be some logic that will make other, specific rows, be visible and make their radioButtons be required.

The logic that will make the rows visible and the radio required is purelly in the scope of business requirements. In this example we are going to use a simple case. The scope of this post is to demonstrate the implementation in order to achieve this functionality.

We are going to create a table in the HR Schema.

The Sql Script is already included in the application.
Download the application and find the script called SampleData.sql

As you can see from the table, there is not something weird.. Columns may have different names depending on requirements.
After we run the script, we create our BC from JDeveloper wizard.

And we have the following BCs:





It is quite obvious that attribute SelectRadio is going to be our radioGroup of yes/no. So we are going to add a List of Values to this attribute. The List of Values is going to be a new view object with static values.
The attributes are going to be the following:
ID,VALUE.



With the following DATA:



We set the Y and N just for simplycity.
After finishing the creation of the static VO we create an LOV in our sample View Object:



Then we just add the Static View object as an accessor.
We map the Selectradio attribute with the selectradio attribute with the choice attribute. and that is it.

Ok, so far we have created the VO with an LOV.

What we want now is to make the radio Group conditionally required. As we see in the db table. it is not required. We could have a entity validation method. But in this example we are going to try something different. We are going to use the required property of the radioButton.


Since, we will have another row determining the required property, we are going to follow this approach:

We will place a transient attribute in our viewObject called  ReqRadio. This attribute is going to determine if this the RadioButton is going to be required or not. So we add this attribute:



Now, the only thing left is to place the logic where this transient attribute will get a value.
Since a radioButton will determine if another radioButton of another row will be mandatory, we will have to do an iteration over all those rows that are dependent of that row.
For this example, we keep things simple. we have a column in our table in the DB which is called, typeofdata. As you will see in the rows, we have a record that has a value of MasterFormC and others that have value of formC. This example logic says that all rows that have formC and the radioButton of MasterFormC is with value Y, then, those records will have their radioButton required.

The simplest way to do that is to create a ViewCriteria in our ViewObject that we will use it to filter our rows. The Execution Mode will be set to memory



As you can see from the screen above, we set the typeofdata to be equal to "formC".
Next, we are going to create a method in our Application Module that will do the following:
First, we will check if the typeofdata is MasterFormC and then:
Will get the ViewCriteria of the View Object, apply it, get the RowSetIterator and set value to the transient attribute ReqRadio of each record.
The value to be set will be given as a parameter.



As you can see from the code, we return a message that we will use it later in our page.
Next, we expose this method to the client interface of our AM.



Next, we will create our page and we will drag and drop our table onto the page:



Then, we will surround our table with a panelCollection container and insert Commit and RollBack operations as toolbar Buttons in the toolbar which will reside in the toolbar facet of the panelCollection



As we mentioned earlier, we do not want to have validation errors every time we change a row... For that reason, we are gong to set the immediate property of the table to true.



The last thing to do onthe UI for the RadioButton is the requiredProperty. the required Property will be based on the value of the reqRadio:


Now that we have a pageDef, we will expose our AM method as a methodAction:




Additionally, we want to filter our iterator with all those rows that can be visible due to our business logic.
For that, we are going to create a transient attribute that will be called IsVisible. We are going to change a bit the code in the getter of this attribute (we have to create the ViewRowImpl jav class of our view object first and select the generateAccessors property):




With the above code, we will know if this row is to be visible or not.
Onto our pageDefinition:
in the pageDef, we select the iterator of our View Object and we wil enable the filtering:




Now we will be able to filter our table properly.
Last but not least, is our radioButton. We set it to autoSubmit=true in the page. We then create a valueChangeListener for our RadioButton.
Additionally we will create a popup with a dialog and an outputFormatted text with value of a pageFlowScope variable.



Then, we create bindings for the popup and the table. This will allow us to programmatically show the popup and partialTarget our table.



And That is it.

If you run the application You will see that initially, the data are filtered and depending on the value of the MasterFormC typeofdata, the rows are becoming visible and required. Additionally there is a popup Shown when the rows are becoming visible notifying the user that the following rows must have a value on their radioButtons.

Download Sample Application.

Regards.

Saturday, November 12, 2011

prepareModel, renderModel and the lifeCycle. ADF 11g

Hi,

This is a small post explaining a bit the difference of prepareModel and renderModel options in the refresh property of an InvokeAction.


Those two refresh properties are very self explanatory..

The only difference is the following:

prepareModel: Is executed right after initContext is executed.


renderModel: Is executed right after metadataCommit is executed.


In other words, prepareModel is executed right before any validations or posts or updates take place. Basically, is executed after initContext and before everything else. So, this property is useful for actions and methods that do not require any validation process or updates. It will be executed before all that.

RenderModel, on the other hand, is executed after all those steps are done and passed. So we can use this refresh option when our business logic, or our logic, claims that all steps of the life Cycle should be done.

I understand that this is not the full description nor it is the official documentation. Besides, there is the official documentation for that. But, those lines can be used in everyday developing and I believe that can help in understanding which property we should choose depending on the case.


(Figure 20-1 Lifecycle of a Web Page Request Using JSF and Oracle ADF from 
online documentation regarding ADF LifeCycle)








(Figure 20-2 Lifecycle of a Page Request in a Fusion Web Application from online documentation regarding ADF LifeCycle)


Regards.



References:

10.5.5.3 Correctly Configuring Refresh Property of InvokeAction Executables

20 Understanding the Fusion Page Lifecycle

http://groundside.com/resources/DuncanMills/S298736_bindings.pdf





Thursday, November 10, 2011

Master Detail CRUD operations with Regions ADF 11g

Hi,

This is an example that demonstrates how to create a Master Detail relationship between tables by using Regions. The main purpose of regions is the notion of reusability. With regions and bounded task flows we can reuse our pages into many other pages keeping the same functionality and having a more cleaner approach.

Download the Sample Application.

For this example we are going to use only one Model project and keep things simple.
We are going to create our Business Components through JDeveloper and it's wizards.
We are using Master Detail for Departments and Employees.


So, we are going to create two Bounded Task Flows that use fragments.
One for the Departments
One for the employees.

In each bounded task flow we drag and drop a view and place the appropriate names of departments and employees.



Then in the unbounded flow we create a jspx that will have two Regions defined.
One for the Department BTF
One for the Employees BTF

For Departments we are going to drag and drop the Departments iterator as a form with navigation buttons and submit button. Additionally, we add the createInsert and Delete Operation buttons next to submit



We do the same with employees. The only difference here is that  we drop an editable table and not a form. Additionally we drag it from the hierarchy and not the alone one in our Data Control. This means that we drag the detailed employees.


Next, we are going to create an index page in our unbounded task flow that will contain our Bounded Task Flows as regions.

In order to that, after we created the index page, we simply drag and drop each Bounded Task Flow as a Region


We do the same for the Employees Bounded Task Flow.
Up to now, we have our hierarchy done and well placed. Since we share the same application module instance, we are good to go!!
All that is left now is to place commit and rollback buttons in our Departments fragment and we are done!
For the rollback button we have to make a specific adjustment:
The emps region needs to be refreshed and indicate that the rollback is performed. For this reason we are going to set the refresh property as follows:



So, what we do here is, to set a refresh condition on our detail region. What we say here is, refresh emps fragment when the dept fragments is refreshed.

NOTE: this is a simple application demonstrating the ease of use of Regions. It is not intended to cover all aspects of regions.


Download the Sample Application.

Regards.

LinkWithin

Related Posts Plugin for WordPress, Blogger...