Thursday, April 8, 2010

Avoid using DBSequence as the foriegn key in master-details relationship

The reason of why to avoid using DBSequence as the foreign key in the Master-details relationship when you need to post the data into the database.

A user case for this scenario: you have two tables: User and UserGrant tables. User table has columns related to user info: user_id, user_name, user_password, user_address, etc. UserGrant has columns related to user and group info: grant_id, role_id, user_id, etc. User is the master table and has the primary key user_Id as a DBSequence. The user_id is also a foreign key in UserGrant table. You create VO based on the entities that based on the two tables, and drag the UserVO to the ADF page to create a new row. When a new role (which means a new user) created in UserEO, you want a new role (which means a new grant: a new user with a role) to be created the same time in UserGrantEO. The issue rises because the posting order of the two entity objects. This is because when a new role is created (before posting data and commit), the DBSequence will be assigned to a negative number (-1, for instance). This negative number will not be replaced by the real sequence number until you implicitly call the commit (actually is the postChange method behind it). We have no idea that which entity object will be posted first. If the detail EO (the UserGrantEO in our example) try to post data first, then a negative number tried to be assigned to user_id. Two issues: 1)it's a negative number, but most importantly 2).this number doesn't exist in master EO yet.

JDeveloper 11g Handbook has pointed out this on Page 221: the importance of posting order. The workaround has been provided on this matter too.

But easily workaround way for me is to link the two tables using another column, in our case, it would be user_name, which is not a sequence. So both User and UserGrant table have the user_name column and it servers as the link for the master-details relationship.

Tuesday, April 6, 2010

Create Data in ADF

Suppose you have to handle a process of user registration in ADF fusion application. Then you will have the page for user to put their user info (user name, user password, and other personal info) into your database. So to implement the process of create data in ADF, you need to do the following:

1. create entity objects for the database tables.
2. create view objects for the data objects that will be handled with user interaction.
3. expose the VO to AM and we need to write some custom codes in AMImpl java file we will use later. The method is about to create a new row in the VO. Expose this method after creation. For example:

public void simpleRegistrationCreate(String userType, Number assignedBy,
String userRole) {
ViewObject userVO = this.getWebUserVO();
Row currRow = userVO.createRow();
currRow.setAttribute("UserType", userType);
currRow.setAttribute("AssignedBy", assignedBy);
currRow.setAttribute("UserRole", userRole);
userVO.insertRow(currRow);
}
4. This step is to handle the UI part. There are many options, but here I am using a bounded task flow for the user registration process.
(1). create a bounded task flow, and drag the simpleRegistrationCreate method from dataModel to the blank bounded task flow and the method automatically set as the default activity in the task flow.
(2). create a fragment named as Registration.jsff, drag the VO from dataModel into the page fragment and select/deselect the data column you need the user to fill.
(3). drag "Commit" from DataModel to the task flow as a method activity. create another fragment as the registration confirmation if you need to.
(4). now connect the activities using control flows (navigation flows).
(5) drag the task flow into a page as a static/dynamic region for the user to register.

Monday, April 5, 2010

ADF Business Validation: password have to match confirm password.

There are many business validations we need to handle in ADF. Most of them are done at the attribute level. But one of them: password/email have to match confirm password/email scenoria has to be done via entity level.

This can also be done not using the business level validation instead by using UI handling.

Here is code example:

Create or CreateInsert

Taken from Jdeveloper 11g handbook:
Create or CreateInsert?

The two different create operations provided by ADF, Create and CreateInsert, can be a little
confusing because they seem to accomplish the same task. The row created by the Create
operation is managed as a temporary object by the framework. If the user abandons an
input screen without submitting the new record, the row will simply disappear, leaving the
programmer with no clean-up to do. CreateInsert, however, requires clean-up.
Although the Create behavior is generally more useful, there are still some circumstances
where CreateInsert should be used. Typically, this will be when the side effects of entity object
creation are desirable. For example, the create method on the entity object adds information
defined as defaults for attributes such as dates and reference numbers. With CreateInsert, this
default information will be visible to the user on the created (blank) record. If the Create
operation is used, the defaults will not be set until after the user submits the new record.




From Fusion Guide:

The ADF BC data control exposes three operations for a view object to create a new row: Create, CreateInsert, and CreateWithParams. The Create operation creates a new row for the collection but doesn’t add it to the iterator. CreateInsert works the same as Create but adds the new row above the current row in the iterator. CreateWithParams works the same as CreateInsert but optionally allows developers to define default values declaratively for the row attributes. The difference between Create and CreateInsert is only relevant if the collection is displayed in a table, not for a form.

Friday, April 2, 2010

Dynamic Tab Functionality

I followed a recent blog from Andrejus Baranovskis on a Dynamic Tab Functionality. Actually this functionality is very similar to Dynamic Region Functionality. An example of dynamic region can be found here.

To summarize how to implement dynamic region functionality:

1. create several bounded task flows that you wish to be a member of the dynamic region.

2. drag the task flow you wish to be displayed by default into the region on a JSF page, and choose "dynamic region" tag, you will be asked to set a bean to handle the regions switch.

3. drag the other task flow to the region you want to control the region switch (like the navigation panel), and choose "dynamic link" and choose the dynamic region you created in step 2 (the name is "dynamicRegion1" by default). Jdeveloper will create the codes in the bean to handle the region switch when you hit any of the command links you created in this step.

For Dynamic Tab Functionality, the steps are:

1. drag a bounded task flow into the "region" part. choose static region instead of dynamic region.

2. create a bean to handle the dynamic tab functionality. The codes are:

   private void _launchActivity(String title, String taskflowId, boolean newTab) {
        try {
            if (newTab)  {
                TabContext.getCurrentInstance().addTab(title, taskflowId);
                }
            else {
                TabContext.getCurrentInstance().addOrSelectTab(title, taskflowId);
                }
        } catch (TabContext.TabOverflowException toe) {
                toe.handleDefault();
            }
        }