Wednesday, January 9, 2013

LOV for Editable Primary Key in ADF Table Problem

Probably every ADF developer at least ones was facing this problem - creating LOV for editable primary key attribute rendered in ADF table. Very often database design is based on business key and there is requirement to create LOV for that key. Unfortunately ADF doesn't handle this case well - LOV defined for editable key in the table is unstable. There are different workarounds, but all of them with the side effects. The best workaround is to fix database design and introduce surrogate key for the table - but in practice is hardly possible, no one wants to change DB design, especially if it works well in Oracle Forms.

My idea was to upload sample application with this use case into Oracle Cloud. Everyone could access and test it, I'm sure most of you had reproduced same error in your projects. Ideally - Oracle ADF should handle LOV for editable primary key. Please access live sample application on Oracle Cloud and see it yourself - EditableTableKeyApp on Oracle Cloud. Same application can be downloaded - EditableTableKeyApp.zip.

Here is how you can test it live. Open application on Oracle Cloud, you should get Employees table displayed:


Open EmployeeId LOV - you will see Departments data, this is correct. I was using numeric Department Id to return into Employee Id - this is just for test, to avoid numeric data duplication. Select value from LOV and try to return it:


Infamous error will be generated - Target Unreachable, identifier 'row' resolved to null:


This happens only for LOV defined on primary key attribute. LOV defined for non key attributes works well in ADF table.

This problem is not reproduced with ADF form, same LOV works:


Value was returned without issues:


This is why I was proposing option to use ADF form for editing data from the table - CRUD Operations in Oracle ADF 11g Table Without Auto PPR.

By the way - Oracle Java Cloud runs with JDBC XA driver, this is not compatible with ADF BC for Rollback operation. If you click Undo button and invoke Rollback operation - your data will disappear:


Click again Undo couple of times - data will be back.

In this sample I was using LOV defined on primary key attribute and rendered with editable table:

Monday, December 31, 2012

My ADF Sample Apps Live in Oracle Java Cloud

With Oracle Java Cloud available for ADF PS5 deployments, I decided to deploy all my future ADF sample apps from the blog in Oracle Cloud, source code will be provided as well as it was up till now. ADF sample applications live will help to explain and present ADF functionality even better, blog readers will be able to test described functionality straight away and provide feedback without downloading and running on their machines. Currently I'm running trial instance of Oracle Cloud for database and Java, but in future I plan to purchase permanent account - let's see how it will go.

Read more about Oracle Database Cloud and Oracle Java Cloud from official documentation. Oracle Cloud right now supports ADF PS5 with certain limitations, please check documentation - however most of the sample apps will run without issues.

I have deployed in Oracle Java Cloud and tested one of the sample apps from my blog post - Tree Table Component in Oracle ADF. This app renders hierarchical data in different levels of the tree, Master-Detail relationship between two tree tables is implemented as well. Original sample app is deployed with minimal changes described below (datasource name and login config are optimized for Oracle Java Cloud). Here you can download source code for ADF app deployed in Oracle Java Cloud - TreeComponents_cloud.zip.

This app is deployed for public access, you can open it by clicking here - Tree Components in the Cloud. Sample app will be loaded and you should see two tree tables rendered with hierarchical data from sample HR schema (see URL pointing to Oracle Java Cloud instance):


We can use Oracle Cloud Service Control for Java to see a list of deployed apps - TreeComponentsApp is one of them. You can find here JNDI Location for Data Source, we will use it in Application Module - database. ADF Application Module will be using it to retrieve data from database Oracle Cloud:


We can review ADF performance for deployed apps - AM and ADF Task Flow usage:


You can deploy ADF app directly using Oracle Cloud Service Control for Java, but same is possible from integrated JDeveloper 11g PS5 environment. You should download latest JDeveloper 11.1.1.6.0 optimized for Oracle Cloud. Apparently Oracle released two JDeveloper versions under the same release number 11.1.1.6.0, Oracle Cloud release was made public around October. So, if you have old 11.1.1.6.0 - remove it and download new one. You should see OCLOUD name in JDeveloper 11.1.1.6.0 build:


I will describe now, what changes I have made to original ADF sample app in order to be able to deploy it and run in the cloud. Firstly you should change JDBC Data Source name for AM configuration, it must be set to database JNDI name, same as it is defined for us in Oracle Cloud Java. This allows to fetch data from Oracle Cloud for database:


Next Application Server connection pointing to Oracle Cloud Java instance must be defined in JDeveloper. Choose connection type - Oracle Cloud:


Provide connection details as per Oracle Cloud documentation and you are almost done.

Almost - because there is just one additional config - ADF application login method handling. By default ADF app is protected by Oracle Cloud security, but I want to make my ADF sample apps public and accessible to everyone. For this reason, I need to include empty login configuration into web.xml - the rest will be handled by Oracle Cloud and ADF app will be public accessible:


This config was suggested by Oracle Cloud automatically, when I was trying to deploy sample app. Deployer creates optimization suggestions and lists them in the deployment log accessible from JDeveloper:


Thats all about ADF deployment to the cloud - very straightforward. Now few words about database schema in the cloud. As usual - I'm using sample HR schema for my sample ADF apps. You can access Oracle Cloud database instance directly from JDeveloper, read this white paper - Data Movement and the Oracle Database Cloud Service. Data can be imported and exported from JDeveloper. However, there is another quick way to populate Oracle Database Cloud - using SQL scripts. Open Oracle Database Cloud instance and go to SQL Scripts section:


I was using HR schema SQL scripts and generated all required tables and populated data:


HR schema data is in the cloud and ready to be accessed from ADF app deployed in Oracle Java Cloud:


I was testing ADF passivation/activation to see if PS_TXN table is automatically created in Oracle Database Cloud. Yes, table was created automatically - perfect:

Sunday, December 30, 2012

After Commit Call for Centralized Transaction Management

With this post I would like to update sample application from my previous post on this topic - Centralized Transaction Management for ADF Data Control. This previous post was about how to call global commit/rollback operations applied for ADF Data Control, without declaring Commit and Rollback in each and every page definition file. Centralized Commit and Rollback operations are created in fragment template, this allows to reuse the same buttons across different fragments. There is one bit we can use to extend centralized transaction management concept - custom method invocation after successful commit. Based on use case requirements, we may need to invoke iterator refresh after commit, etc.

Updated sample application - GlobalTransactionControlApp_v2.zip, implements after commit call. User is changing data and commits transaction with Save button:


Separate method with after commit logic is invoked, this time it just prints static text:


I will describe implementation steps below. Firstly we should provide our custom after commit method name into fragment template - where transaction is commited. For this purpose you can define new attribute for page template definition:


You can look into provided sample application and find there afterCommit attribute defined, we will pass our custom method name through this attribute:


Now take a look into global commit method itself. Two additional lines were added - retrieve custom after commit method name from page template attribute and invoke it as method expression using JSF API:


Method expression construction method is standard, it constructs method expression for any method signature returning void and without input arguments - this is important, otherwise you will need to update invokeMethodExpression method code to support return and argument types. When method expression is constructed, it invokes referenced method:


We move now to consumer part and open fragment, based on our template - depsEmplsView.jsff:


Select af:pageTemplate tag and open Properties window - you should see our custom afterCommit property included into template properties. Provide custom method name, including backing bean name (no need to specify expression brackets, these will be added automatically):


Make sure such bean is defined in the ADF task flow:


Take a look into method invoked after comment signature - no return value and no arguments:

Monday, December 24, 2012

Conditional Validation in ADF BC

ADF BC offered out of the box business validation support is quite advanced - allows to control validation execution conditionally. Still some functionality is missing - easy configuration for execution order. Now we have entity and attribute level validations, but really this doesn't give any guarantee that entity level validation will not be invoked when attribute value is changed (especially true for ADF table component). In the future ADF versions I would like to have more control over validation execution order and time. This post is to demonstrate what is available now - conditional validation execution. Validation rule can be executed conditionally in ADF BC, for example depending on user security role (based on use case requirement, we may want to skip certain validation for the super user).

Sample application - ConditionalValidationApp.zip contains validation rule implemented for Salary attribute value check:


Conditional execution expression for the validation rule is based on Groovy and is accessing ADF security context to evaluate if super user role is granted to the current active user:


If current use is not a super user - validation rule will be invoked.

Don't forget to set AutoSubmit=true on the ADF UI for the field to be validated (this is typical ADF beginners mistake) - otherwise validation will not be displayed immediately after data change:


There are two users (both with welcome1 password) defined in the system, one of them is super user:


Test with super user - redsam1:


Change salary value to be 300, less than 500 - validation is passed for super user:


Test with regular user - redsam2:


Change salary value to be less than 500 - validation is executed for the same Eemployees EO:

Friday, December 21, 2012

Skip Validation for ADF Required Tabs

Tell me - how often it happend to implement such basic layout where required attributes from one Entity are located on the same fragment/page but in different tabs? I guess quite often, this is common requirement. However, is not so obvious how to implement it properly. Most likely you will end up into infinite loop of validation errors for required fields when trying to switch between tabs. I will describe in this post how to implement multiple tabs with required attributes from the same Entity and avoid unexpected validation errors.

Sample application - TestValidationApp.zip is based on Employees EO and contains two tabs - Contact and Details. Half of Employees attributes are located under Contact and the rest under Details tab:


Firstly I will show you how it works by default. Press Create button, this will call CreateInsert operation and insert new row (attributes from this row will be initialized blank in both tabs):


Type values for required fields and try to open second tab - Details. Validation errors are displayed for missing attribute values in the second tab. But wait a bit - we want to open Details tab and already getting validation errors? This makes our form unusable:


Let's make first attempt to solve this problem - set Immediate = true for both tabs. In theory this should help, in practice it doesn't. Immediate = true allows to skip validation lifecycle, but as a side effect it prevents Model update and value is not set.  Immediate = true will not solve described issue, but still let's test it - I will show you why Immediate = true doesn't help at all. Select both tabs in JDeveloper:


Set Immediate = true property for both tabs:


Do the same test again - create new record and type required values in the first tab:


Because of Immediate = true - we can open second tab without getting validation errors. Type required values in the second tab and press Save. Validation errors are reported for the required values in the first tab. This is quite a magic, actually not - this happens because of Immediate = true - entered data is not stored on the Model:


Set Immediate = true to be false for both tabs, as it was originally:


Solution will be described now. Open page definition file and select root tag in the structure window:


Go to Properties window and search for SkipValidation property. Set SkipValidation to true:


This allows to prevent such silly validation execution as you saw above. Enter required values in the first tab:


Switch to the second tab - enter required values there. Press Save button to commit transaction - no errors this time:


SkipValidation = true doesn't affect regular ADF validation behavior - if required field value is missing during transaction commit - ADF will stop processing and ask user to provide a values as expected: