Sunday, May 29, 2011

Controlling ADF BC Attribute Insert Security

As we all know, its possible to define attribute level security for ADF BC EO and control update operation. However, there is one catch - users granted with create access for the same EO, will be able to insert values into restricted fields during new row creation. These values will be stored during new row commit, typically we would like to avoid such situation and preserve consistency between different modes (update or create) for the same EO attributes. We can achieve this by overriding EO create() method and checking EntityAttributePermission class against row attributes.

Download sample application - ManagerId and DepartmentId attributes are selected to be editable only by managers-role:

There is user in the system, who is not granted with managers-role - redsam2:

Let's use redsam2 user to perform our tests:

This user is not granted editing privileges for ManagerId and DepartmentId attributes, as expected these fields are disabled:

Press Create button now - disabled fields are becoming enabled, user can type data and commit:

Unauthorized user can save values for these fields, user is not authorized to update:

We can prevent such behavior during new rows creation by overriding ADF BC method - create(), on EO level:

Through this method we can access attributes of newly created row and check security permissions against those defined in jazn-data.xml. We can assume, if user don't have editable access to certain attribute, same level of security restriction must be applied for newly created row as well. We are iterating over the set of attributes and through EntityAttributePermission class validating if current attribute can be updated by current user. If no, attribute is set with readonly flag:

It works now much better - secured attributes for update, are protected during new row creation as well:

Saturday, May 28, 2011

Extending WebCenter 11g PS3/PS4 ADF Task Flows - RSS Example

Oracle WebCenter 11g PS3/PS4 allows to extend standard WebCenter product task flows, original Oracle library files are not modified - all customizations are stored inside MDS repository. Thats really powerful feature, quite often we can hear customer requests to customize one or another item for out-of-the box functionality. Because all changes are stored inside MDS, we are safe when doing migrations from one WebCenter release to another, just need to apply previous MDS. As per documentation - 24 Customizing Task Flows, only View level customizations are supported in current release. Will be waiting for ADF Model and Controller layers to be supported as well.

I will walk you through WebCenter RSS task flow customization example - In order to customize WebCenter task flow, you need to install Oracle WebCenter Customization Framework Design Time extension, as per documentation link mentioned above.

WebCenter RSS task flow looks like this:

It brings news items, however is not so convenient to read. Let's say, we would like to have more space between news items and news link to be highlighted in bold. No problem, we can customize this and store our changes in MDS.

This task flow is pointing to certain RSS feed location and brings data from the internet directly into your WebCenter portal application:

This task flow is part of WebCenter product task flows:

Once RSS task flow is added into your application, we can customize imported WebCenter library. As I already mentioned, you should have installed WebCenter customization extension. Second step would be to enable Seeded Customizations for your Portal project:

Restart JDeveloper in Customization Developer mode:

WebCenter application will be marked for customization with MDS:

Enable Show Libraries option, this will list all imported libraries, among then WebCenter libraries want to customize:

You will perform customizations on "site" level, this means MDS customization will be applied on application scope:

Locate WebCenter RSS library from imported libraries list:

Expand library contents and open RSSViewer.jsff fragment, this is main fragment for WebCenter RSS task flow:

We can explore fragment contents, for example there is refresh icon - but rendered property is set to check for authenticated users. We don't need that, so I can remove this condition and make it default:

Set rendered property to default (true) - change will be stored in MDS file:

Change RSS item link to be rendered in bold:

There is no spacer between RSS messages:

We can add one - this will make messages more readable:

All the customizations are stored inside designated MDS file for specific resource (RSS fragment in our case). During deployment, this file is uploaded into MDS repository and applied later on runtime, during rendering. Its how standard functionality is adjusted on runtime, based on available MDS data:

Take a look, RSS news became much more readable now - and still using same WebCenter RSS task flow. Refresh icon now is available as well:

Sunday, May 22, 2011

Oracle WebCenter 11g PS3 ADF Security Login Bean

When you generate new WebCenter 11g PS3 Portal Framework application in JDeveloper 11g, it creates login/logout pages and configures ADF Security. However, it generates basic login page, this can be improved by using new WebCenter 11g PS3 security login bean. With WebCenter 11g PS3, we have out of the box bean (o_w_s_l_LoginBackingBean), which can handle login/logout functionality without writing any custom code.

Download sample application - Here you can see basic auto-generated login page structure for WebCenter 11g PS3 Portal Framework application:

I will reuse the same template for login page, but will change content structure. Will be using ADF Panel Form layout, username and password fields mapped with WebCenter login security bean, as well as ADF action button calling WebCenter login bean method for authentication:

Username field is mapped with o_w_s_l_LoginBackingBean userName property:

Password field is mapped with o_w_s_l_LoginBackingBean password property:

Action method for Login button is pointing to doLogin() method from o_w_s_l_LoginBackingBean:

Run portal application, will be redirected to Login page, login as redsam/welcome1 - o_w_s_l_LoginBackingBean will handle authentication process for you:

Authentication is successful - we are inside portal space:

If authentication process fails (wrong username/password, etc.), o_w_s_l_LoginBackingBean returns error message:

You may have valid question, how we could call required custom functionality, before o_w_s_l_LoginBackingBean login authentication method is invoked. Because login authentication is done by calling Action method, this means we could process before login logic from Action Listener method - let's create Action Listener method for the same Login button:

Inside Action Listener method, we can access both username and password values from o_w_s_l_LoginBackingBean, perform required actions and update (if needed) username and password values:

As you can see, for test purposes I'm changing username to scott. With current test case, when user provides username, for example - redsam:

Username will be changed to scott automatically, this user exists in ADF Security store as well:

Sunday, May 15, 2011

Target MDS Repository for ADF Applications Deployment

JDeveloper 11g MDS wizard for ADF application doesn't provide target MDS repository configuration options, you can specify only file based repository location:

Only when deploying ADF application enabled with MDS functionality directly from JDeveloper, wizard asks where we want to target MDS repository and specify partition name:

This works fine, when deploying directly from JDeveloper. However, very often deployments are done from deployment automation (Hudson with OJDeploy, etc.). In those cases, we don't have option to specify target MDS repository through the wizard.

By default, target MDS repository is configured in adf-config.xml as file system repository:

We can try to change this and point to database MDS repository, one that should be used after deployment:

However, OJDeploy fails to locate specified JNDI connection - target MDS location with database details is ignored and not included into deployment package:

If we try to deploy such EAR from Hudson automation, errors for target MDS repository are generated - naturally, because required information is missing. Its same as we would try to deploy EAR through Enterprise Manager, it asks to provide mandatory missing information for target MDS repository:

Possible solutions for automated deployment? Looks like only one - you need to write additional script, which will access packaged EAR and substitute target MDS repository values, right before EAR deployment. This would work, because EAR is already generated - we would simulate target MDS repository wizard action - substitute target MDS repository values in adf-config.xml with database details:

Now EAR contains information about target MDS repository, automated deployment will succeed:

Download sample application - You can find sample adf-config.xml file inside application_root/deploy folder, this file contains target MDS repository configuration with database details.

Saturday, May 14, 2011

ADF Business Components Entity Object Read Permission or (1 = 2)

One more interesting thing encountered this week, during integration of ADF Task Flows into WebCenter 11g PS3. We were using ADF library JAR files and integrating ADF Task Flows into WebCenter 11g PS3 Menu Model. ADF Task Flows were rendered fine inside WebCenter, however data was not coming. Funniest thing, while checking detail log, we saw that ADF appends multiple (1 = 2) conditions to original SQL statement - naturally its why data was not queried, but why (1=2) was appended? First we thinking, may be WebCenter is playing some evil games and modifying SQL statements on runtime. However, at the end it was proved WebCenter was unrelated to this problem, problem was related to ADF Security and ADF BC EO's permissions. The thing is, some of the EO's from common library were enabled with ADF Security read permissions and packaged into ADF libraries. Once such EO's are imported into secured ADF environment, permissions are evaluated on runtime - if user is not granted with read permission, no data is returned. Okej, but what we really didn't expected, is to see ADF generating (1=2) conditions for those EO's, where we didn't had permission to read.

Download working sample application - Below I will explain complete scenario for this example.

Main ADF application imports ADF library JAR file with common EO objects:

This application implements local EO for Employees and is using two imported EO's two create SQL Join with Employees:

As I was explaining above, Departments and Jobs EO's are coming from ADF library.

We login into our main application with user redsam/welcome1:

Page is rendered correctly, but no data is returned:

If we check generated SQL statement, we will notice (1=2) condition applied two times:

Why two times? Its because we join two imported EO's into main VO. These imported EO's are enabled with ADF Security permission. So, ADF instead of checking if user is allowed to use EO for query, just appending (1=2) condition and sending SQL for database processing. I don't want to criticize this, but imagine having complex VO with multiple joins - generated SQL always will be sent for database processing, isn't it bad for performance? It would be smarter to verify EO security read permissions earlier, in the middle-tier - and not to generate SQL when there are clearly no results will be returned.

It was quite hard to believe (1=2) is generated because no authorization to access EO for reading. But indeed, our EO from reusable library was enabled with security for read access:

We copied required EO read security permissions into main application jazn-data.xml:

Permissions are declared now and visible inside main application:

SQL join is performed correctly, data is returned: