Wednesday, November 14, 2012

ADF Generator for Dynamic ADF BC and ADF UI

Often we implement solutions to automate ADF development, based on custom metadata stored in database. This is common requirement especially for reporting systems, where screens have very similar layout, just number of UI components differ. Reporting systems require parameters capture screens, each report may have different set of parameters. Instead of building separate ADF UI screen for each report - we can build only one, but dynamic. I will describe how we can achieve this with detail sample application.

I have presented this topic on OOW - OOW'12: Oracle ADF Implementations Around the Globe: Best Practices. It was promised by me to post a blog post with sample application - ADFDynamicReportUI.zip.

This sample consists four dynamic elements:

1. Dynamic VO
2. Two dynamic LOV's
3. Dynamic ADF UI Form


There is one proxy VO (read here about proxy VO concept - Proxy ViewObject and Dynamic Editable UI in ADF). This VO gets substituted by dynamic VO on runtime. I'm using this VO to be able to define iterator reference in page definition:


AM offers Client Interface method, this method is invoked from ADF Controller and is the main method responsible for dynamic structure construction:


First thing what this method does - dynamic VO creation along with the attribute creation. Select statement is defined from Dual, aliases for each of the attributes with default values are included (this typically will be retrieved from metadata). We have option to set different properties for the attribute - type, label, mandatory flag, etc.:


Next - LOV View Objects are created along with View Accessors. You should notice that second LOV is created with bind variable (Departments LOV will be filtered based on Location ID). All of this is done dynamically and can be based on custom metadata:


Sequence of the steps is important. LOV mapping with main VO attributes must be done after all View Accessors are defined. Here we map LOV's with attributes and also set LOV display type (Combo, LOV):


Last step - proxy VO is substituted with our dynamic VO:


Take a look now into helper method for LOV View Object creation. If SQL statement contains bind variable, you must set LOV View Object binding style to be BINDING_STYLE_ORACLE_NAME - otherwise will get error on runtime, related to bind variable index. If there are any bind variables, all of them must be defined:


There is another helper method, where View Accessors are defined. If LOV have bind variables, View Accessor bound attributes must be defined here. LOV metadata is constructed here also:


LOV metadata helper method constructs LOV representation:


Dynamic ADF BC code is invoked from ADF Controller, before fragment is accessed - through the custom method invocation:


On ADF UI we are using standard ADF component for dynamic UI - Dynamic Form:


This component is very good, because it doesn't require static attribute mapping in page definition, it allows to render dynamic ADF UI directly from iterator defined in page definition:


We can get parameters from UI easily, by accessing iterator from page definition:


Here you can see how dynamic ADF UI is rendered from dynamic ADF BC. Even validation is enforced, also choice list and LOV UI components are displayed:


Department Id is dependent on Location Id, change Location Id value:


Department Id LOV will be filtered by Location Id bind variable:


All this is generated dynamically from bottom to top:


Values are access and printed in the managed bean, from current row retrieved through the iterator:


Friday, November 9, 2012

ADF BC View Accessor To Centralize Business Logic Processing

I was implementing today one use case, where it was required to compare current row status with the data returned by another query (no master-detail relationship). Such use case can implemented in many ways in ADF - custom method on AM with combination of expression on ADF UI, etc. I decided to go different path and centralize processing logic into VO itself by using View Accessor (same as LOV's are defined in ADF). This allows to simplify implementation part on ADF UI - only simple access to VO attribute will be required, without calling any custom methods from ADF BC (all the job will be done already on VO level).

Here you can download sample application - ViewAccessorSampleApp.zip. This app logic allows to render in green these location lines, where at least one department exists:


There are 2 VO's, no View Link between them:


DepartmentsView VO is designed to check if at least one department exists for the current location. There is bind variable defined:


Here is important point now - Locations VO defines View Accessor (simply add it through the wizard) for Departments VO:


This means we are going to have access to Departments VO result set from Locations VO. Moreover, we can define Bind Variable value declaratively:


To complete use case, there is transient attribute defined of boolean type:


Getter method for this attribute is overriden in VO Row Implementation class. Here we are accessing View Accessor and check if at least one row exists:


And to complete, on ADF UI we only need to set color condition for table columns:


If current location got at least one department - it will be highlighted in green:


Thursday, November 8, 2012

Difference Between Initialized and New Mode in ADF BC

Its always a bit confusing - what is actually the difference between Initialized and New mode for created rows in ADF BC. I have found good information in ADF Developer Guide for this - 27.4.5 What You May Need to Know About Create and CreateInsert. In short - when you create new row, it gets status New. If there is requirement to deregister created (but not yet inserted into DB) from pending changes list - you can set Initialized status for such row. It will keep Initialized status, until user will change attribute value.

I have created small sample application to test this behavior - NewInitializedRowADF.zip. This application implementes two methods in AM implementation class:


These two methods are almost the same, except - row.setNewRowState(Row.STATUS_INITIALIZED) statement in the first method. This methods assigns newly created row with Initialized status. Both methods are invoked from ADF UI. Sample application is based on Employees table from HR schema. This table contains number of required attributes - for the test purpose, I have set default values for each of required attributes (this allows to avoid validation errors).

Test is really simple - calling one method and then checking if pending changes exist, same done for the second method.

Firstly I was testing the method where row is created with the default status New. Pending changes are reported:


Next - method with row.setNewRowState(Row.STATUS_INITIALIZED) statement was tested. No pending changes detected for inserted row:


Setting row with Initialized status is useful, when we want to delay pending changes check. For example, when new row is created with default values from PL/SQL functions - we don't want to consider it as candidate for pending changes in ADF, until user types value by himself.

Saturday, November 3, 2012

Cascading LOV's in JDeveloper 11.1.2.3.0

Blog reader was asking about cascading LOV's support in JDeveloper 11.1.2.3.0 (latest release). Question was based on my old post from 2008 - Cascading LOV's in Oracle ADF 11g Update 1. Things changed since then - its easier to implement cascading LOV's with the latest JDeveloper 11g releases. I decided to update old sample application and describe how you can implement such functionality using ADF BC declarative tools.

Here is updated sample application - CascadingLOV_v2.zip. This sample is based on custom table - Vacationrequests (sql is script is provided). Two cascading LOV's are implemented with one master LOV (Locations -> Departments -> Employees):


There is no need to perform any additional configuration for ADF UI (opposite from before), cascading LOV field will be refreshed automatically. Here we are creating new record and cascading LOV works for the new record:


We change master LOV value to be 1500:


Dependent LOV values for Departments -> Employees are cleared automatically:


Same works for ADF table component, change master LOV to be 1800:


Dependent columns are cleared - bind variable value is reset:


Now I will present 4 steps, describing how this functionality is implemented.

Step 1

Dependent LOV VO must have View Criteria, it filters based on bind variable value:


Step 2

View Accessor from main VO (Vacationrequests) contains bind variable and sets value from the parent:


Step 3

Set Auto Submit = True for master attribute on VO level. This allows to simulate AutoSubmit behavior on ADF UI and reset dependent LOV bing variable value:


Step 4

Set dependency on VO level for cascading LOV attribute from the parent - this will force dependent LOV to clear its value after changes in master LOV:


Tuesday, October 30, 2012

ADF Mobile - Login Functionality

This post will be about new Oracle product - ADF Mobile. While ADF Mobile is deployed as native application, ADF Mobile Browser option is available as well - it allows to build lightweight ADF UI pages and host them on central server (check my previous post from 2011 about ADF Mobile Browser - iPhone Web Application Development With ADF Mobile Browser). New ADF Mobile approach with native deployment is cool when you want to access phone functionality (camera, email, sms and etc.), also when you want to build mobile applications with advanced UI. Same time ADF Mobile Browser remains very important for enterprise customers, because it simplifies development, deployment and maintenance procedure. If you want to expose simple worklist with approval/rejection to mobile interface, it would work just fine with ADF Mobile Browser approach (as per blog post above).

Today I will talk about new ADF Mobile and about Login functionality implementation (read more about it from ADF Mobile developer guide - 17.3 Introduction to Authentication). I will go step by step and describe how sample application is implemented - adfmobilelogin.zip. This archive contains two applications:

1. ADFBasicAuthApp - typical ADF application with basic ADF security authentication enabled. This application will be used as authentication server

2. ADFMobileSecuredApp - ADF Mobile application, with deployment profile for iOS simulator. Implemented secured home page and contains configuration for login page

Firstly I will describe ADFBasicAuthApp, this application contains single ADF page and is enabled with standard ADF Security - ADF Authentication option:


jazn-data.xml contains one registered user (we will test ADF Mobile login with this user) - redsam:


Page - index.jsf, is granted with authenticated access:


Application is deployed on the server and is accessible through URL:


You can see that URL is pointing to our index page. We will use the same URL for ADF Mobile Login functionality configuration. ADF Mobile is authenticating against remote authentication server (our ADF application with basic ADF Authentication) - username/password is passed from ADF Mobile Login page to access protected URL. If access is successful - user is allowed to access ADF Mobile application as well.

We move now to the second part - ADFMobileSecuredApp application. This one is quite basic ADF Mobile application, it contains single ADF Task Flow and page:


There is one feature defined, it is mapped with the ADF Task Flow (it renders home.amx page):


This feature is configured with remote credential authentication (authentication is done with remote secured application - ADFBasicAuthApp application enabled with basic ADF Authentication):


Login page behavior is configured in adfmf-application.xml file. ADF Mobile offers default login page, there is no need to build it (although you can build custom login page also, if you need it) - keep Default option:


We have only one feature, it is listed in Authentication and Access Control section - com.redsamurai.home. We should define Login Server Connection for this feature and point to our remote authentication application:


As you can see - Login URL points towards index.jsf, this is ADF Security protected page from ADFBasicAuthApp. If mobile user will be able to login into this application, user will be granted access to the mobile application also. You should specify JSESSIONID cookie, if authenticating against WebLogic server.

These are main steps in configuring Login for ADF Mobile application.

Here you can see how default Login page looks in iPhone simulator:


Try to login with un-existing user - sking:


It reports error about invalid username/password, as it was expected:


Provide now valid user - redsam/welcome1:


Authentication with remote ADF application is successful, home page is loaded: