Andrejus Baranovski

Subscribe to Andrejus Baranovski feed
Blog about Oracle technology
Updated: 15 hours 25 min ago

Takeaways from OOW'17

Sun, 2017-10-08 09:28
Let's summarise important points from OOW'17 conference. This year conference was a breakthrough for Oracle JET - most of Oracle Cloud UI's were implemented with Oracle JET. Oracle ADF is used for Oracle SaaS (Fusion Middleware) back office applications, same as before. There is often misunderstanding in JET vs. ADF comparison. Keep in mind - JET is only UI layer and it can be compared with ADF Faces only. While ADF is much more than UI - ADF BC Model, ADF Task Flows and ADF Bindings.

1. Use JET for front-end apps, with relatively simple complexity but strong requirement for performance and scalability. Back-end can be implemented with ADF BC REST. Typically it would take longer to implement JET UI comparing to ADF Faces (no drag and drop support, unless using Visual Cloud Builder Service for JET)

2. Use ADF Faces for complex and large back-office applications. Some degree of mix between ADF Faces and JET is possible. Back-end should be done in ADF BC

ADF is stable technology and Oracle is focusing to advertise new things on OOW. Recommended focus for ADF developers was around JCS, DevCS, JET and VBCS:


There was one session about how to move existing ADF app into the cloud with JCS. And session about ADF BC REST, no new features - mainly showing customer system implementation with current features.

JET open source contribution was announced, along with new JET offline support - persistence toolkit (will be available through NPM in next couple of weeks):


Oracle explained why handling offline use case in JET is important:


Persistence toolkit will run on JET hybrid, web and desktop apps (yes you can run JET as desktop app, with 3-rd party Electron plugin):


Here you can read more detail info about persistent toolkit design principles:


JET supports Fetch API (used by persistence toolkit):


Architecture explanation for JET persistence toolkit:


Another hot topic related to JET - Web components. Slots are supported, this allows to build advanced Web components with dedicated facets (ADF Faces terminology):


OOW'17 was packed with chatbot demos. Unfortunately there is no trial access for chatbot cloud yet. There was good session about chatbots from Lyudmil Pelov - he explained how Oracle chatbot service and language processing works:


I was impressed with Oracle Visual Cloud Builder Service progress this year. I really liked this service and I think it will become JET IDE development tool. Is not focused for business users only, but is targeted for JET developers too. It comes with embedded DB or you can call external services too. Next versions will allow direct JET code development, combined with drag and drop:


Develop JET in VBCS using drag and drop where possible and code additional logic in JS/HTML:


VBCS is not targeted for business users anymore, they target it for coders (us) too - thats news I like:



RDK UI is available now for ADF, JET and MAF. ADF RDK was updated to newer version. ADF and JET RDK UI look is identical.

New ADF RDK UI:


JET RDK UI:


Machine Learning was another big thing on OOW and JavaOne. Nice to hear things I was studying in university about neural networks are becoming hype now:


JVM garbage collection tuning. Is better to have objects to be dead young. This means in ADF is better to use Backing Bean Scope where possible, because short scope bean is destroyed after request and this allows VM to clean memory:

ADF BC REST Service from ADF Library JAR

Sun, 2017-09-17 11:39
I had assignment to enable ADF BC REST for existing ADF application, which was developed with multiple ADF libraries. ADF BC REST was supposed to be enabled for one of the ADF libraries and then accessed through Master application. All ADF BC REST samples usually show how to enable REST inside Master application itself. I was curious if it will work to enable ADF BC REST and package it into ADF library, which is consumed from Master application. It worked and I would like to share sample app.

Sample app is based on two JDEV projects - library and master applications. Library application contains ADF BC REST implementation for Employees VO:


ADF Library is generated out of ViewController project, ADF BC REST is packaged through dependency:


Model (enabled with ADF BC support) project in Master application imports ADF library:


Run Master application by running REST project. There is improvement in JDEV 12.2.1.3 comparing to 12.2.1.2 - re-deployment works even if dependent ADF library was changed (this is very useful fix - saves a lot of time during development):


REST response is received:


Download sample application - adfbcrest.zip.

Oracle JET List Implementation based on WorkBetter Alta UI

Mon, 2017-09-11 14:04
During weekend I was playing with JET WorkBetter sample app. I thought it would be nice to extract People list UI into my own app - so that it will be easy to reuse this UI pattern in our own JET applications. I succeeded to achieve my goal and would like to share WorkBetter Alta UI list sample with you.

This is how my own JET list UI looks like, based on sample app:


Header block is implemented in separate div, this contains title and toolbar for buttons. List content is rendered out of template located in its own div:


Template renders JET list component. List in turn is based based on item template:


Item template defines list row content and structure - through set of JET and custom CSS styles. Data attributes are referenced directly from template structure:


For this sample I'm using basic set of mock data defined in JS module, but obviously it can fetch data from REST service too:


Set of custom styles (created based on WorkBetter example) is located in override.css file within JET application structure:


Sample JET list application can be downloaded from GitHub - jetlistapp.

To build this application, I was using JET CLI commands. Especially useful I found options to strip application leaving only sources and then to restore JET environment - this helps to share code.

Here is the sequence of commands how I was using JET CLI:

ojet create jetlistapp --template=navdrawer (creates JET application)

ojet serve (runs JET application)

ojet strip (removes all files except your sources)

ojet restore (brings back JET environment, after application was stripped)

ojet serve (you can run application again, after it was restored)

Oracle JET Simple Table with Fake JSON Server

Thu, 2017-09-07 14:13
What if you want to build JET UI, but there is no back-end REST service ready yet. You could use static JSON data inside JET app and load it from the JSON file. This works, but data retrieval logic will need to be changed after REST service will be ready. This is not productive. Ideally you would like to have fake REST service to simulate REST calls from JET UI, until real REST back-end is ready.

This can be achieved with JSON Server. It provides full fake REST API to be used by front-end client. It is extremely easy to setup JSON Server with NPM. Run npm install to setup JSON Server:

npm install -g json-server


Create simple JSON file with data structure - this will be served from JSON Server:


Run JSON Server with this command, pointing to JSON file:

json-server --watch db.json


You should see REST endpoint URL displayed in the log. Use this URL in JET application to define collection:


JET CollectionTableDataSource can be created on top of collection backed by REST:


JET UI table component renders data directly from CollectionTableDataSource:


Table UI is rendered based on REST call:


To verify REST call, go to developer console and check network request. You should see request executed against fake JSON Server:


Response is visible too:


Download JET sample application with JSON file for JSON Server from my GitHub repository - jetsimplecrud.

ADF 12c Table CRUD Fix for Auto Focus

Sun, 2017-09-03 05:57
I had a post about how to improve user data entry for ADF table with auto focus for new row - Improving ADF UI Table CRUD Functionality with Auto Focus. If you follow comments thread for that post - you will see described approach doesn't work exactly as it should in ADF 12c (focus is set for new row but later is lost after tab navigation - it should move focus to another column). Thanks to the community we have simple fix for this issue, read OTN Forum thread - Set Focus on CreateINsert row in ADF Table. I hope Oracle will fix this functionality in the next ADF versions (currently they say it is expected behaviour, and I don't agree with this). But for now - fix does the job.

 Sample app was updated to 12.2.1.3 and it contains fixes described on OTN Forum - ADFTableFocusApp_v2.zip. Focus is set for first column of new row to avoid extra mouse click:


After tab is pressed - focus moves to the next column:


Fix simulates row selection through ADF JS API. After focus was set for the first column in current row - we execute row selection based on active row key. This allows ADF Faces to move focus to the next column on tab, because it knows currently selected row on client side:


Make sure to set active row key in the bean method, same place where focus ID is calculated (otherwise there will be JS error):

ADF Client Side Validation with JavaScript

Wed, 2017-08-30 09:25
In my previous post I explained how to use JS client side formatter for ADF Faces input components - ADF Goes Client Side - UI Performance Boost with JavaScript. The same principle can be applied for client side validation. Most likely you are not going to implement complex validation rules on the client side, but for simple checks - it will be perfect. There will be no roundtrip to the server and this will allow to improve user experience.

Client side validation check runs instantly when value is changed and there is no need to set Auto Submit = true to send value to the server. This rule checks value to be in certain range, similar simple checks can be implemented on client side (I'm sure you will find similar rules in your project):


If value is in range, client side formatter is applied as expected:


Custom JSF converter is registered in faces-config.xml and can be added to the input field either manually or dropped through the wizard:


Converter is based on ID, which is defined in faces-config.xml:


Definition in faces-config.xml:


Customer converter class defines range values, these properties will be consumed in JS logic:


Range check is done in JS. If validation fails, we display JSF error message. All happens on client side, without request to the server:


Download sample application with client side validation logic - ADFFormattingApp_v2.zip.

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 12.2.1.1):


Download sample application - ADFFormattingApp.zip.

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 - ADFVOFromSQLApp.zip.

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 - AMExtendApp_v3.zip.

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 12.2.1.2 Patch for Transient Expression Compilation Infinite Loop

Tue, 2017-07-04 10:26
If you are using JDeveloper 12.2.1.1 or 12.2.1.2, 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 12.2.1.2 and another one for JDEV 12.2.1.1):


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 (ADFBCCheckboxApp.zip) 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 - AppsCloudUIKit_v3.zip.

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 - ADFLovDescriptionApp.zip.

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 - ADFFacesRESTApp.zip.

Pages