Tuesday, August 19, 2014

Accessing ADF Iterator Binding from Value Change Listener

This is a quick hint about how to access ADF iterator binding from value change listener method. Let's say you have generic value change listener, reusable with any kind of input components and you want to get information about underlying ADF BC View Object structure in that listener. Value Change Listener provides access to UI Component, we should evaluate component expression and look up in the bindings for component binding name.

Here is the sample application - ADFIteratorAccessApp.zip. This applications comes with generic value change listener method implemented in the bean. I'm getting value property expression of input component and translating it into attribute name. With the attribute name, I can search in the binding container for attribute binding. From the attribute binding, is possible to retrieve mapped iterator object, iterator could provide information about ADF BC View Object structure:


It works pretty smooth, when generic value change listener is attached to the input component and user is changing value:


Iterator name is printed from generic value change listener, iterator object is retrieved dynamically through attribute definition mapping to iterator:

Tuesday, August 12, 2014

Data Caching Implementation for ADF Mobile MAF Application

If you are building mobile application with web service call integration, you must take into account data caching strategy. Without data caching, mobile application will try to establish too many connections with the server - this will use a lot of bandwidth and slow down mobile application performance. This post will be focused around the scenario of implementing simple data caching strategy. In my next post, I'm planning to review MAF persistence framework from Steven Davelaar - this framework is powerful and flexible. Simple data caching strategy makes sense for smaller use cases, when we don't need to use additional framework for persistence.

Data caching implementation in the sample application - MAFMobileLocalApp_v3.zip, is based on SQLite database local to the mobile application. The whole idea is pretty straightforward, there is a database and Web Service publishing data. Mobile application is reading and synchronising data through Web Service. Once data is fetched from the Web Service, it is stored in local cache, implemented by SQLite DB. For the subsequent requests, mobile application is going to use a cache, until user will decide when he wants to synchronise data from Web Service:


Sample application implements a Web Service, based on ADF BC module. This Web Service returns Tasks data (SQL script is included with the sample application):


Besides fetching the data, Web Service implements Task update method:


On the mobile application side, use case is implemented with a single Task Flow. Task list displays a list of tasks, user can edit a task and submit changes through Web Service. This change is immediately synchronised with local cache storage. User is able to refresh a list of tasks and synchronise it with a Web Service. During synchronisation it will clear local cache and populate again with the data returned from Web Service:


Data caching logic is handle in TaskDC class, Data Control is generated on top of this class, this makes it available through the bindings layer. Initially we check if cache is empty and load data from the Web Service, for the subsequent requests data is loaded from cache. Unless user wants to synchronise with Web Service and invokes refresh:


There is a method responsible for fetching data from Web Service and translating it to the Task list structure:


Data from cache retrieval is implemented in the separate method, we are querying data from local SQLite database:


When request hits TaskDC Data Control, we are checking if there are any rows in cache. If there are rows, call to Web Service is not made and rows are fetched from cache:


When user is synchronising with the Web Service, cache is cleared up and re-populated with the rows fetched from Web Service:


Update is synchronised with local cache, so there is no need to re-fetch entire data collection from Web Service:


If the local cache is empty and Web Service is invoked to fetch data, we can see this is Web Service log - it executes SQL. Later call to Web Service is not made, data loaded locally from SQLite database:


We can track update operation on the server side as well, Task details are updated using Task Id:


Initial load for the task list, this is what you should see if Web Service and MAF mobile applications runs correctly:


User could open specific task and edit task properties - changing status:


Task description could be modified:


All changes are saved through Web Service call and immediately synchronised with local SQLite database:


Selected task is updated, user is returned back to the list of tasks:


We could simulate data update on the server, lets change status for one of the tasks:


With refresh option invoked, data is synchronised on the mobile application side and local cache gets refreshed:

Thursday, August 7, 2014

ADF Thematic Map in ADF 12c (12.1.3)

ADF Thematic Map component from DVT library was updated in ADF 12c with marker zoom option and area layer styling (ADF 12c (12.1.3) new features). I have decided to check how it works and implemented quick sample application - ThematicMapApp.zip.

I was using world GDP data (SQL script is available together with sample application) and displayed it using ADF Thematic Map. World country borders are hidden on purpose, borders are visible by default:


While zooming, marker points are growing - very useful feature:


Data for thematic map is fetched using SQL based VO. I'm calculating total GDP and taking percentage from total for the country, this allows to scale marker points better:


ADF Thematic Map is configured to support zooming for markers:


Countries area layer is set to be hidden, although data is still gets attached to the countries:


Marker is configured with dynamic scaling, this is how each country gets appropriate marker size, based on its GDP value:


Marker colour property is set to be dynamically calculated in marker Attribute Groups section:

Tuesday, August 5, 2014

Standard ADF BC Passivation/Activation for Transient View Object

If you want to implement transient View Object in ADF BC, you must make sure it will be passivation/activation ready, otherwise you may loose data. There are several ways how to achieve passivation/activation for such View Objects - override passivation/activation lifecycle and handle transient View Object rows programmatically or reinitialise transient View Object rows from Application Module prepareSession method. There is one more solution, I'm going to describe it in this post. It is based on dummy SQL based View Object, designed to to store transient attribute values.

Sample application - ADFTransientVOPassivationApp.zip, implements SQL based View Object with transient attributes. Instead of creating completely programmatic View Object, I have created SQL based with single Id attribute based on SQL expression and added transient attributes. This Id attribute is actually never used, it is there just for only reason - to simulate SQL based View Object. As a key attribute is selected one of the transient attributes:


SQL query doesn't fetch any rows, I'm using it only for a single reason - to simulate SQL based View Object. ADF BC knows how to passivate/activate SQL based View Objects automatically, so I'm going to use this feature and force passivation/activation for all transient attributes created for the same View Object:


Just make sure to select Passivate Including All Transient Values option, this will ensure all transient attributes will be passivates/activated automatically, without any coding intervention:


I'm going to test sample application with AM pooling off, this would simulate passivation/activation behaviour for each request:


On ADF UI side, I'm going to implement a table. To be able to enter rows successfully, for such SQL based View Object with transient attributes, I must enable ChangeEventPolicy = ppr option in Page Definition for the iterator:


Input components must be set with AutoSubmit = true option:


On runtime, when I enter rows, all data gets passivated - you can see this from the log. Three rows are entered, data for all attributes gets passivated/activated automatically:

Sunday, August 3, 2014

Handling Rollback Operation for ADF Input Components with Immediate Property

One of my colleagues is implementing advanced dynamic ADF BC/ADF UI functionality. To force validation to be invoked properly, he must use ADF UI input components set with Immediate=true property. This allows to keep validation messages always displayed, even if user navigates to edit another dynamic ADF UI input attribute, until form is submitted or canceled. However, as by JSF design - usage of input components with Immediate=true, blocks execution of command components, if there are validation errors available. This means - user can't use Cancel button to reset the form with validation errors, until he would fix these errors manually. However, there is a potential solution - we could use ADF subform component to isolate input components, with a combination of ADF View reload to refresh rendered UI.

Sample application - ADFAttributeImmediateApp.zip, implements  basic ADF Panel Form Layout with a set of input components. Each of these input components is set with Immediate=true property:


Let's say there is validation error on the screen for input text component with Immediate=true property:


Try to press Cancel button - no action will happen, it will continue complaining about validation error:


This is how it supposed to be - by default, Cancel button will not be invoked, because Immediate=true validation from input component would block it. We could improve it and adjust for our specific scenario to make sure Cancel button will be invoked, even with validation errors on the screen. We should surround input components with ADF subform component, this allows to isolate from Cancel command:


Cancel button must stay out of ADF subform, this will make it possible to invoke Cancel action listener method, even with immediate input components available on the same screen (but surrounded with ADF subform):


Action Listener for Cancel button gets invoked and reset happens now, no matter if there is validation error for input component with Immediate=true:


There is one extra bit - even with Rollback operation executed, UI would stay unsynchronised and keep displaying validation message until next submit. It requires to force ADF view refresh - you should recreate ADF view programmatically from the same method, where you are invoking Rollback operation:

Saturday, July 26, 2014

Oracle BPM 12c Installation Improvements and Issues with Mac

Oracle BPM 12c is improved with a great installation process - simplified and stable. You only need to download single installation package, run a wizard and after several clicks it gets installed. All required products are installed for you out of the box, no extra configuration is needed - JDeveloper, BPM/SOA extensions, BPM/SOA schemas in Java DB. Developer can focus on his development tasks, no need to spend days to install and configure development environment. You should read official guide - Quick Start for Oracle Business Process Management Suite.

Installer works on Mac OS platform, you can install entire Oracle BPM 12c infrastructure and run domain. However, it fails to open Human Task wizard, while running JDEV on Mac OS. I have developed extremely basic Oracle BPM 12c sample application, to test Human Task wizard with JDeveloper installed on Oracle Enterprise Linux and on Mac OS - BpmApplication.zip.

It works fine to load Human Task wizard with JDeveloper 12c installed on Linux:


The same Human Task fails to open with JDeveloper 12c installed on Mac OS. There is Null Pointer exception generated, thrown from JDeveloper IDE class:


Messages in JDeveloper log for this exception:


Probably you should not use Oracle BPM 12c for development on Mac OS, rather use Linux or Windows platforms. This is a bit pity, but on other hand JDeveloper extensions (except ADF Mobile) always had issues running on Mac OS. It should be no difference, but it seems like development on Linux or Windows with JDeveloper is more stable.

Friday, July 25, 2014

MDS Support for Mobile Application Framework (MAF) in JDeveloper 12c (12.1.3)

MAF framework in JDeveloper 12c (12.1.3) comes with MDS support. This means, we can customise mobile applications in similar way as we customise regular ADF Web applications. I'm going to explain and demonstrate with the sample application, how it works in MAF 2.0. You can read about it more in MAF 2.0 developer guide, Customizing MAF AMX Application Feature Artifacts.

Sample application, tested with iOS platform - MAFMobileLocalApp_v2.zip. Original version of this application brings Locations screen, where both City Name and Street Address are displayed:


We are going to customise original application with MDS, without changing source code directly. Customized application is based on two MDS tip layers - gold and silver level partners. Gold level partners are able to see State Name in addition to the Street Address:


While silver level partners are allowed to see only City Name:


To achieve MDS functionality behaviour for MAF application, you must define first MDS customisation class, this class must extend from standard MDS CustomizationClass and implement several methods. Important method is getName(), you must define MDS customisation name, the same name will be used for customisation (JDeveloper automatically reads this name during MAF application design time):


Customization class must be set in add-config.xml MDS section, in order to be registered for customisation use:


Once customisation class is registered, we can switch JDeveloper to the Customization Developer mode and start customizing application:


Make sure MDS layers are properly configured in CustomizationLayerValues.xml file. Customization layer must be set to the same name as you set in Customization class above. Layer values should specify different layers supported for customization:


I have defined two layers - gold and silver partnership. MDS layer can be selected for customisation, we start from Gold:


Locations page is updated to include State Name:


However, actual change is stored not in Location page, but in generated MDS file for Location page - it keeps delta for the changes made in customization mode. This file is generated under Gold Partnership profile folder:


State Name addition required to update Page Definition file for Locations, there is extra MDS file created with delta information for Locations Page Definition:


Next we can customize for Silver layer - change layer value:


Here we should keep only City Name and remove Street Address:


This change is reflected in MDS delta for Locations page, stored under Silver Partnership level: