Friday, November 4, 2011

Drag And Drop Records Between Tables. ADF BC 11g

Hi
This is a small example of the following case:

Drag and Drop  records from one table to another.

More Specifically,  we are going to create a small application that will give us the ability to drag and drop employees to the desired department. The result to this will be to update the information of that employee.  We are going to present  each department and it's employees separately and we will be able to drag and drop employees from one department to another...
For this simple case, we are going to use 2 departments with their corresponding employees.

Download the Sample Application (JDeveloper 11.1.2.1.0).

We generate the appropriate business components for our little example.  The business components are:
Entities: Departments, Employees.
View Objects: Departments Employees.

Furthermore, all the appropriate entity associations and viewlinks are generated by the JDeveloper wizard.
Once we have that, we have to concider what else of development is left to be done on the Model layer.
Our use case describes the "move" of one or more employees from one department to another department. This means that each employee, of those draged and droped, will update there DepartmentId value.
So, what we have to do now, is to provide answers to the following logical and technical questions:

1) How are we going to know which employees are being moved?
2) To which Department are those employees are being moved?
3) Should we prevent any movement to the same department?
4) Should we immediatelly commit any movement to the database? Or should we have it a separate operation for the user?
5) How are we going to handle two different instances of VO in the Same Application Module? Are there any benefits to have two different Application Modules ?
6) How much code should we use in the view layer? Are we going to use AM methods? Are we going to develop in the Backing Beans?
7) Will the user be able to  edit employees and drag and drop without just commiting?

Lets try to answer them one by one...
1) We are going to know all the information of every row straight from the controller. Sample code will be provider later in this post. So, there is no problem for this. The framework allows use to handle this information.

2) We have this imformation as well. Even though we will be droping employees to another employees table. Basically we will be able to know the Department Id of the other iterator directly from the Application Module. More about the Applicaton Module later on.

3) Normally, we should prevent it, because it is less consuming to simply check both Departments's ids and raise a message, rather than updating viewRows and entities with the same values. Besides, the implementation will acutally be the same for both tables. Which means that the user will be able to actually drag and drop employees inside the same table.  This will certainly be an overuse of the functionality and it will be better to prevent it.

4) No, we should not immediatelly commit, simply because, the user might do a mistake and will want to undo her changes. It is a lot easier to simply have a rollback button, which, in terms of ADF development, is just a drag and drop. On the other case, we will have to redo an update and commit again. These are extra roundtrips to the database which is not a good thing to occupy the database if you can avoid it. Now, there is always the case where the user will want to undo the changes of only specific employees and not all of them. Well, in this case, the user will have to find those employees and re drag them back to original Department. Even if this is the case, all those changes will take place in the cache and not in the database. All those changes will be posted and commited to the DB when the user will press the commit button. One button. One press. One commit. keep the DBAs even happier.

5)With ADF we can simply insert the Same View Object twice. This will create two total different instances and handle them as such in the presentation layer. However, with one Application Module, the out of the box rollback functionality will rollback everything in both tables. But, this is the default functionality and we should treat it as is. On the other hand, if we use two Application Modules, we will be opening two database connections. You can reference documentation regarding Application Module pooling parameters here:

http://www.oracle.com/technetwork/developer-tools/jdev/index-097578.html

Overall, from architectural point of view and my personal opinion, it is better to use one Application Module and keep the DB and Weblogic resources as low as possible. But again, this is my opinion..

6) We will use both cases. We are going to use methods developed in the views and in the Backing Bean. The reason is simple. every action should be done in the appropriate layer.

7) This is possible yes. Since we will be using one Application Module, all changes will be carried to the other Department. At the bottom line, it is just a change.

------------------------------------------------------------------------------------------------
IMPORTANT NOTE: In HR Schema, there is a trigger called UPDATE_JOB_HISTORY
(using SQL Developer ).



This trigger is executed every time an update is done for employee regarding jobid and/or departmentid. As you will see this trigger has many check constraints that will not allow us to update an employee. For instance the pk is a combination of employee Id and the start Date to the new department...



Since in this example we want to demonstrate a back and forth drag and drop along with commit operation, we will disable this trigger. Just right click on the trigger in the SQL Developer and select disable. Again, this is an example of the drag and drop implementation. In real production environments those issues will be addressed accordingly. In case you dont disable this trigger while running this example, you will not be able to drag and drop the same employee to another department in the same day... the choice is yours!!
-------------------------------------------------------------------------------------------------

We shall Develop!!

So far, we have just created the BC and Shuttle twice the same viewObjects. Departments and Employees. This will give us the freedom to use two total different instances of the same View Object in the same page and keep the cached values visible in both of them. So, every time we update a




The part of the selected rows and their information is already described by Frank Nimphius in the
ADF Code Corner . We are going to use that sample code because it is exactly what we need.

We want to know the selected rows that are going to be updated.

The difference in this example is that we will be updating table rows in the backend.
We will not commit and the user will have a smooth "administration" of departments and employees.
In other  words the user will point and change.

Developing the jspx
Since we have already created our BC, it is time to develop the jspx.
For that reason, we will create a bounded task flow and a view inside it.







Then, we double click on the view to create the jspx. For this example we are going to use the three column Oracle template.
The layout of the page is rather simple. We will just drag and drop Departments and Employees, Left and Right, to our jspx with the help of JDeveloper Wizard



 JDeveloper will create all the needed components along with partial triggers as you see in the screen below:


Additionally, we change some labels and add Commit and Rollback buttons from the DataControl in the start facet of the template:






When we run our task flow the page will be like this:




Up to now we have achieved to have two panel boxes with separate functionality in terms of navigation. Commit and Rollback button apply to both panelBoxes since our views belong to the Same Application Module.

Applying Drag and Drop functionality.


In order to add Drag and Drop functionality, we have to do the following:
Each table will be able to either drag one or more rows to the other table. So, each table will have a drag source  and each table will be a drag target. We simply insert inside each table the tags dragsource and droptarget.

DragSource:
We want to move one or more rows from a table. For that reason we have to specify the action to be MOVE:


We do exactly the same for both tables. Now, we have enable both tables to be able to drag rows and move them. We will specify now where those rows can be dropped.

DropTarget:
The implementation is similar to dragsource. We write the droptarget tag inside each table and we specify the same action move. Additionally, in the droptarget we have to specify the following:
dataFlavor:  This is an inner tag of droptarget in which have to specify the type of data that are going to be handled and the type of action. In our case we want to move a RowKeySet with discriminatn rowmove.
dropListener: Without a dropListener we do not achieve much since we want to update our employees with the "accepting" departmentId. The dropListener is a property in the droptarget tag:


We set the dropTarget tab to both tables. The difference here is that we have to specify different dropListeners for each droptarget tag. This is because we want to handle the different dropEvents. We could fix our code to be better in terms reusability, but this is not the scope of this example.

On each drop listener we have to do the following:
We have to gather all rows that are dropped, find the new DepartmentId and update them. Finally we have to  show the updated rows under the new department.

JAVA coding:

The coding part is relatively little for this implementation. All we have to code is:
Get the Landing Department (the new Department Id to which the dropped employee will belong),
Get the Selected Rows,
Update each row with the new DepartmentId,
Show the changes to the user. This means executeQuery for the Employees and update the components.

Getting the Landing Department Id:






Getting the Selected Rows:



Update Each row with the New DepId:


Refresh UI:





All this code is basically one method: a DropListener method:




The operationBindings is nothing more than 2 ApplicationModule methods exposed to the client:




last but not least, is the panel box bindings which are used to refresh the UI components:


And That is it!

 Download the Sample Application.


References:

ADF Code Corner
60. Table Drag and Drop Sample by Fank Nimphius:

http://www.oracle.com/technetwork/developer-tools/adf/learnmore/60-table-drag-n-drop-sample-176981.pdf

af:dragsource:
http://download.oracle.com/docs/cd/E15523_01/apirefs.1111/e12419/tagdoc/af_dragSource.html

af:droptarget:
http://download.oracle.com/docs/cd/E17904_01/apirefs.1111/e12419/tagdoc/af_dropTarget.html

Adding Drag and Drop Functionality
http://download.oracle.com/docs/cd/E12839_01/web.1111/b31973/af_dnd.htm


Regards.


2 comments:

LinkWithin

Related Posts Plugin for WordPress, Blogger...