Andrejus Baranovski

Subscribe to Andrejus Baranovski feed
Blog about Oracle technology
Updated: 18 hours 6 min ago

Oracle Java Cloud Service - Scaling and Cluster Setup for ADF

Wed, 2017-08-16 12:10
Last couple of weeks I was busy preparing to my OOW'17 session about estimating Java Cloud Service performance for ADF application. I was running stress tests against various JCS instance configurations to be able to create performance estimation methodology. I will describe this methodology on OOW, but here today will list key steps required to scale up JCS instance.

Let's assume you are running single cloud node with 1 CPU and 7.5 GB RAM. This node contains WLS admin and managed server:

To scale up cloud node, simply invoke Scale Up command from the menu. Select new compute shape and confirm scale up operation:

Scale up completed:

Now go to WebLogic console and update Managed Server startup parameters, to adjust heap size to higher value:

Managed server memory can be increased up to certain amount. If more resources will be needed, at some point you will need to create multiple managed servers and connect them into cluster. This would require to define Load Balancer instance (to have single entry point to the cluster):

Cluster node must run in dedicated cloud node. If cluster is based on two managed servers, there must be two cloud nodes:

Managed servers from cloud nodes can be connected into single cluster, this can be done in WebLogic console:

Once cluster is defined, deployment becomes easy - you can deploy ADF application into cluster and it will be propagated to all nodes:

Traffic director running in load balancer instance will be automatically configured to route traffic to cluster nodes:

My Blog Samples Download Repository (For Samples Before 2014 January)

Sat, 2017-08-12 08:44
I have been asked, where to download my blog sample applications, posted before 2014 January. If you try to download such sample - you will get error about sample not found. Thats because Google discontinued their support for Google Code repository.

However, you can still download all my samples posted before 2014 January from Google Code archive. Go to archive URL - Google Code Archive for jdevsamples and you can browse all old samples there by date:

All new samples (after 2014 January) are hosted from Google Drive or from GitHub and are accessible directly from blog by URL.

Oracle JET Busy Context API to Control Asynchronous REST Calls

Sat, 2017-07-29 10:59
I have received feedback from users working with JET UI - sometimes it is not obvious that action button was pressed, users tend to press same button again very fast, which leads to parallel REST calls executing at the same time. In JET - REST call is executed asynchronously, this makes user to believe action was done instantly when button was pressed. However, REST call still may run in the background - while user will be trying to call same service again. While in most of the cases such behaviour is fine, still there are use cases when we want to block action button, until REST response is not received (while response is executed, button will be disabled - this will give visual feedback to the user about action still executing). JET provides Busy Context API to handle asynchronous REST calls in synchronous way.

I will describe how to apply Busy Context API in your JET application. Take a look into my sample app (JET + ADF BC REST) available on GitHub - JETCRUD.

When you run sample app, go to Customers tab and navigate to edit screen. There you will find Save button, which is enabled:

Save button calls saveCustomer() JS function. JET Busy Context is established in this method, before making REST call. Busy Context is attached to Save button. If there are no busy states in the context, function isReady() returns true and we can register busy context. After busy context is registered - REST call can be made. If saveCustomer() JS function will be called again, before REST call is executed - isReady() will return false and no REST call will be made. When busy state is created, we update observable variable - which helps to change disabled property for the button:

Data in one of the fields is changed and user pressed Save button to execute REST call - button becomes disabled:

Button stays disabled until REST call response is received. Of course when REST service is fast you even will not notice that. But if REST service call takes a second or so - you will see disabled button, when action is busy. After REST response is received and if there are no errors - success callback is executed. We call resolve() function there and this removes busy state:

We need to use promise call for whenReady() function to read changed value from isReady() function. This step updates button visual state back to enabled:

Save button becomes enabled:

Observable variable is set for UI button disabled property. This is how visual state is controlled from JS:

Don't forget to add resolve() to error callback too, otherwise button will stay disabled - if REST call fails:

ADF Goes Client Side - UI Performance Boost with JavaScript

Sat, 2017-07-22 10:48
If you would like to boost ADF UI performance, you should look into client side validation and formatting options possible to be done in ADF UI. Today I will describe how you can implement client side converter, to format number value on client side, without making request to the server. Same approach could be used to implement client side validators. You can raise error message and it will be assigned to UI field in the same way, just like any standard ADF error message. While this approach is documented long ago in Oracle ADF developer guide - How To Create Client Side Converter, it is not well known and not often used.

Client side converter is attached to ADF UI field through JSF tag, it points to custom converter ID (make sure autoSubmit=false is set, we don't want request to the server on value change):

Custom converter is defined in Faces Configuration file, it points to custom converter class:

Converter class is responsible to load JavaScript file, where number formatting logic is implemented. Also we have an option to pass initialization parameters:

Example of client side converter logic (to format numbers) code in JS:

Formatting happens on the client, no request to the server is done. User enters value and navigates out of the field - value is formatted:

If fractional part is incorrect, error raised from converter is displayed same as any other error in ADF - attached to the field:

If value is invalid - error is displayed too, this simple validation error comes from JS converter. Request is processed on the client, no call to the server:

Server side formatter in ADF BC is still required. When data is fetched from DB, ADF BC server side formatter is applied to transform data to correct format (this happens when data is fetched and doesn't affect end user performance):

Custom number formatter implemented in ADF BC (read more about it: Generic BigDecimal Formatter in ADF

Download sample application -

ADF BC - Create View Object From Query with Custom Implementation Class

Sun, 2017-07-16 12:18
I had a request to explain how to create dynamic ADF BC VO from SQL statement and set custom VO implementation class for newly created VO instance. Custom VO implementation class extends from ADF BC ViewObjectImpl and overrides super method:

There is a method createViewObjectFromQueryStmt, in previous ADF versions this method had two parameters - VO instance name and SQL statement. In current ADF 12c - there is a second signature of the same method, which contains option to specify VO implementation class name. Dynamic VO from SQL with VO implementation class:

ADF BC custom methods can be tested with ADF BC tester:

Overridden method from custom VO implementation class is called:

Download sample application -

ADF 12c BC Proxy User DB Connection and Save Point Error

Mon, 2017-07-10 14:35
If you are modernising Oracle Forms system, high chance you need to rely on DB proxy connection. Read more about it in my previous post for ADF 11g - Extending Application Module for ADF BC Proxy User DB Connection. It works in the same way for ADF 12c, but there is issue related to handling DB error, when DB proxy connection is on. DB error is propagated to ADF but is being substituted by save point error (as result - user would not see original error from DB). It seems like related to JDBC driver in 12c. The workaround is to override ADF SQL builder class and disable save point error propagation (there might be better ways to workaround it).

Proxy connection is established from prepareSession method in generic AM Impl class:

If I would change salary value to negative and save data - DB constraint error would fire (negative not allowed). Unfortunately, end user would not see that error - he gets message about failed save point:

Workaround -  we can disable save point error propagation. Override SQL Builder class and add try/catch block in rollbackToSavepoint method. If error happens, do nothing:

You must register SQL Builder class with AM. Add jbo.SQLBuilderClass property in bc4j.xcfg, pointing to the class:

You should be able to see DB errors after this change is applied:

However, there is one drawback of this workaround to keep in mind. When data is posted to DB, ADF executes lock statement. If update fails, normally ADF would execute rollback to save point and lock will be removed. But not in the case of DB proxy, now rollback to save point is failing - this means lock will stay:

If user would fix data and try to save again - lock error will be returned:

Error during lock:

To bypass lock issue, you should enable DB pooling for AM instance. In this case, after each request DB connection will be returned back to the pool and lock will be released automatically:

Download sample application -

Working with Location and Permissions in JET Hybrid

Thu, 2017-07-06 00:35
What if you want to access mobile device location data from JET Hybrid application? This can be achieved with Cordova Geolocation plugin. But you want it to be nicely done and want to make sure application is granted with permission to access location information. Use Cordova Permissions plugin for that.

You could add Cordova plugin to JET app by executing this command:

cordova plugin add 

If this command doesnt work for any reason, you could add plugin information directly into config.xml file (check Geertjan post about the same - Plugging into Devices with Oracle JET on Cordova (Part 1)):

In JS function, before calling location API - we call permissions API to check if app is already granted permission to read location data. In hasPermission method, in case of success - location data is accessed. In case of no permission, request for permission is sent. If request is satisfied - location is accessed (and permission is granted at the same time):

Location data is retrieved through callback:

This is how it works. On very first location access, when permission is not granted yet - we request permission through permission API:

When permission is granted, location is displayed:

Download sample application from GitHub repository - rslocationapp.

JDeveloper Patch for Transient Expression Compilation Infinite Loop

Tue, 2017-07-04 10:26
If you are using JDeveloper or, probably you run into transient expression compilation infinite loop issue. Infinite loop happens when you open ADF BC project and navigate to VO, which contains Groovy expressions. JDeveloper starts to print repeating message in the log - compiling TransientExpression and soon at some point JDeveloper window closing down without any feedback:

For those of you, who are not aware - there is a patch for this issue. Patch can be downloaded from Oracle Support, search for Patch: 25218838 (there is one for JDEV and another one for JDEV

If its your first time applying Oracle patch - no worries, process is very simple and smooth. Extract download patch zip archive first. Next setup ORACLE_HOME environment variable, point to root folder of JDEV install:

Once environment variable is set, run OPatch by executing opatch apply from the directory where patch archive was extracted. You can reference OPatch by direct path:

Hopefully fix provided by this patch will be included into next JDEV version by default.

Oracle JET Router State Control

Sat, 2017-07-01 02:25
In my use case there is requirement to navigate to JET module, without displaying it in menu structure. Navigation is a simple task, more complex is to make sure current menu item will be unselected after navigation to invisible module (so that later we are able to re-open it).

There is accounts module in JET sample app (download it from GitHub - JETModularArchitecture):

Accounts module is included into router, but not included into array of visible menu items:

On button click (dashboard module) we call function, where router navigation happens to accounts module:

Let's see how this functionality works. I click on Accounts button to call a function and force router navigation:

Accounts module will be opened (through router navigation), but currently highlighted menu item will stay as it was (Dashboard). This makes it impossible to navigate back to Dashboard (unless we navigate to another module and then navigate to Dashboard):

Solution for this problem is to change selection property of ojNavigationList component in HTML:

Instead of pointing to router stateId directly, we should point to computed function. This will help to control currently selected menu item. But we still need to update router state, when menu item is selected. For that reason I'm using beforeSelect property, which points to function, where router state is changed:

Selection property value is calculated by function, which returns NULL, if accounts is currently selected module. This allows to remove focus from Dashboard menu item, after navigation to accounts. Once focus is removed, we can click back on Dashboard and navigate. For all other modules - current router state ID is returned. Select handler call router API to navigate to the module:

Navigation to accounts module from dashboard. Dashboard menu item doesn't remain focused anymore:

Navigation back to dashboard work too:

Oracle JET Modular Architecture Example

Tue, 2017-06-27 13:01
One of my favourite parts in Oracle JET - modular code structuring support. This allows to split application functionality into modules and reusable functions. In this post I will show how you could leverage Oracle JET modular architecture not only by implementing common code functions, but also by managing data maintained in common modules.

Let's jump to the example (download or browse through sample code on GitHub repository - JETModularArchitecture). Sample application is based on JET template. I have created two common modules - dashboardChartHelper and dashboardTableHelper. These modules define data structure to be displayed in the dashboard and provide API to manage this data from consuming module:

Both helper modules are imported into consuming module - dashboard:

Dashboard module defines variables (chart and table data), which are initialized from variables assigned with data structures in helper modules:

There are two wrapper functions, calling API functions from helper modules. API provides data manipulation logic, which changes chart data structure. Wrapper functions are invoked from dashboard UI:

Here is the implementation of API functions - data array changes:

What is great about such structuring - data and data changes logic can be encapsulated in common helper module. As soon as we have observable variable defined in consuming module (dashboard), which points to the method helper method (where data is changed) - changes are automatically visible on UI.

Here is the data coming from helper modules rendered in dashboard module:

Press on Add Group E button, this will call helper module API function to update data array cached in that module. In turn observable variable in dashboard module will be updated and data displayed on UI will be refreshed:

Press on Remove Group E button - chart data will be changed again:

ADF BC Attribute - Collection Storage Mode Property

Sun, 2017-06-25 14:45
I would like to describe one interesting property for ADF BC attribute. This property is called Storage. There are two possible values: row (default) and collection. By default attribute value is saved in row storage, but alternatively it can be saved in collection storage. ADF BC implements collection storage using map which comes from session scope. This allows to keep value even between ADF BC requests, this is ideal for transient attributes.

Sample application ( implements VO transient attribute to keep checkbox value:

VO is configured for Range Paging support. While user will navigate through UI table pages - VO range paging will re-execute and this will force VO replace rows (which will result in loosing transient attribute values):

This is how it will look like. User will select checkbox and then navigate to another table page:

After navigating back - checkbox value will be lost (range paging mode will re-execute VO rowset to bring rows belonging to current page):

To force transient attribute value to stay, go to Properties window for the attribute and scroll down to the last section. Select attribute called Storage:

Change value to collection. This will force ADF BC to store value for this attribute in session map:

Transient attribute value will stay, even when VO is re-executed in range paging mode and VO rowset is refetched:

Fixes for ADF Cloud User Experience Rapid Development Kit (RDK) UI Layout Issues

Mon, 2017-06-19 13:45
If you was evaluating Oracle RDK UI template, probably you noticed information popup coming up, when RDK home page is loaded. Popup is loaded through showPopupBehavior listener, which is executed on Welcome page load event. Such popup is not required in practice, and usually is disabled. But as soon as you disable it, there will be layout issues with Welcome page. User information widget will not align the name and menu navigation items will not be ordered correctly:

This is not nice. And you will get such behaviour only when popup is not loaded:

I looked into it in more detail and I saw there is a second HTTP PPR request executed, when popup is loaded. It seems this second HTTP request was triggering partial response and this was forcing UI to load correctly:

Fortunately I found a simple fix for that. Need to set layout="horizontal" for springboard panelGroupLayout component located in Welcome page:

This change makes job done and now Welcome page layout is rendered correctly from the start, even without loading popup and forcing second HTTP PPR request:

There is another issue - related to panelGridLayout usage in ADF Task Flows loaded through Film Strip page. You can check my previous example about customising/extending RDK template - Extending ADF Cloud User Experience Rapid Development Kit (RDK). Let's assume use case with ADF Task Flow implementing two fragments (search and edit functionality):

Search screen renders ADF list implemented using panelGridLayout:

Navigate to edit screen:

Try to navigate back to search screen, you will get empty list displayed:

Fix is simple. RDK is using property stretchChildren="first" in FilmStrip page and this seems to break UI layout for regions with panelGridLayout component:

Remove stretchChildren="first" property from FilmStrip page, showDetailItem component assigned with id="sdi1":

With this fix applied, try to navigate from edit to search:

This time search page layout with panelGridLayout component is displayed as it should:

Download extended RDK application code with applied fixes -

Nice Trick to Get ADF LOV Description Text

Wed, 2017-06-14 12:29
I will tell you about nice trick to display LOV description. Usually you would create separate attribute in VO for LOV description and base LOV on this attribute (read about it in my previous post - Defining the LOV on a Reference Attribute in Oracle ADF 11g). But there is one more way - it makes it much faster to define LOV on description, but you should be aware about additional SQL statement executed to fetch description text.

You could set converter for ADF UI LOV, and then LOV component would use description by itself, without any additional configuration.

It is important to set correct order for LOV display attributes. Make sure to set description attribute to be first in the list for converter approach to work:

Go to ADF UI LOV component and set converter property. This must point to binding object, converter expression:

What you get - LOV field displays description, converter is able to mask ID value behind it:

It offers nice usability option - you could start typing description, press tab and value will be auto completed (if autoSubmit is set to true):

Behind the scenes it executes LOV SQL to get description text (this SQL is executed on page load too, which is not ideal when you have many LOV fields - in such situation is better to use separate attribute for description in the same VO):

When LOV value is changed and changes are saved, ADF BC updates ID value only (as expected):

Download sample application -

Running ADF BC REST Service Together with ADF Faces Application

Sat, 2017-06-03 05:44
ADF 12c provides out of the box support for ADF BC REST API. It is straightforward to create ADF BC REST service and run it. But what if you would like to expose ADF BC REST for existing ADF application with ADF Faces UI. This could be useful if there is a requirement to handle ADF Bindings access to ADF BC along with light ADF BC REST service API implementation for Oracle JET or other JavaScript clients. The same ADF application could handle two types of client access - ADF Faces and REST.

When you create ADF BC REST application, JDeveloper creates REST Model and WebService projects. Technically speaking, if you have existing ADF application with Model and ViewController, you could add third project for REST Web Service by yourself. Two configuration files are required - web.xml and weblogic.xml (if ADF Security is enabled):

ADF BC REST is exposed to the client through ADF servlet. It doesnt work to enable ADF BC REST servlet in ADF Faces project web.xml. This requires to have separate WAR deployment for ADF BC REST and different context root.

ADF Faces and ADF BC REST are sharing the same ADF Security context and this means we are using the same set of Application Roles for both.

In my example, ADF Bindings are mapped with Employees VO instance - this brings data to be displayed in ADF Faces:

The same VO instance is exposed through ADF BC REST:

ADF BC REST servlet is defined in REST project web.xml. It doesnt work to define it in the same web.xml where ADF Faces are configured - context conflict error comes on runtime. Thats the reason why I have separate WAR for ADF BC REST:

There is one WAR for ADF Faces app and one for ADF BC REST. Both WARs are packaged into single EAR. This means there is one deployment, but two context roots, one for each WAR:

If you download my sample app and want to run it, make sure to build REST project first:

Then click Run for ADF Faces app - ADF BC REST WAR will be packaged automatically (if you deploy it on standalone, simply build EAR - it will include both WARs):

We can see it in the deployment log - both WARs are packaged into single EAR:

This is the result - ADF Faces UI is accessed through adfapp context root:

ADF BC REST from the same application is accessed through restapp context root, authenticated with the same ADF Security context as ADF Faces app:

Download sample application -

ADF PopUp Event Context Launcher

Tue, 2017-05-30 02:30
I will describe how you could use ADF popup event context to pass parameters into popup. This could be useful if you want to develop reusable popup, which should accept different type of parameters from various launcher components.

In this example - popup is loaded from context info. Launcher component - output text is assigned with attribute, reading its value from binding. Our goal is to pass attribute value into popup:

In order to be able to read attribute value from launcher parent component, make sure to set eventContext="launcher" for ADF popup:

You can reference parent UI component from launcher property, this can be done in popup fetch listener - where value will be copied to managed bean property:

We could process launcher parent component in managed bean, extract values, etc.:

Value retrieved from popup launcher is displayed in the popup:

Download sample application -

Oracle JET Hybrid - NavDrawer Template Menu/Header Structure

Thu, 2017-05-18 13:31
Oracle JET provides NavDrawer template for Web and for Hybrid. Read how to create JET Hybrid application based on template - Create a Hybrid Mobile Application. There is significant difference in NavDrawer template implementation when we compare Web and Hybrid application.

Hybrid template draws menu structure on top of the form. Web template is pushing form to the right, when menu is opened. Such approach works fine on the Web, but you would see significant UI lag each time when menu item is selected. Probably thats the reason why hybrid NavDrawer template draws menu on top of the form - visually this provides better performance when switching between menu items. Menu is rendered on the top of the form in JET Hybrid Nav Drawer template:

Form is loaded instantly, when menu item is selected. Header in JET Hybrid NavDrawer template stays fixed, it doesnt scroll. This gives good opportunity to put there common actions:

NavDrawer template in JET Web application moves form to the right, when menu is opened - thats the main visual difference when comparing to NavDrawer Hybrid:

Index page of NavDrawer hybrid template is almost identical to Web NavDrawer, except that it doesn't contain header part. Header is implemented separate module:

I have customized default header implementation with additional items - logo and user preferences:

Header module is constructed in appController, this is how it is generated by default. If we want to have access to variables/functions from appController in the header, we need to create a mapping:

Every module must include div with fixed top JET CSS class (thats why it doesnt scroll and stays on top), where you would copy header code:

Header is bind with module, which is defined by headerConfig variable (must be located in each module) - which is initialized in appController:

Thats all about menu/header implementation.

Let's learn how to push update to Google Play. Make sure to increase application version in Cordova config.xml file:

Go to Google Play and upload new APK, it will be parsed and Google Play automatically will deactivate previous version:

You can initiate roll-out to production:

This will push new release to Google Play. Users will be automatically notified about new version:

Version 2 of our JET Hybrid app is available on Google Play:

Oracle JET Hybrid Mobile Application on Google Play

Wed, 2017-05-10 12:57
Oracle JET Hybrid mobile application can be published to Google Play and installed on Android device. We have tested this process from beginning to the end. Of course JET Hybrid mobile app can be published on Apple Store too, but we are using Google Plain and Android for now.

Where to get started if you want to publish your own Oracle JET Hybrid (open source and free to use) mobile app? First of all you need to build APK (if building for Android) file in release mode. Read about it in my previous post - How To Package JET Hybrid Mobile Application for Release (Android Platform).

Search for JellyHouse in Google Play to install and test our JET app:

You can use demo data account redsam/welcome1 to login and check how JET runs on your Android mobile:

Let's walk through the main steps about how to upload and publish JET APK file in Google Play. First of all you need to login into Google Play Developer console and pay license fee 25 USD (if you are publishing first time). Second, prepare APK file compiled in release mode (read above how to do it). APK file typically is located in hybrid folder, build/outputs directory:

In Google Play Developer console create new application - press Create Application button:

Before you could publish APK to Google Play, you will be asked to complete various forms with information about the app, content rating and upload application graphics:

APK file is uploaded under Release Management -> Artifact library:

To verify upload, click on show details icon and you should see additional information for uploaded APK:

There are options to manage test releases. But you could opt out directly for production - this is what I did. Press publish button and wait about 30 - 60 minutes. Status should be changed to published:

Once published, search for your app in Google Play. Google Play for JellyHouse app:

How To Package JET Hybrid Mobile Application for Release (Android Platform)

Sun, 2017-05-07 11:01
If you want to build/package JET Hybrid application you must issue build:release or serve:release command. Read more about it in JET developer guide: Packaging Hybrid Mobile Applications. In order to run build:release or serve:release commands successfully, you need create buildConfig.json file, which includes information about self signed certificate. This allows to sign application and package it for release.

Steps below are tested for Android platform.

You can generate certificate with Java keytool utility. Navigate to Java home bin folder and run keytool. Specify correct path and preferred alias:

keytool -genkey -v -keystore /Users/andrejusbaranovskis/jdeveloper/mywork/jellyhouse-release-key.keystore -alias RedSamuraiConsulting -keyalg RSA -keysize 2048 -validity 10000

You will be asked to enter additional information, such as name, organization, location, etc.:

Once certificate is generated, you can create empty buildConfig.json file. I have created it in the root directory of JET Hybrid application. Certificate file is copied into the same location:

Provide release information in buildConfig.json. Since certificate file is located in the same folder, it is enough to specify its name without path. Include alias name, certificate password and keystore password:

If buildConfig.json contains correct entries, build:release should run successfully:

sudo grunt build:release --platform=android --buildConfig=buildConfig.json

Successful result output:

JET Hybrid release app built for Android platform size is 7.5 MB (major part takes Cordova libraries):

So, if you create self signed certificate and populate buildConfig.json correctly - it is very easy to run release build for Oracle JET Hybrid application.

Batch Requests Support in ADF BC REST

Wed, 2017-05-03 09:48
ADF BC REST provides a set of enterprise features for REST, one of them support for batch requests. In single REST batch call we can execute multiple update, insert, delete and get operations. This is important functionality, it allows to minimize number of REST calls from the client and improves client performance. Take a read about it in developer guide - 22.13.7 Making Batch Requests.

Batch request in ADF BC REST is executed through POST. You need to specify root URL for REST request, complete path will be set in the payload. Make sure to include batch request Conent-Type:

Request is constructed with different parts, each part describes separate request operation - update, create, delete or get. Path to REST resource is specified too, along with payload if any:

Complete example of ADF BC REST batch request (one for update, create, delete and another for multiple get):

It is important to keep in mind - if one of the batch operations fails, other operations are reverted. In this example, validation fails for create operation - message is returned to the client:

Successful batch request returns back response data for each operation. This is useful, if you want to leverage response on the client - there is no need to do separate REST call to retrieve latest data:

I have logged execution output on the server side. Batch request is executing two update operations, create and delete. At the end single commit is called:

Very useful could be execute multiple get operations in single batch request. We can fetch data for different REST resources in one call to improve performance. In this example fetching data for Employees and Departments:

In response we get data for Employees under part1:

Data for Departments under part2:

Response structure is simple and this makes it easy to parse it on the client.

Access sample application code on GitHub repository - jetcrud.

ADF BC Groovy Expression Security Policy Configuration

Mon, 2017-04-24 13:23
Today I'm going to explain how to configure Groovy expression security policy. This could be helpful, if you dont want to change trustMode property to trusted everywhere across the app, but looking for single configuration point.

My sample app -, contains bind variable with expression reference pointing towards custom method located in AM implementation class:

JDEV returns compilation error for Groovy expression, can't resolve applicationModule property:

Such kind of checks can be disabled in Model project configuration. Uncheck option for Groovy Expression Type Validation:

JDEV by default creates Groovy expressions in untrusted mode. If you change it to trusted, expression would work OK. However, if your app contains many expressions like this, you may want to ignore trustMode property:

If you run ADF BC tester in JDEV, it will show error text in the log for untrusted expression. ADF BC tester will fail to start, if there is any error - we logged this issue with Oracle Support. Property applicationModule can't be resolved, when trustMode is set to untrusted:

To disable this check, we can create new class extending ExprSecurityPolicy class. Override checkProperty method to allow calls to applicationModule property:

This class should be registered in adf-config.xml:

Try to run ADF BC tester again. Error about applicationModule will be gone. This time it will complain about permission error to call getCurrentRegion method:

Method access can be granted by annotation in AM implementation class:

ADF BC tester runs, and returns VO row data: