Wednesday, February 8, 2012

Updating a flag when deleting an entity in ADF BC / BC4J


Soft delete, is the process when the user deletes an entity, its deactivated or hidden, but not actually deleted. Its a fairly common use case, and comes in various flavors. In the most common case, a delete/active flag is flipped to signal that the row or entity has been deleted or inactivated. In other cases, the row is moved to another table, or some other action is taken in response to a deletion. In ADF most of these requirements can be met with ease. Lets look at the most common situation where a flag is flipped.

There are a couple of approaches I found by googling, some more involved than the others.
Jobinesh's Post on soft delete with undo.
http://jobinesh.blogspot.com/2011/05/soft-deletion-of-rows.html

Hussain's post on soft delete that sets up standard history column for the active flag and enables tooling
http://husaindalal.blogspot.com/2009/11/generic-way-to-handle-soft-delete.html

Jobinesh's method is particularly useful for implementing an Undo functionality, and it does not commit the transaction. Hussain's method needs quite a bit of setup and when you have existing tables that don't follow standards, it may be difficult to implement. My own approach, based on Jobinesh's method, seems to me, is the most simplistic, and I think its the most generic and offers most flexibility. It basically abstracts the method Jobinesh describes in to a base class that can be selectively extended by EOs that need SoftDelete.

I will create a new base VOImpl calss that can be extended by all VOs that I want to support soft delete for. Not all VOs need to extend this. If a VO extends it, the VO is forced to implement a method that updates the value of one of its columns. This also does away with standardizing a column name for the "Active flag" and also different VOs can use different standards. This may be useful when the DataModel already exists and the existing tables have different column names for the flag column.

The crux of this method is overriding the remove() method on the EntityImpl , and converting a delete in to an update in the doDML() method of the EntityImpl both of which are now abstracted by the base class and the actual entities simply implement the logic of that column to use as the flag column and what sort of flag to set. Allowing the Entity to decide this helps when different entities need to use different flags.
The relevant code is below.
    public abstract void setActiveFlagColumn(boolean isActive);
    

    @Override
    protected void doDML(int operation, TransactionEvent transactionEvent) {
        if (operation == EntityImpl.DML_DELETE){          
          operation = EntityImpl.DML_UPDATE;
        }
          super.doDML(operation, transactionEvent);
        
    }


    @Override
    public void remove() {
        setActiveFlagColumn(false);
        super.remove();
    }

The method setActiveFlagColumn(boolean) is implemented by the actual EntityImpl class and it should be implemented based on the spacific table. In the example application to keep things simple, I chose to just update the PhoneNumber field with the value 'false'. A setter method for the actual Flag column will be available in the actual EntityImpl.
public void setActiveFlagColumn(boolean isActive) {
      // Make appropriate conversion to represent this value (0/1,Y/N,T/F,A/I... etc.)
      setPhoneNumber(String.valueOf(isActive));

  }
Example application
The example application is based on the HR schema, but since the HR schema does not contain any tables with a flag column, and I wanted to keep the work required to run the example to a minimum, I chose to use one of the existing columns as my flag column. Its the "Phone" number column in the EMPLOYEES table. When a record is deleted, the example application updates that record with phoneNumber=false. The VO in the example is setup to ignore records with "false" as the value for phone number. Again, this is just so that I want to avoid making you alter your schema just to run an example application. This also goes to demonstrate how generic the approach is. The example can be downloaded here :
http://myadfnotebook.googlecode.com/files/SoftDelete.zip

To run the example, just open the ViewController Project and  run the page empView.jspx.
In the example you will notice that the delete does not commit the transaction and I have a separate commit button. In many cases you'll want to delete and commit in the same action. Check out Shay's blog post on performing two declarative operations on one button to achieve that.

Thursday, November 3, 2011

ADF Security Basics

ADF security is a pretty deep topic especially when you put it in perspective of an enterprise deployment and how the security infrastructure works together with the application server to provide for the functionality. Also, there are a number of great resources out there that give a good understanding about how to configure and secure an ADF application. My first go-to resources on the web would be :

Oracle ADF Documentation : Section 35
Chris Muir's Blog Post

Having said that, this is a quick look at the various aspects included in ADF Security  and a rundown of whats possible with ADF security and how to implement some fairly common use cases.  The example is based on the HR schema and can be downloaded from here.

In its simplest form, ADF security is declarative and protects pageDef files( for pages in the Unbounded taskflow) and whole BTFs (Bounded Taskflows), it can also be applied to EOs and EO attributes, which I personally consider especially powerful when combined with Oracle Database's VPD feature ( maybe that's a good topic for a blog post ! ).

ADF security is based on OPSS which in turn is based on JAAS. In this model, we create "application roles" and grant permissions to application roles to do certain operations within the application and hence the name. So the ability to do a set of operations is collected and called a role. Now these roles are granted to specific users, which enable those users to do all the actions defined by those roles assigned to them. In a real production environment however, the users are not defined in the context of a single application, instead they would be defined for the whole enterprise and granted access to various applications, all using the same user name (a single sign-on or SSO). So these identities (or users) would be defined in an identity store like LDAP and WLS can work with such systems. In WLS we can create "enterprise roles" which is very similar to application roles, but are defined at the container (app server) level, and so all applications can use them. Therefore, in a production setup, we also have to map application roles to enterprise roles (for each application) and then associate users to the enterprise roles. This makes it possible for developers to develop applications without worrying about enterprise roles or application roles used by other teams and products.

By default when we enable ADF security , the bounded taskflows and the pagedefs for the pages in the unbounded taskflows are secured. The UBTF is not security aware and cannot be secured as a whole like the BTFs. Entity objects and EO attributes are not secured by default, and requires a grant to be given explicitly.

Tip :  to secure a page that does not use the ADF bindings, we can just create an empty pageDef file by right-clicking the page and choosing "Go to PageDef" . This empty pageDef can then be used to secure the page.

EO (and therefore editable VOs) can also be secured on the basis of application roles. Security is applied on two levels for an EO. On the EO as a whole or on a specific property of the EO. For the whole EO, security permissions exist to restrict read,update and delete on the EO. For EO attributes the permission exists to secure the update operation on any field. Column-wise security can be done on the View layer by toggling the visibility of a table column based on a security EL.

More Details & Example Application

The example application tries to demonstrate various use cases and how to secure various parts and pages in an application.The example is built on the standard HR schema and has two bounded task flows apart from the default unbounded task flow. The example has a landing page, and a taskflow to maintain (Search & Edit) Employees and another taskflow to maintain Departments.


For the example, we shall define the following Application roles in our application :

  • EmployeeAccess - can view MaintainEmployees taskflow
  • DepartmentAccess - can view MainatinDepartments taskflow
  • EmpManager - can edit employee details (except salary)
  • DeptManager - can edit department details
  • SalaryManager - can edit salary for employees
 For the purpose of demonstrating various cases, the task flow is structured as below :


The Landing Page
 The landing page, Welcome.jspx,  is accessible for everyone, but also contains an embedded taskflow that is displayed only to authenticated users who have access to view it. There are links on the welcome page that take the user to other pages and require the user to authenticate before the page is displayed to them. The other pages to search for and edit employees and departments, require the user to have various access levels to perform various actions.Welcome.jspx is a publicly accessible page. It is made public by granting 'view' access on this page, to the 'anonymous-role' built in role. To do this, open your jazn-data.xml and follow the steps below :

The jazn-data.xml editor allows you to associate roles to pages/taskflows

The same dialog is used to set permissions for taskflows (change dropdown marked "1" from webpage to Taskflow). The roles defined will be shown in area marked "3".

In the UI pages we can use the security EL to show hide fields or to make then editable and non editable. If you open the expression builder you will see the securityContext object in the bindings object with a number of very useful methods in it.
Notice the expression to check if the user has permission to view a taskflow, and also the various methods exposed by the securityContext object(click to enlarge)


On the welcome page the following EL is used to render the bounded taskflow as a region


This EL basically checks if the logged in user has access to see the taslflow. The taskflow is referenced by giving the path to the taskflow xml file (relative to the WEB-INF directory) followed by the taskflow name.


At this point its worthwhile to note that permissions are usually hierarchical in nature. The role that can edit the salary for an employee would surely have the permissions to edit and view employees. So in our case the permissions would be like this :
Hierarchical Permissions


The Maintain Departments Page
The MainatainDepartments page and taskflow are secured and is available to authenticated users who have the DepartmentAccess permission or above (see the permission hierarchy above ). With the DepartmentAccess permission the users can search departments and view details, but cannot edit anything, because we will ensure that components are editable only based on the permissions granted to the logged-in user. To edit a department, the user needs the DeptManager  permission. This taskflow is also calledby the edit employee taskflow where an employee who has the permission to edit departments can directly edit a department.
-
The Maintain Departments BTF supports parameters to directly show the edit page for a given department.
The Maintain Employees page
The Maintain Employees page and taskflow are also secured and accessible to people with appropriate permissions. Just like Departments, the user needs an EmployeeAccess  permission to view , and an EmpManager permission to edit details. But in this case, we implement EO level security, by requiring the some users to also have a SalaryManager permission to edit a user's salary. The  permission hierarchy screenshot above should make better sense now. SalaryManager gets to everything, the next lower permission, EmpManager gets to edit everything but the salary, and the lowest permission EmpAccess allows only readonly access The taskflow diagram is below :

The Mainatain Employees BTF is simple and has a taskflow call to directly edit Departments.
The EO level security for the salary is set by selecting the EO attribute to enable security on it.
Enabling security on EO attributes.
Once security is enabled, you need to associate roles to it, or no one will be able to edit this attribute.
This is a little tricky just because the JDeveloper menu is very well hidden !
To associate the roles do this :
Select the EO in the navigator window

Right click the EO attribute in the structure window to get the "Edit Authorization" Menu
This opens up the following dialog :

In this dialog, the application roles are displayed and you can grant the permission to the roles you select.

Showing/Hiding UI elements based on permissions
 Since we mostly use EL to check for permissions and decide whether or not to display some attribute, or set the readOnly property, having this hierarchical form is very beneficial as you see below. The code below is for the first column in the result table on the employee search. This column will render a link which can be clicked to view the employee details and edit them for an 'EmpManager' role, but will render as read only text for people with 'EmployeeAccess'. Now from the hierarchy we have, there is another level above 'EmpManager' and that is 'SalaryManger'. This higher level also needs to be able to edit employee information because by definition, the 'Salary Manager' can do whatever the roles below it can do, plus something extra (edit salary, EO level security in this case). So the EL securityContext.userInRole[''] will return true for and any if its parent roles. So in this case, when a user with the role 'SalaryManager' logs in he sees the link and not the readonly text becasue the expression will return true since 'SalaryManager' is a parent role of 'EmpManager'.

See the highligted EL expressions to see how application roles are referenced

That all the basics. What we have not looked at here is the integration with the WLS security infrastructure and Identity & Access Management tools like LDAP, OID and OAM.

You can download the source code here : http://myadfnotebook.googlecode.com/files/SecurityDemo.zip
To run the project, you can run the Welcome.jspx page. You will notice that some Authorization exceptions are not handled. These were left to demonstrate what happens when an authenticated user tries to access a page he is not authorized for. The exceptions can be handled by exception activities in the task flow , or the navigation links can be shows or hidden based on the authorization of a user.

By default the following users are configured (see jazn-data.xml to view/change these) :
User                  Password                   Role
department        weblogic123              DepartmentAccess
Dmanager         weblogic123              DeptManager
employee          weblogic123              EmployeeAccess
Emanager         weblogic123              EmpManager
empdept           weblogic123              DepartmentAccess & EmployeeAccess
Smanager         weblogic123              SalaryManager

Sunday, October 30, 2011

Get the ID/String Value for an LOV drop-down item though EL


In a previous post we looked at how to get the selected value or text from an LOV in our backing bean. While that approach is effective for most use-cases, there are some situations where you cannot use that approach , or using it is too cumbersome.In this post we'll look at a slightly different approach that can be used when you need to use the ID or String value in EL or you don't want to have a backing bean.

Needing to get the value in EL can be a common scenario when you are trying to extract the selected ID behind an LOV and pass it somewhere, like passing the ID to another bounded task flow. Very common use-case.

To consider an example, suppose you have an app built on the EMP and DEPT tables and you have an "Employee Edit" page. On this page, you have the department the employee belongs to, implmented as a drop down list of Departments ( LOV ). Now lets say you want to have an "Edit Dept" button next to the Department drop-down, which when clicked should take you to an "Edit Dept" page for the currently selected dept in the drop-down. This LOV drop-down on the "Edit Employee" page was created on the EMP VO, for the Dept ID attribute and would use a view-accessor on the EmpVO to map the Dept ID in the Emp Table with the Dept ID in the Dept table and pull the Dept name from that. What we need is the Department ID of the department selected in the drop-down so that we can pull up that department details in the "Department Edit" page when the user selects a department and clicks on "Edit Department".

The LOV when placed on a page, creates a list binding in the binding layer by default and as such is not very useful for us because it stores the index of the selected Item and not the underlying ID. The easiest method to get the current ID is to manually create an Attribute Binding in the pageDef that points to the DeptID on the same iterator that the list binding is pointing to. This means that when the user changes the selection in the LOV, the currency in the iterator will change and since the attribute binding is on the same iterator, the attribute binding will also change.

To get the value in EL, just refer to the attribute binding in EL and not the list binding .
Simple !

Sample application

I'm gonna re-use the sample application from the ADF Security Basics post.
http://myadfnotebook.googlecode.com/files/SecurityDemo.zip
In this application, there is a feature when editing an employee there is s a link go to the edit department page (from the employee detail page). This page has a drop down allowing you to select a department for the employee, but also a link on the side directly takes you to edit the selected department. This link is implemented using the approach described here.