Friday, May 30, 2014

Default tab closing icon in ADF UI Shell is located in the top right corner. Users are not really happy about this and there is a demand to have the same positioning as you can see in the Web browsers - directly on the tab. Tab placeholders are implemented in ADF UI Shell with af:navigationPane and af:commandNavigationItem components. Component af:navigationPane supports item removal, this means we can implement tab closing functionality directly in the tab. Unfortunately, out of the box ADF UI Shell template in ADF 11g and 12c is not updated with this adjustment. I will explain how you can implement by yourself, you would need to change ADF UI Shell source code.

Component af:navigationPane is set with itemRemoval="all" property. This renders and supports tab closing directly in the tab itself:

Component af:commandNavigationItem must be set with itemListener, this allows to implement a custom listener method to close current tab:

By default, close icon becomes visible, only when user moves mouse focus on top of the tab. This could be misleading for the users. However, there is a fix with custom CSS - you can define icon for disclosed and undisclosed tab:

Tuesday, May 27, 2014

I was investigating performance impact of navigating between tabs in UI Shell template. To compare, as alternative solution for UI Shell, I was using dynamic tabs with Multi Task Flow binding (Building Custom UI Shell with ADF 11g R2). When you switch between tabs in UI Shell, you could notice slight delay. This is normal delay (differently to browser tabs, where no delay), as there should be generated response from the server and JSF tree must be updated. However, it is not clear what is the impact of such delay to application performance. The goal of my post is to answer this question.

Multi Task Flow binding is a new feature since ADF 11g R2, list of task flows can be referenced from the Page Definition:

This list can be rendered on UI with dynamic tabs, each tab would be physically created (in UI Shell case, only one region is rendered at a time):

Second project is using UI Shell template:

UI Shell doesn't render real tabs, instead it is using navigation pane component with links, displayed as a tabs:

Only one region is rendered at a time, the one you select. This means, when tab is changed - different region will need to be rendered again:

I was navigating through tab items for both solutions and recording tab opening time. Here are the results.

Multi Task Flow Binding:

- Departments: 0.29 sec.

- Employees: 0.47 sec.

- Locations: 0.59 sec.

Average: 0.45 sec.

UI Shell:

- Employees: 0.61 sec.

- Locations: 0.55 sec.

- Departments: 0.28 sec.

Average: 0.48 sec.

You can see, both are almost the same. There is 0.5 second delay to open tab for a relatively simple UI with a form and editable table components. In the real scenario, with more complex UI, delay could grow to couple of seconds.

One second or couple of seconds delay is generally acceptable in UI Shell, for navigation between tabs. If delay is longer than that, something must be wrong in your application - slow data fetch or slow table initialisation, could be one of the reasons.

Tuesday, May 20, 2014

I bet you are familiar with ADF Query UI having many criteria items. This may look irritating to the users, as there are so many options to use for the search. I will describe alternative approach in this post, with MDS user persistence and personalisation involved. It might be more user friendly, to offer only few criteria items by default and allow to add other items through ADF Query advanced option, together with MDS user persistence feature enabled for personalisation. Post is based on sample application from - ADF Query Saved Search in ADF 12c.

Here is updated sample application, for today post - SavedSearchApp_v2.zip. As you can see, there is minimal criteria set is available by default:

User could add additional criteria items he needs, like Email and save modified criteria for the future use:

Logout/login and personalised criteria for this user will remain available - quite cool. User could work only with criteria items he finds useful, this would make screen lighter also:

I hope such quick insight about ADF Query personalisation and criteria items optimisation will be useful for your project.

Thursday, May 15, 2014

You may have a requirement to apply different format for date type attributes, based on username, as for example. Different users, may use different date formats - in such case, formatting for date type attributes must be set dynamically. This can be achieved, using approach described in my previous post - Controlling ADF BC Mandatory Attribute Validation Conditionally. I would extend explained technique and apply it for date formatting.

Sample application for download - DynamicFormatADFApp.zip. Here you can see two different browser sessions, two different users and different date formats applied in both cases. dd/MM/yyyy is applied for redsam1 and yyyy/MM/dd for redsam2:

ADF UI is standard for a inputDate component in a form - format is set through a standard EL expression in convertDateTime tag by referencing format property from AttributeDef object:

EL expression to get a format for the attribute, rendered in ADF table is changed slightly (otherwise, with default EL expression, overridden getFormat method is not invoked):

Generic View Row Implementation class must override createViewRowAttrHints and getAttributeHints methods - this would allow pass a custom format to be applied on ADF UI dynamically:

Finally CustomViewRowAttrHintsImpl class overrides framework method getFormat (this method is invoked from ADF UI EL for format property automatically). Here we could check for a username and return dynamic format (in real use case, this logic can be more complex):

Sunday, May 11, 2014

I bet one of the most common doubts ADF developer, or may be DB admin, has - why VO SQL executes slower than the one identical from SQL Plus? This is often the case, but there is nothing VO SQL to blame about. Usually VO SQL executes in almost same time, as it would execute in SQL Plus - but there is extra added time of row fetch. When ADF UI page is rendering, data becomes available after VO is executed and rows are fetched from result. These two separate technical actions, look like one for ADF UI user - data will not be displayed, until it is not fetched. So, there is extra time for row fetch on top of VO SQL query execution. This is why - displaying data in ADF UI, could be slower than displaying it in SQL Plus.

You should tune number of rows fetched by VO's, the worst practice is to set Range Size = -1 and fetch all rows at once. This is going to consume significant amount of memory to create many ViewRowImpl objects and waste time. Make sure to fetch only such amount of rows, close to be required for display on UI or any back-end operation.

I'm going to show you with a practical test - how time differs between VO SQL execution and row fetch for simple Employees table with 107 rows fetched as total. Here you can download sample test case application - ADFFetchApp.zip.

There is one iterator in Page Definition, for Employees VO:

I have set this iterator with Range Size = -1, to fetch all rows. I have seen the use cases, while reviewing and tuning ADF applications, where developers are using Range Size = -1 without actually understanding what a side effect for runtime performance it could create. Afterwards, it is common to blame ADF for a mystery, well hard to blame. Anyway, here is my test case Range Size = -1 setting for Employees iterator:

Sample application comes with a generic VO implementation class. There are two methods overridden here - executeQueryForCollection and createRowFromResultSet. In the first method, I'm tracking how long it takes to execute SQL for given VO. Second method tracks total time to fetch all available rows from Employees table (remember Range Size = 1 from above):

Fetch time is initialised, before constructing first ViewRowImpl object and stopped with the last row.

Just run sample application, after test page with Employees rows will be rendered you could check execution times and compare them:

In average it runs as following: 15 milliseconds for VO SQL query execution vs. 94 milliseconds for total row fetch:

As you can see, time added by row fetch operation could be quite significant and it makes sense to tune and ensure optimal row fetch in your application. SQL query is not only one thing to blame, when VO performance is slow, it could be you are fetching too many rows.

Tuesday, May 6, 2014

We have new improvements in Red Samurai ADF Performance Audit tool. Update 3.1 is focused on new features in drill down reports for Slow Queries and Large Fetches.

Current day occurrences (in red) for Slow Queries are calculated per individual VO instance, along with latest occurrences (in yellow) and total occurrences. This helps to track outcome of performance fixes and understand if additional tuning is required for specific VO instance:

It is possible to select VO instance and display Weekly Trend - graph displaying distribution of reported Slow Queries per during previous days. This helps to understand, how reported issues were distributed recently and if tuning is producing any positive effect:

The same statistics are reported for Large Fetch issues in VO instances:

Sunday, May 4, 2014

It could come handy to know how to get WebLogic server name and port in ADF application. Particularly this could be useful, when running ADF application in the cluster and there is a requirement to track WebLogic node with application session instance running. Usually it is not enough to get server host, as cluster node is accessed through load balancer and server IP is different, not the one visible in HTTP session.

There is a way to get WebLogic server name and port. Server name could be retrieved from system property - weblogic.Name. Port could be retrieved from MBean - see the code below:

Server name and port is retrieved and displayed correctly for my test environment - DefaultServer and 7101:

Thursday, May 1, 2014

You can implement adaptive forms, generated on runtime using ADF Dynamic Form component in 11g R1 or 11g R2 (keep in mind - ADF Dynamic Form component is not supported with Facelets). In 12c you could use new ADF Dynamic Component to generate adaptive forms. All good, but customisation options are limited. For example, if you would need to define Value Change Listener for adaptive form UI component, this would be quite tricky as there is no direct access to ADF UI component properties.

If you need to control how UI is generated, you could implement your own ADF UI generation procedure. This would allow to manage ADF UI and ADF Bindings construction on runtime. I'm going to explain high level framework for such task and share sample application with ADF dynamic UI and ADF Bindings implementation.

This method creates attribute binding dynamically, so you don't need to define attributeValues property in page definition on design time - this will be created on runtime. PNAME_TextField identifies simple binding (you could create different binding for LOV or Check Box). Iterator name must be set, along with attribute name and binding ID (exactly as it is defined in Page Definition XML, only programmatically this time). This code is not documented, you must check ADF source code for different scenarios.

Sample application contains ADF BC components, there is regular VO for Employees with a list of attributes defined:

There are no bindings for these attributes in Page Definition, all of them will be generated automatically on runtime. In real use case, you would have dynamic VO in the background or switch Iterator to use different VO's at runtime. This would allow to synchronise and generate adaptive form on runtime:

There are 3 steps to follow. Firstly we would need to construct on runtime a list of attributes to be displayed. This could be a custom method invoked from forEach ADF UI component:

This method gets a list of attributes from iterator and constructs a list of attributes to be displayed (some attributes could be hidden):

Second step is to render different attribute types. Text, number and date should be rendered differently, with different formatters or ADF UI components. For this purpose, we could use ADF UI switcher component and call custom method to return current attribute type:

Custom method retrieves information about given attribute and returns type to be used in the switcher (here I'm checking for text, date and numeric type only):

Third step is to provide properties for actual ADF UI component we are going to display. All properties as value, label, columns, validator, etc. should be provided. Expression language points to our custom method:

Custom method checks, if such attribute binding was already created, if not - it will be created. Attribute binding is created through a method described in the beginning of this post:

This is how it looks on UI - form is rendered same way, as it would be prepared on design time. I was checking if validation is executed correctly - as you can see, validation message is displayed properly: