Skip navigation.

Andrejus Baranovski

Syndicate content
Blog about Oracle technology
Updated: 17 hours 59 min ago

How To Set EAR Upload Size for Oracle Enterprise Manager

Sat, 2014-12-13 06:29
By default, there is a limit for EAR upload size (~40 MB) in Enterprise Manager. If your ADF application is fairly big, you may face this limitation and will not be able to deploy through Enterprise Manager. Deployment for large EAR would work through WebLogic console, WLST script or directly from JDEV, however sometimes you may need to deploy through Enterprise Manager. I will describe in this post, how you could increase the limit - we are going to extract Enterprise Manager application EAR and change maximum file upload size specified in web.xml.

In my case, the requirement was to be able to deploy ~47 MB EAR file:


When trying to deploy this EAR through Enterprise Manager, I would get the error about maximum file upload size exceeded:


You must navigate to the folder, where applications are deployed for your domain (alternatively, double check in WLS for EM application, where EAR file is stored). There must be one called em.ear, this is the deployment for Enterprise Manager application:


Extract this EAR (make sure to create backup), you will find em.war file inside - we need this file:


Extract em.war file now. Navigate to WEB-INF folder, you will find web.xml file there. Open web.xml file for editing:


Search for org.apache.myfaces.trinidad.UPLOAD_MAX_DISK_SPACE parameter in web.xml and change its value to be large enough to accept the size of EAR file you want to deploy. I have set it to 50 MB = 52428800 bytes:


Make sure to pack everything back, and keep original em.war and em.ear files structure:


After all the are changes applied, large EAR file is accepted in Enterprise Manager and we can proceed with the deployment:

ADF Mythbusters UKOUG'14

Mon, 2014-12-08 09:11
I would like to post the slides from our recent session on UKOUG'14 conference - ADF Mythbusters. This session was presented by my colleague from Red Samurai Consulting - Florin Marcus. The goal was to break popular ADF myths. We have logged Oracle Support SR's, each myth in the slide is assigned with SR number.

Slides are available on SlideShare:

ADF Mythbusters UKOUG'14 from andrejusb
The following topics are covered in the presentation:
  • ADF BC Batches Of Functionality
  • AM Pools and DB Connection Pools
  • Activation-Safe Application Modules
  • Maximum Number of Regions Per Page
  • JSP vs Facelets
More detailed description and analysis data are available in the slides.

Adaptive Case Management 12c and ADF Human Tasks

Thu, 2014-12-04 14:08
I'm diving into the new topic - Adaptive Case Management 12c and ADF integration. Today will be the first post in the category and there are more posts planned for the future. I strongly believe that ACM (Adaptive Case Management) makes a great extension for standard BPM. Mainly because it allows to define a loose process, without strict order steps. Process steps can be executed in different order, depending on the situation requirements, at given time. I will be explaining how to implement ADF Human Task for ACM activity and will share several tips, how to make it run in BPM Workspace application.

This is how sample application (HotelBookingProcessing_v1.zip) is constructed, there are two Human Tasks (AddHotelBooking and ValidateHoteBooking) and HotelBookingProcessing Case control:


HotelBookinfProcessing case is defined with Hotel Booking Details data type (this type is based on XSD schema and is defined as Business Component variable - don't mix up with ADF Business Components) - you can think about it as about main data structure type for the case, this can be transferred into every case activity:


There are two stakeholders defined, this could help to control who could have access to human task and case activity. Customer Service Representative is supposed to add new hotel booking, while Financial Accountant can approve or reject it:


I have created Human Task activity directly through composite, it is not necessary to have BPM process to define human tasks. Important to set Application Context property for Human Task to be OracleBPMProcessRolesApp, this will help later with security roles configuration in BPM workspace:


In order to register human task with Case management, we are given option to promote human task as a case activity. This will allow to initiate human task from the case management:


We can define input and output for the case activity, based on the same data type defined in the case. This will allow to transfer data from the case to the activity, and to the underlying human task in our situation:


You could generate ADF form case data, this form will be rendered in BPM workspace case UI. I'm going to look into customisation options of this kind of form in my future posts (checkbox is set to generate editable form):


This is how case data form is rendered, out of the box is given option to save and reset data for the case - Hotel Booking Details:


Human task form is generated in the same way as it was in 11g - no change here for 12c. You could auto generate this form, it generates a lot of code and I would prefer to build custom light form instead:


Important hint - auto generated human task form will not render in BPM workspace window. You need to change FRAME_BUSTING parameter generated in web.xml from differentDomain to never. With differentDomain option it doesn't render human task form, in 11g it was generating with option set to never, for some reason this was changed in 12c - not for good:


With FRAME_BUSTING set to never, human task form renders well:


Human task is started directly from the case activity - Add Hotel Booking from the available list of activities:


We can track in the case activity log - when activity was started, completed or modified. This is quite helpful info to track activity history:


One of the main advantages - user could decide the order of activities, on contrary to strict BPM process. Start Validate Hotel Booking activity, this will create new task for Financial Accountant:


Activity was started, we can see this from the audit log:


This is readonly human task, rendered in BPM workspace - Financial Accountant could approve or reject it:


Case can be closed and hotel booking approved:

Adaptive Form with Dynamic ADF LOV Value Binding

Sat, 2014-11-29 05:25
Previously I had a post about dynamic ADF attribute binding creation and dynamic ADF form generation - Adaptive Form with Dynamic ADF Attribute Value Binding. Blog reader was asking how to generate dynamic ADF LOV binding using similar approach. This is possible and actually documented in Eugene Fedorenko post here - Dynamic LOV binding. I will use the same piece of code to extend my sample application with dynamic ADF LOV binding support.

Here you can download updated sample application - DynamicAttributeBindingApp_v2.zip. This application is updated with LOV definition for JobId attribute in ADF BC:


Once you are generating dynamic components on the UI and getting VO attributes to render, you should not be surprised there will be more attribute entries returned than you can see defined in VO. Additional attributes are for View Accessors, and we don't need them while generating dynamic ADF UI. This can be controlled by checking attribute kind property for attribute definition. If attribute kind is not of rowset kind, we can display it:


There is another method in the sample app, it checks for attribute type. This helps to decide what kind of UI component to render - input text, input date, LOV, etc.:


Dynamic ADF LOV binding is constructed from helper method below, this method is invoked from ADF UI LOV component:


Here is the essential part of the updated sample app - LOV binding creation method. LOV binding is constructed, similar as ADF attribute binding, by pointing to the iterator, LOV server binding name, attribute name and ID:


Dynamic ADF UI components are stamped through ADF UI iterator:


There is a special Facet to support ADF LOV UI component creation. UI component is created by pointing to the helper method, where ADF LOV binding is constructed:


LOV generated dynamically works well on runtime, user can open a list and select a value:


LOV validation also works, try to enter invalid value (not available in the list), user will be prompted to enter existing value instead:

Suppressing ADF LOV Like Operator Filtering V2

Wed, 2014-11-26 01:53
I had a post about the solution to suppress ADF LOV Like operator and prevent LOV popup loading when user is typing existing value - Suppressing ADF LOV Like Operator Filtering. Thanks to a blog reader, there was one use case found, when Like operator was not suppressed properly. This is fixed now and I would like to post updated sample application here.

Additional method is overridden in LOV VO implementation class - applyViewCriteria(ViewCriteria, boolean). Besides previously overridden method buildViewCriteriaClauses(ViewCriteria), this method provides additional handling for LOV Like operator suppression. Download sample application - ADFTableApp_v2.zip.

Blog reader reported an issue, when LOV value was changed to 10, again changed to 100 and again 10, then LOV popup was opened on the last change. This should not happen, as value 10 exists in the LOV. It seems like when LOV value is changed to the same as it was set before, ADF BC executes extra call for LOV filter through applyViewCriteria method. This is why this method is overridden as well as buildViewCriteriaClauses.

Both methods are overridden and check for STARTSWITH (Like) operator is implemented:


It works well now. Try to enter value 10, LOV will accept this value without opening LOV popup:


Enter value 100, this value will be accepted as it exists in the LOV list:


Again enter value 10, it will be accepted as it was previously (it will not be, without overriding applyViewCriteria method):


If I type any value, not available in the LOV list:


As expected LOV popup will be opened and user could select a valid value:

BPM Authentication On Behalf Business User from ADF

Wed, 2014-11-19 01:20
This is the next post in the series of ADF/BPM integration, check previous post available here - Dynamic ADF Buttons Solution for Oracle BPM Outcomes. Here I'm going to describe how you could authenticate with BPM from ADF through a proxy user, on top you could apply only business user name, password will not be required.

There is API method available - authenticateOnBehalf(context, userName), you must have a valid connection context created and with authenticateOnBehalf method you could set to use any valid user name, instead of proxy user. Here is the example for Workflow Context:


Similar example for BPM Context, same authenticateOnBehalf method:


As a proxy user I'm using weblogic. You could set to use any different user and consider it as a proxy user.

Tasks assigned for redsam1, connected through proxy user weblogic, are retrieved and displayed in the table:


This is how you could avoid using password for each business user and simply create initial connection through a proxy user. Download sample application - adfbpm11gr4.zip.

Dynamic ADF Buttons Solution for Oracle BPM Outcomes

Thu, 2014-11-13 13:07
BPM Human Task activity is configured with outcomes. Based on these outcomes, buttons in ADF UI are constructed allowing user to perform different actions with the task. Auto generated ADF Human Task form contains a set of predefined buttons and this set is controller with rendered flag. My sample application is using different approach, it implements custom tasks table and dynamic ADF UI for the human task input form - Dynamic ADF Form Solution for Oracle BPM Process. Once user selects a task, action buttons are generated dynamically - using a set of outcomes configured for the particular task.

Here you can download complete sample application - adfbpm11gr4.zip. This application implements a method based on BPM API, where a list of outcomes by the currently selected Task ID is fetched from BPM engine:


Each outcome is represented by ActionType. I'm constructing a list of outcomes to be used on ADF UI. There is ADF UI iterator components on the fragment, this component is generating dynamic buttons, based on the constructed set of outcomes. Outcome name is used to set button name and outcome itself is used as attribute value for the generic action listener method:


Generic action listener method is responsible to parse outcome name, initialise a payload if needed, and execute BPM API to submit the outcome for further task processing:


We can check how this works. There is a human task AssignEmployee with SUBMIT outcome, in the sample application:


Task action button is generated accordingly - there is only one Submit action button for the selected task:


The next human task ApproveEmployee is set with two outcomes - APPROVE and REJECT:


Based on the set of the outcomes, two buttons are present now - Approve and Reject:

Dynamic ADF Form Solution for Oracle BPM Process

Fri, 2014-11-07 03:07
I was working recently on integrating ADF 11.1.2.4 and BPM 11.1.1.7 environments. This worked pretty well, all configuration was done based on my previous blog post for similar topic, only previous ADF and BPM versions - BPM 11g R1 Worklist Integration (Hacking Experiment) Into Non-SOA ADF 11g R2 Domain. Goal of this post is to describe dynamic ADF form approach associated with BPM process human task.

BPM payload contains additional element called voInstanceName. This element is supposed to contain ADF VO instance name, this instance will be used later to render dynamic ADF UI for the currently selected task:


Sample application - adfbpm11gr4.zip, is based on two separate applications. One implements simple BPM process with payload including ADF VO instance name and another implements standalone dynamic ADF application with BPM API.

There are two human tasks in BPM process. Each of these human tasks accepts a payload element with ADF VO instance name. This allows to control ADF UI from BPM process, by providing ADF VO instance name to be used in ADF. The first human task is set to work with EmployeesView1 instance:


Second human task is set to work with different ADF VO instance - EmployeesROView1:


I'm reading voInstanceName payload variable value in ADF application, to construct dynamic ADF UI accordingly. Accessing currently selected task by ID and retrieving payload information for voInstanceName. Later this information will be used to construct dynamic ADF iterator:


Value from voInstanceName payload is used as a parameter for the ADF task flow rendering dynamic ADF UI. Task flow is configured to refresh each time, when parameter value is changed - new UI will be rendered for each new task selected:


ADF task flow checks if parameter for voInstanceName is not empty (it could be empty, if there are no tasks from BPM or payload value was not set). If there is no value, user will be redirected to the empty fragment:


Dynamic ADF UI is constructed in the bindings, instead of using static ADF iterator - we are initialising iterator from task flow parameter value passed through voInstanceName. This is how we can switch between different VO's from the ADF BC, depending on BPM task selected:


ADF UI is rendered with dynamic ADF form component. There are several ways to implement dynamic ADF UI, it can be all custom or using out of the box ADF UI components (depends on use case requirements). Here I'm using out of the box dynamic component, because UI is fairly simple:


This is how it looks like. Initially there are no tasks, no dynamic ADF UI - blank screen:


Start a new task in BPM, task is started through BPM API from standalone ADF application:


ADF UI form is rendered for the task. User can select a task and then select Employee, by navigating with Next/Previous buttons. As soon as Employee is selected (ID: 103), task can be submitted for further processing:


Login with different user - redsam2 and you are going to see new task in the inbox. Employee data is rendered from different VO instance and is readonly now. Employee ID was taking from the payload, this is how a row with ID: 103 is selected (the same as selected in the previous step):


Employee data in the second step is rendered from different read-only VO, including Job Title attribute:


There are two human task activities in the process, both are rendered with different dynamic ADF UI:

MdsMetadataResourceProvider Error in ADF 11.1.1.7

Mon, 2014-11-03 02:59
If you have migrated ADF application to ADF 11.1.1.7 version recently, you may see error in the log related to the internal MetadataResourceXmlImpl class usage. Runtime behaviour will not be affected, but there could be many redundant error messages in the log, like this one:


Error UNEXPECTED_CLIENT_OBJECT_TYPE found oracle.adf.controller.internal.metadata.xml.MetadataResourceXmlImpl, points to the ADF internal class usage, instead of public. You must look through the source code and you should find illegal internal imports for MetadataService and TaskFlowDefinition classes. Typically ADF developer would use such classes in the previous ADF versions to check if specific ADF TF exists:


In ADF 11.1.1.7 you can use public classes for MetadataService and TaskFlowDefinition, instead of private. To fix the error, you only need to change class import:


Here you can download sample application with correct API usage - ADFMetadataInternalApp.zip.

Handling Date Format and ADF Bindings

Tue, 2014-10-28 14:25
There are tips and tricks related to the date format handling and ADF bindings. When Oracle date type attribute is being used through ADF binding expression, it will be converted to String with default format (yyyy-MM-dd), no matter what original format was set. This is described in API for the Oracle date type - Date constructor with String. Below I'm going to explain how it works and how you could optimise ADF application to handle date type attributes from ADF bindings layer.

Sample application (download it here - DateFormatApp.zip) is based on one simple VO with calculated attributes, both oracle.jbo.domain.Date type:


ADF UI implementation is standard - there are ADF Input Date components with regular date converters:


There is a button on UI, it calls custom method implemented in AM and exposed through the bindings. This method accepts two parameters, both oracle.jbo.domain.Date type. I'm using regular binding expression and getting inputValue property (this returns formatted value of the date):


Try to invoke the method, you will get an error about invalid argument - binding expression with date attribute is not accepted. It is trying to use formatted value dd/MM/yyyy and set it for the custom method argument value, but Oracle date accepts only yyyy-MM-dd (I'm using Alta UI skin):


Error message is written in the log:


The workaround is to use attributeValue instead of inputValue in the binding expression. Property attributeValue returns original unformatted date type attribute value:


Do the same test again, type both dates and press Test Dates button - this would work now:


I'm checking out date values in the custom method. Originally it comes unformatted date value, taken from attributeValue property. If we would like to use date value in the certain format (e.g. send to PL/SQL in format dd/MM/yyyy, instead of default yyyy-MM-dd), we should apply DefaultDateFormatter to retrieve the formatted String value for the original date:


Here is the output from the custom method:

ADF BC View Object SQL Query Customization with MDS

Thu, 2014-10-23 12:51
This post is based on my previous article about MDS Seeded Customization - MDS Seeded Customization Approach with Empty External Project. Today I will focus on explaining how to customise SQL query for read-only VO. This is not so obvious as it sounds. However, it is doable - I will explain how.

Sample application - MDSCustomizationsApp_v2.zip contains both main and customisation projects. Main project implements read-only VO for Jobs data, it doesn't include Job Title attribute:


This is how SQL query looks for such VO in the wizard:


We should take a look into the source code, SQL query is defined by SQLQuery tag. Tag doesn't have ID, this would disable tag customisation using JDEV MDS wizards:


No matter there is no ID set, we still could customise it - I will show you how. Here is the example of SQL query customisation stored in MDS customisation file. Firstly you should remove SQL query completely from VO and then add it again (this will create two entries in MDS customisation file). Once SQL query is written to the MDS customisation file, we can change it as we would like to - Job Title attribute is added to the SQL statement:


We need to add separately VO attribute for Job Title, this can be done through JDEV MDS customisation wizard. Make sure to set IsSelected=true property, otherwise attribute will not be set from the query:


You should drag and drop Job Title attribute from Data Control into the fragment, this will generate binding entry in the page definition file:


UI component for Job Title will be generated as ADF Faces output text:


You should notice on runtime customised SQL statement executed, this statement would include Job Title added through MDS customisation:


Job Title value is fetched and displayed on UI:

Video and Slides - Data Caching Strategies for Oracle Mobile Application Framework

Sat, 2014-10-18 09:08
I have recorded a video tutorial, based on my OOW'14 session - Data Caching Strategies for Oracle Mobile Application Framework. ADF developers who could not attend OOW'14 in San Francisco, this is for you !

Here you can view the slides:


Data Caching Strategies for Oracle Mobile Application Framework
Watch the first part of the tutorial:


Watch the second part of the tutorial:


Described solution is based on the sample application from the blog post - Transactional Data Caching for ADF Mobile MAF Application.

Workaround for ADF 12c Choice List Blank Selection Issue

Sun, 2014-10-12 09:28
I would like to share a workaround for Choice List component in ADF 12c. There is specific issue, related to blank selection - as soon as user selects blank selection in the choice list, it starts to invoke value change listener for that list, each time when any other element is selected in the table. This is quite annoying and could lead to unexpected results, especially if you depend on logic implemented in value change listener.

Workaround is implemented in the sample application - ADFChoiceList12cApp.zip. We should take a look first, how it works without workaround applied. Imagine you have a table and one of the columns implements a choice list. Go and select a blank selection for a couple of rows:


Navigate between rows, do couple of clicks - you should notice in the log information about value change listener invoked. This is quite strange, it should not call value change listener each time, just only first time after selection was changed in the list:


Choice list UI component is set with AutoSubmit=true and assigned with value change listener method:


Choice list is configured with blank item selection in ADF BC:


To apply workaround, go and uncheck blank item selection in ADF BC, make sure checkbox for 'Include No Selection Item' is unchecked:


On UI side, provide any value for UnselectedLabel property of the choice list component, this will generate property in the source (alternatively you could just type it manually directly in the source):


Make sure UnselectedLabel property is set to be blank, this will generate blank item on the runtime (it works much better than the one enabled from ADF BC):


User could navigate through the table, there will be no value change listener triggered anymore (besides one time, when value was actually changed):


Exciting as usual - new features and new bugs :)

New Alta UI for ADF UI Shell Application

Tue, 2014-10-07 23:14
I have applied new Alta UI for customised ADF UI Shell application. Customised version of ADF UI Shell is taken from my previous blog post - ADF UI Shell Usability Improvement - Tab Contextual Menu. Old application with new Alta UI looks fresh and clean. Runtime performance is improved - ADF transfers less content to the browser, this makes application load and run faster.

Here you can download my sample application with Alta UI applied to ADF UI Shell - MultiTaskFlowApp_v12c.zip.

All three ADF UI Shell tabs are opened and Master-Detail data is displayed in this example:


New style is applied for LOV component and buttons, making all buttons and controls more visible and natural:


Customized ADF UI Shell supports tab menu - user can close current tab or other tabs:


There was a change in 12c related to the tab menu, we need to set align ID property differently. You can see this change in ADF UI Shell template file - Java Script function gets tab ID to align directly from component client ID property:


Alta UI is applied simply by changing a skin name in trinidad file:


This hidden gem was packaged with current JDEV 12.1.3 release, you don't need to download anything extra.

New ADF Alta UI for ADF UI Shell

Mon, 2014-10-06 15:55
New skin for ADF in 12c looks great, I have applied it for one of my sample application with ADF UI Shell and it works smoothly. Check Oracle documentation how to apply Alta UI, really easy.

ADF UI Shell with Alta UI - clean and light:


REST Support for ADF BC in 12c

Thu, 2014-10-02 18:45
Frank Nimphius have announced REST support for ADF BC feature on OOW today. Probably this functionality will be available in the next JDeveloper 12c update release.

Once REST will be enabled for Application Module, new XML definition file and project will be created. Here you can see how new wizard will look like for REST definition on top of ADF BC:

Suppressing ADF LOV Like Operator Filtering

Sat, 2014-09-27 05:05
ADF LOV component provides filtering option with STARTSWITH operation. This is used to check if similar value exists in the LOV, if such value exists - LOV popup is opened with all the suggested values. If user types 10 and there are 100, 1000 in the LOV, instead of accepting value 10 - LOV popup will be opened and all three values 10, 100, 1000 will be displayed. While this is useful, there is no option to turn off such functionality. My post describes a solution, that can be used to disable suggested LOV filtering.

Here you can see, how it works by default. User types 10, there is 100 in the LOV. LOV popup is opened with both suggested values. This can be annoying for advanced user, who already know the code and they don't need to use LOV popup to select it:


We can check generated SQL statement. Original LOV SQL was updated with LIKE and this was applied for bind variable value. This is how suggested LOV values are retrieved:


LIKE is applied for DepartmentID (LOV key), even we have set it explicitly in the LOV View Criteria to use EQUALS operator:


The solution is to override buildViewCriteriaClauses method in VO Impl class. ADF executes additional View Criteria to retrieve suggested LOV values, this criteria name is "__lov__filterlist_vcr___". We can intercept this View Criteria and replace all STARTSWITH operators with EQUALS:


With this fix applied, user could type 10 and there is no LOV popup opened anymore with suggested values:


Same SQL as before is generated, but LIKE is changed to =, this is the result of our fix:


New LOV value can be successfully saved to the DB:


Download  - ADFTableApp.zip.

ADF Region Data Synchronisation with Change Event Policy

Tue, 2014-09-23 11:30
This post applies for multiple ADF regions, based on the same Data Control. I will show you can avoid using ADF Contextual Events to synchronise two ADF regions, when both are based on the same Data Control and this Data Control is shared between the two.

Sample application contains two ADF Task Flows, both are using the same VO instance from shared Data Control:


Two ADF regions are implemented based on these TF's, one implements table component and another a form:


Data from both regions is synchronised automatically. Based on row selection in the table, form data from another region stays in synch:


Backwards synch works as well - change Salary attribute value in the form:


Salary attribute in the corresponding row from the table will be updated:


In order for this to work, make sure to set ChangeEventPolicy=ppr for Employees iterator in the first fragment page definition (this will ensure update when data is changed in the form and we want to see synch in the table):


Set the same property for the iterator in the second fragment page definition (this will ensure form data to be in synch when row selection is changed in the table):


Download sample application - RegionCommunicationApp.zip.

JDeveloper 12c ADF View Token Performance Improvement

Sat, 2014-09-20 05:37
There is known limitation in ADF 11g, related to accessing application in the same session from multiple browser tabs. While working with multiple browser tabs, eventually user is going to consume all view tokens, he will get timeout error once he returns back to the previous browser tab. Unused browser tab is producing timeout, because ADF 11g is sharing the same cache of view tokens for all browser tabs in the same session. This means the recent mostly used browser tab is going to consume all view tokens, other browser tab would loose the last token and screen state will be reset. This behaviour is greatly improved in ADF 12c with separate view token cache supported per each browser tab. If your application is designed to allow user access through multiple browser tabs in the same session, you should upgrade to ADF 12c for better performance.

I'm going to post results of a test with 11g and 12c. Firstly I'm going to present ADF 11g case and then ADF 12c.

ADF 11g view token usage:

Sample application contains one regular button, with PartialSubmit=false, to generate new view token on every submit:


Max Tokens parameter in web.xml is set to 2, to simulate token usage:



To see the debug output for view tokens usage on runtime, you should set special parameter - org.apache.myfaces.trinidadinternal.DEBUG_TOKEN_CACHE=true



On runtime try to open two browser tabs. You are going to see two view tokens consumed and reported in the log:



Press Test View Token button in the second tab, this would consume another view token. Remember, we have set maximum two tokens, no in the log it says - removing/adding token. This means, we have consumes both available tokens (for both tabs) and token from the first tab is replaced:



Go back to the first browser tab, try to press the same Test View Token button and you are going to get time out error - view token is lost and you need to reload the tab:


ADF 12c view token usage:

Sample application in the same way as in 11g, also implemented simple button set with PartialSubmit=false. This would force to use new view token on each submit:


Max Tokens parameter in web.xml, again is set to 2:


Two browser tabs are opened and two view tokens are consumed:


Press Test View Token in second browser tab, you are not going to see in the log information about removing/adding token (differently to 11g). This means, view token from the first browser tab still remains in the cache, second browser tab maintains its own view token cache:


Go back to the first browser tab, press Test View Token button - application works fine, no time out error as it was in 11g:


Download sample application ADF 11g and 12c examples - ViewTokensTest.zip.

Handling Format for BigDecimal Numbers in ADF BC

Tue, 2014-09-16 13:12
This may not be as straightforward as it sounds - to define a format for a number attribute in ADF BC. Especially if you are going to have large number (more than 15 digits). Most likely you are going to experience precision/scale and rounding issues, for BigDecimal and Number type attributes with format mask applied. Sounds frustrating? Yes it is. I hope my blog post will help you to implement proper number formatting.

Firstly I'm going to demonstrate, how it works by default. I'm going to use format mask for 18 digits and 2 decimals. Format mask for a number attribute of BigDecimal type would fail with invalid precision/scale error - this is surprising, especially knowing that attribute is defined with (20, 2) precision and scale:


There is one more issue to handle - automatic rounding for large numbers (more than 15 digits). In this example I'm trying to enter a number with 18 digits:


Suddenly number is rounded, immediately after focus is moving out of the field - this is bad, user can't enter correct large number:


Let's see, how we can fix it. I will explain solution, based on Salary attribute with (20, 2) precision and scale. By default, this attribute is generated with BigDecimal type, I'm going to keep the same type, no need to change to oracle.jbo.domain.Number:


I have set format mask on the VO level, for the same Salary attribute. There is another issue - maximum length of the attribute value user can enter on UI. Maximum length property is reading precision and calculates maximum number of characters, however this is wrong when format mask is applied:


There will be extra comma and dot signs coming from the format, so I would advice to set Display Width to be equal to the attribute precision plus maximum number of commas and dots (26 in my case). Later we would need to change maximumLength property on the UI to use Display Width instead of precision:


Once you set a format mask, formatter class name is assigned for the attribute. Formatter class name is saved in resource bundle, for each formatted attribute separately:


You must change formatter class name to the custom one, don't use DefaultNumberFormatter class - out of the box formatter doesn't work with BigDecimals. Sample application comes with custom Number formatter class. Format method is overridden to support BigDecimal, standard formatter method breaks BigDecimal number by converting it to Double (this is the reason for rounding error) - this is fixed in the sample:


Method to parse is changed as well (this is fixing precision/scale number for the BigDecimal). Instead of calling parse method from super, I'm calling custom method:


I'm setting a property to enable BigDecimal parsing, this allows to work correctly with precision/scale:


In addition, precision and scale are checked by custom method - if there is invalid number of digits, user will be informed:


I was mentioning it earlier - maximumLength property on the UI is updated to point to Display Width set on the VO attribute UI Hints:


We can do a test now, type long number with 18 digits (remember (20, 2) precision/scale for Salary attribute):


Correct format will be applied:


Type decimal part and now there will be no error about precision/scale - it will be successfully accepted:


You can see from the log how format is being applied, it works well with custom formatter class provided in the sample application - ADFFormattingApp.zip: