Skip navigation.

Andrejus Baranovski

Syndicate content
Blog about Oracle technology
Updated: 3 hours 14 min ago

Oracle JET and WebSocket Integration for Live Data

Sat, 2016-02-06 09:57
I was researching how to plugin WebSocket into JET. I would like to share my findings and explain how it works. It is amazing, how scalable and quick it is to send JSON message through WebSocket channel and render it in JET. Luckily WebSocket client is implemented in JavaScript, this integrates perfectly with Oracle JET (also based on JavaScript).

Watch recorded demo, where I'm sending updated data with JSON message through WebSocket. UI chart is rendered with JET. See how nicely JET re-draws chart, based on received new data (watch at 6th second):


Download sample application - JETWebSocket.zip. This contains both WebSocket application (implemented with JDeveloper) and JET (implemented with NetBeans).

On WebSocket server side, I'm listening for DB changes (Database Change Notification Listener Implementation). Each time when DB change happens, all changes are collected into one collection and sent to the clients through WebSocket:


Changes are collected into array. WebSocket message must be encoded into JSON Array, this makes it easier to read it on client. Multiple JSON Objects are added into JSON Array:


Message is sent to all connected WebSocket clients:


All this happens on server side. Now lets take a look into client side. We should open WebSocket connection when JET is loading. I have included WebSocket client JavaScript code from separate file websocket.js. JET renders chart component:


Each time when WebSocket message is received by the client, onMessage method is invoked. This method is responsible to parse JSON message and pass it to function from JET context, where chart data update happens:


WebSocket is opened, when document is rendered. In the next step, JET View Model is created along with bindings:


Variable viewModel is accessible from WebSocket onMessage method, because it is defined outside of JET function:


Method updateChart invoked from onMessage, applies received changes to chart data. JET re-draws chart automatically, because changes are applies for observable array. This is really cool:


See how it works. Page is loaded with JET chart component, WebSocket is opened:


Go to DB and update few records, commit changes:


JET receives changes through WebSocket and chart is updated instantly:

Database Change Notification Listener Implementation

Sat, 2016-01-23 08:43
Oracle DB could notify client, when table data changes. Data could be changed by third party process or by different client session. Notification implementation is important, when we want to inform client about changes in the data, without manual re-query. I had a post about ADS (Active Data Service), where notifications were received from DB through change notification listener - Practical Example for ADF Active Data Service. Now I would like to focus on change notification listener, because it can be used in ADF not only with ADS, but also with WebSockets. ADF BC is using change notification to reload VO, when configured for auto refresh - Auto Refresh for ADF BC Cached LOV.

Change notification is iniatilized by DB and handled by JDBC listener. There are two important steps for such listener - start and stop. Sample application - WebSocketReusableApp.zip, implements servlet DBNotificationManagerImpl:


I'm starting and stopping DB change listener in servlet init and destroy methods:


DB listener initialization code is straightforward. Data changes are handled in onDatabaseChangeNotification method. Listener is registered againt DB table executed in initial query:


In my example I'm listening for changes in Employees table. Each time, when change happens - query is re-executed to calculate new average salary values for jobs:


On first load, when servlet is initialized - listener is registered. Initial data read happens and listener is reported as started:


I can change value in DB, commit it:


DB change listener is notified and query is being executed to fetch new averages. Value for SA_REP is changed:


I hope it makes it more clear how to use DB change listener. In my future posts I will describe how to push changes to JET through WebSocket.

Automatic ADF Logout on Browser Close with WebSocket

Sat, 2016-01-16 12:15
Every ADF project could have a requirement to handle browser close event effectively. Differently than desktop applications where we could handle such events, browser doesn't send any event to the server, when browser page is closed. This is especially important for transactional data, when user locks data row and lock must be released automatically, in case if user is closing browser without unlocking. Besides transactional data management, it is important for performance improvement - Web session will be closed instantly and WebLogic resources will be released. There was no reliable solution to handle this, now we can do it with WebLogic 12c and WebSockets. WebLogic 12c supports WebSockets natively, there is no need to configure anything or add libraries.

When WebSocket channel is closed, it delivers event to the server on browser close. We could use this event to release locked resources, we need to logout ADF session to force ROLLBACK. Sample application implements HTTP client invoked by WebSocket server endpoint. This HTTP client simulates browser activity and redirects to adfAuthentication with logout request, using original JSESSION ID from closed browser session. This works also during accidental client computer power off. Download sample application where I have described all important implementation steps - ADFSessionHandlingWebSocket.zip.

Sample application is protected with ADF Security, you can login with redsam/welcome1 user. It includes Oracle JET libraries, one of the dashboard tiles implements JET fragment. JET is not required for the sample to work, it is used only to implement dashboard UI.

You can observe from browser log when WebSocket connection is opened. Connection is established on initial page load, immediatelly after login. This opens WebSocket communication chanel, as soon as this chanel will be closed - WebSocket server endpoint will force logout for ADF session from closed browser:


As soon as WebSocket channel is established, ADF web session ID (JSESSIONID is retrieved from the cookie) is sent to WebSocket server endpoint. Sample logs ID of ADF web session:


I'm going to lock one of the records, I'm invoking ADF BC lock method (DB pool is disabled, this will keep DB connection assigned for AM):


Lock action for row data is visible in the log, SELECT FOR UPDATE is executed for ID 102:


Let's close a browser now without issuing ROLLBACK, invoke Quit action in the browser:


WebSocket channel will be closed and this will trigger ADF Authentication servlet request to logout from ADF web session. As logout happens, ADF resources are released, ADF BC is triggering ROLLBACK in DB:


Session is closed based on JSESSIONID. With HTTP Client we simulate user logout after browser was closed:


Now we should overview technical implementation. WebSocket channel is opened from JavaScript:


This happens on page load, with clientListener triggering connectSocket method:


Method connectSocket in JavaScript is using standard WebSocket API to open connection:


WebSocket server endpoint is defined with custom configurator. Through configurator we can reference HTTP session initiated in ADF. HTTP client in WebSocket endpoint will use it later, to simulate ADF logout:


ADF HTTP session is referenced through WebSocket configurator:


Helper session listener class is defined in web.xml, here I'm copying JSESSIONID from the cookie into session attribute (to be able to reference JSESSIONID in WebSocket endpoint):


OnClose method in WebSocket endpoint is invoked, when connection channel between client and server is closed (browser is closed). Here I'm invoking custom method handleLogout method:


I'm constructing HTTP client request with the same JSESSIONID value as it was copied from ADF session. HTTP Get is executed against ADF Authentication servlet with logout request using JSESSIONID value. This is forcing ADF session to logout from simulated HTTP session by HTTP client:


Edit Use Case for ADF 12.2.1 Dashboard with Masonry Layout

Fri, 2016-01-15 11:53
I was researching ways to implement edit functionality for dashboard created with ADF 12.2.1 masonry layout. Check my previous post, where dashboard was implemented - ADF 12.2.1 Responsive Dashboard with Masonry Layout. I have decided to use panel drawer component, which would bring editable fields in the context of data displayed in the dashboard.

Panel drawer icon is displayed in the top right corner of the dashboard:


User can click on the icon and this shows editable form for the data rendered in the dashboard:


Dashboard is implemented with masontry layout, it makes it possible to re-arrange tiles. This proves to be useful when editing data. I can move tile with the chart and change salary value. Chart is synched and new value becomes visible. Two actions are done at once - data update and change review in the chart:


One more use case - validation. While editing salary, we can check tile with minimum and maximum salary values. This could help to understand, what salary value can be accepted. For example, if too low salary is set, validation error is returned. User can cross check this in the chart with minimum and maximum values:


Panel drawer is defined in the same group, where masonry layout block is located:


Edit form is rendered through ADF region, this means it can be reusable:


Download sample application - DashboardApp_v4.zip.

Handling ADF BC 12.2.1 REST Validation in Oracle JET

Sun, 2016-01-10 15:37
CRUD use case would not be complete without validation logic implementation. Oracle JET allows to implement standard and custom validators on the client. Probably most of the simple to average complexity logic will be implemented in Oracle JET. Complex use cases can be handled in ADF BC validation rules, data will be validated through REST calls. When validation fails in ADF BC, error message is propagated through REST back to Oracle JET client, where we can parse it and attach to the UI field.

You can watch demo video, it shows how it works. I'm trying to update a row with invalid data, rules are executed in ADF BC and validation messages are displayed next to the UI fields in JET:


There are three rules defined in ADF BC. It might be tricky to map UI field with error message. This is easy in case of PATCH method, ADF BC REST returns failed attribute name together with the message. This doesn't work in the same way with POST method, when new row is created. For this reason, I have introduced custom indicator into each validation message *AttributeName*. I'm parsing this value in JET, to understand which UI field should be marked as incorrect.

Rule 1. Unique Key validation rule for Email attribute.


Rule 2. Hire Date validation rule, it should not be in the future.


Rule 3. Salary range validation rule.


Mandatory check is performed in JET, if mandatory UI field is not set - JET will prevent further call to REST service. I have achieved this with JET invalidComponentTracker property defined for JET UI input fields:


Tracker variable is defined and accessed in JavaScript, here we are going to evaluate if there are any issues on UI components, before calling REST service. There are three variables defined to report valdiation messages from ADF BC REST for Hire Date, Email and Salary fields:


In update function, before calling REST - I check if there are no issues with UI components by obtaining tracker:


Method showMessages is invoked for tracker, if there are issues - focus is set on the first one. If this doesn't happen, it means there are no issues and further REST call is allowed:


This is how it looks on UI. I'm trying to update empty row, there are mandatory fields and built-in functionality prevents me from submitting data:


Let's move to the main topic of this post - ADF BC REST call validation error handling. JET allows to define callbacks for REST call action - success/error. If ADF BC REST call fails with validation issue, error callback is invoked. Here we can get response text, parse it and assign to the UI fields. Multiple validation rules can fail at once in ADF BC, REST returns multiple messages in one response. This is good, we can display all errors at once:


Messages are attached to UI field through special property (and variable defined above) - messageCustom. This must be set on JET UI field:


In JavaScript callback, we are parsing response, constructing error message and assigning it to the messageCustom of specific UI field. This is how message is displayed on UI, next to the field:


Here is example of all three validation rules failing and messages are displayed on JET UI:


All three are reported in REST call response by ADF BC validation. We just need to parse returned message in Oracle JET and display it:


Download sample application - JETCRUDApp_v4.zip.

Very Practical CRUD with JET and ADF BC - POST and DELETE Methods

Tue, 2015-12-29 12:13
In my previous post I have described how to implement PATCH method with Oracle JET and call ADF BC REST service to update row attributes - Very Practical CRUD with JET and ADF BC - PATCH Method. Today I'm going to complete CRUD implementation with POST and DELETE methods, to create and delete rows through ADF BC REST service and JET UI.

Here you can watch video, where I demonstrate PATCH, POST and DELETE methods invoked from JET UI. Also you are going to see how pagination works with JET paging control and ADF BC range paging mode (Oracle JET Collection Paging Control and ADF BC REST Pagination Perfect Combination):


Download sample application - JETCRUDApp_v3.zip. This sample app contains JET UI and ADF BC REST implementation. I'm going to explain in more detail steps recorded in the above video.

Salary column was updated with right align in the new sample, in JET we can assign class name for table cell:


JET supports date formatters and converters. I was using yyyy-MM-dd pattern to format Hire Date attribute value:


POST method - row creation

New row is created with JET collection API method create. I have implemented success callback, if POST method in REST was successful and new row was inserted - collection is refreshed to display new row. There is no need to refresh, if collection is not virtualized (fetchSize and pagination is not used):


DELETE method - row removal

Row is removed from JET model with API method destroy. This calls DELETE method triggering REST service and removes row from JET collection, by refreshing current page (invoking GET method for collection page):


POST method test. Example of new row creation:


POST method is invoked by JET, which in turns calls ADF BC REST service and inserts new row through ADF BC into DB:


PATCH method test. Example of attribute value update. I have changed Salary attribute value:


Row with ID is updated by PATCH method through REST service call:


DELETE method test. Example of row removal:


Row with ID is removed by DELETE method through REST service call:


In my next posts I'm going to describe how implement validation and handle REST call errors.

ADF BC Groovy Improvements in ADF 12.2.1

Mon, 2015-12-28 14:28
Groovy scripting is improved in ADF 12.2.1. There are no inline Groovy expressions anymore. Expressions are saved in separate Groovy language file, external codesource. Each EO/VO will be assigned with separate file to keep Groovy expressions. This improves Groovy script maintenance (easier to check all Groovy expressions from EO/VO located in one file), also it improves runtime performance (as JDeveloper ADF code audit rule suggests).

Inline Groovy expressions created with previous JDeveloper versions are compatible in 12.2.1. All new expressions are created in separate *.bcs file. Sample application - ADFGroovyApp.zip, comes with validation rule implement in Groovy script expression:


We should check how validation rule definition looks in EO source. There is one inline Groovy expression I have created with previous JDeveloper version. It is marked as deprecated and suggested to be moved to external codebase:


Validation rule with Groovy expression created in JDeveloper 12.2.1 looks different. There is no inline Groovy code anymore, instead it points to the external codesource name:


Codesource name is registered inside operations definition:


I have defined two validation rules with Groovy for Jobs EO attributes MinSalary/MaxSalary. Code for both of them are included into single Jobs.bcs file:


On runtime it works correctly, entered values are validated against logic coded in Groovy:


Separate Groovy file approach can be turned off in ADF BC project settings, not recommended though:

Very Practical CRUD with JET and ADF BC - PATCH Method

Sat, 2015-12-26 12:48
I'm going to share few more tips, how to implement CRUD in JET and call ADF BC 12.2.1 REST service. You are going to learn how to implement table row selection and how to call REST PATCH method to update data through ADF BC REST service. Why very practical? You can take sample application code and use it in your project. Less theory and more practical hints - this is my approach.

This is how it looks JET table (with pagination control - Oracle JET Collection Paging Control and ADF BC REST Pagination Perfect Combination) and form. Download sample application - JETCRUDApp_v2.zip. User can select row and edit data in the form:


I'm going to change salary value for Alexander Hunold and invoke PATCH method with Update button click:


Through network monitor in NetBeans we can check REST method execution. PATCH method is executed for employee ID 103 with Content-Type set to Oracle ADF resource item:


Changed salary value is submitted through Request Data:


We should check ADF BC log. It shows executed SQL statement to update employee salary by employee ID. This works as expected:


Table row selection in JET is implemented with selection mode property:


ADF BC 12.2.1 REST service access in JET is easy. You need to define collection (set URL, fetchSize and model). In case of pagination, you should wrap table data source with paging data source type:


When collection is set with Fetch Size (collection is virtualized), there is a special way to access rows from the collection. Row retrieved by key from the collection, will be returned with Promise type. You should use then function to retrieve row value. This is how selected row data is retrieved. Next step is to update form fields to display selected row data, this is done through updatFields method:


Method updateFields sets each element from the form with values from selected row attributes:


Initially form elements are defined as observables with empty values:


In HTML each form field is mapped through data-bind property with  corresponding element defined in Java Script - this is how it's all mapped together:


Update button handles click event and calls update method:


Row data is updated through REST service with PATCH method, initialized by save operation on current row. Row to be updated is assigned with attribute values from form fields. PATCH method is configured through save operation property, you must do it explicitly. By default, PUT method will be executed, which requires to submit all attributes for the row, otherwise ADF BC will throw error. PATCH method is much better, there is no need to submit values for all attributes from EO row:


In my next posts, I'm going to cover create/delete, validations and call failure cases.

Oracle JET Collection Paging Control and ADF BC REST Pagination Perfect Combination

Sun, 2015-12-20 09:15
Oracle JET provides out of the box support for collection paging control, this allows us to use table/list UI with show more option or pagination - Paging Control: High Watermark Table with unknown row count. The main advantage of pagination from performance point of view - no need to load entire collection at once. Data from the REST service can be loaded to the UI in small portions.

I did a test to check how it works to use JET pagination control on top of data from ADF BC REST service. It works great, it seems to be ADF BC REST and JET collection with pagination control are in perfect synch. ADF BC REST service is fetching data based on JET pagination settings.

Here you can download sample application (this archive contains two projects - ADF BC REST implemented in JDEV 12.2.1 and JET UI implemented in NetBeans) - JETCRUDApp_v1.zip. Make sure to download JET distribution and copy JS/CSS into my sample app.

JET UI table with show more functionality rendering Employees table data received from ADF BC REST service:


I have configured JET to render 10 rows initially. ADF BC receives request to fetch 10 rows, we can see that from iterator range size:


ADF BC is configured with Range Paging support. SQL query is constructed with rownum to fetch only a subset of data for requested 10 rows:


Let's load more rows, click show more and 10 more rows will be loaded out of total 107:


We can observe correct behavior in ADF BC log. SQL query with rownum is executed and two ranges (1-10, 10-20) are filled with data, which corresponds to JET UI request:


Show more functionality for collection in JET is configured with loadMore mode option set for paging control. You should put paging control below table UI in JET, in HTML page:


JavaScript method responsible to call ADF BC REST service and construct collection data source with paging control sets fetch size. Through fetch size property, JET controls how many rows will be rendered in the page or how many more rows will be displayed with show more functionality. Fetch size is sent to ADF BC REST service, where VO range paging and data fetch are controlled accordingly:


If you want to render pagination instead of show more option, remove loadMore property from paging control. Table pagination out of the box rendered with JET on top of data fetched from ADF BC REST service:


I can load second page of data and check how rows are fetched in ADF BC:


ADF BC works the same way as with JET show more option. It executes SQL query with rownum based on range paging enabled and fetches first two pages of data. It would be preferable, if it would fetch only second page of data. Differently from show more option, user can't see first page anyway (we should log enhancement request with Oracle Support):


At the end of each request, ADF BC executes SQL to count rows. I guess this is needed for JET, to know total number of rows:


I was positively surprised, when I saw how fetch of the last page works. Instead of fetching all rows before last page (which is usually the case with going to the last page in ADF), ADF BC REST fetches only rows displayed in the last page. This makes JET UI paging control really fast and useful. Here I'm going to the last page in JET UI table:


ADF BC is fetching rows only for the last page, no rows fetched in between:

Improved JET Rendering in ADF

Thu, 2015-12-17 07:02
This post is supposed to provide improved solution for the approach described previously - ADF and Oracle JET - Integration Pattern with ADF Regions. Many thanks to John Brock, Product Manager for Oracle JET, for his proactive comments and suggestions.

I have changed it to JET rendering in ADF, instead of integration. Perhaps word 'integration' is too strong in this context. You should not mix two frameworks together, like trying to render data from ADF bindings in JET components. Oracle doesn't encourage mixing ADF and JET, there is no support for this.

But still there are valid business requirements to create JET islands inside ADF. For example, fast data entry or displaying data from WebSocket. We could use JET table on top of REST within ADF page and allow users to type and save data really fast. There will be no integration between ADF and JET features, simply JET UI rendering inside ADF page. Similar as ADF DVT components currently work, they are based on JET libs (at least I heard such talks on OOW).

Here you can download improved sample application (you must download JET separately and copy into public_html folder) - DashboardApp_v3.zip. Improvements:

1. No need to use ADF region, it works to isolate JET code into JSF fragment


2. We can use simple JSF include to include fragment with JET into ADF page


3.CSS stylesheet is loaded once in the main page. Using af:resource, instead of script:


4. This is how it looks, chart is rendered by JET component. Obviously we could render same chart with ADF DVT, but here is only simple example. In the future I will post more advanced use cases. ADF UI built with Masonry layout, including JET island tile:

Checking for Data Consistency with ADF BC REST 12.2.1

Sun, 2015-12-13 10:27
ADF BC REST supports HTTP ETag to check for data consistency. This is common approach to implement caching and optimistic locking in REST.  ADF BC REST relies on EO change indicator attribute, when change indicator attribute value is updated, new ETag is generated. All clients with previous ETag value should be prevented from updating data, without refreshing to the latest state. Read more - 22.9.1 Checking for Data Consistency When Updating ADF REST Resource Items. There are issues with data consistency check in ADF BC REST, hopefully it will be fixed in the future (read below).

To test data consistency check, enable discriminator attribute in EO. I have enabled Salary as discriminator. Each time when this attribute is changed, new ETag value will be generated and clients holding previous value will require to re-query:


GET with If-Non-Match use case (works)

Initially we don't know ETag attribute value, we can query with empty value in If-Non-Match header. Current ETag value for the row will be returned together with the data:


Copy ETag value into If-Non-Match header field and try to execute GET request. If row data is not changed (discriminator not changed), there should be no result - ETag remains the same. This can be useful when we want to check if there are any changes in the current row:


I would like to update discriminator value to check how GET would work with changed ETag. I have tried to update with PATCH from another REST client. Unfortunately current ADF BC REST implementation contains a bug and doesn't allow to update discriminator attribute (we are going to log a bug with Oracle Support):


I'm going to update discriminator value directly in DB:


Execute GET with If-Non-Match set to previous ETag - new row data will be returned (take a look, new ETag value is different from previous one):


PATCH with If-Match use case (doesn't work)

When you try to update data and row is already changed on the server (discriminator value changed), update should be prevented. This is how it should work and it almost works that way in ADF BC REST.

We can execute PATCH with If-Match value set to the same as it is set for current row on the server. Update is successful, as it should be:


Change discriminator value in the DB, this will force server to generate ETag value in the next request and it will not match with the one on the client (it should prevent next update):


Try to execute PATCH with previous ETag value, update doesn't happen (correct), but it also returns some strange message (not correct). It should be 412 (Precondition failed) HTTP code returned instead. This should be fixed (another bug to log with Oracle Support):


Download sample application - ADFBCRestApp_v4.zip. Read my previous post about ADF BC REST - Range Paging and ADF 12.2.1 ADF BC REST.

Range Paging and ADF 12.2.1 ADF BC REST

Sat, 2015-12-12 06:27
ADF 12.2.1 ADF BC REST service is compatible with range paging mode of ADF BC View Object. Range paging generates SQL query with rownum to retrieve only a subset of rows to be returned to the REST service. This can be especially effective when executing SQL query against large tables. Range paging size is determined dynamically by parameter in REST URL.

When range size is not specified, ADF BC returns 5 rows. This number represents iterator range size configured by default and it can be changed in iterator binding (the one generated for REST service). In the example below, I have changed returned rows size to 10. Parameter limit sets how many rows will be returned in one call:


Instead of default 5 rows, 10 rows will be returned now. This is visible in the log, View Object is updated based on the new range size (changing iterator range size from :5 to :11). SQL query is executed and 10 rows are fetched (similar principle as with ADF Faces table). No range paging is configured for the VO yet::


Let's change VO to work in Range Paging mode. No need to set Range Size, it will be updated automatically based on the number of rows fetched by REST service:


Same 10 rows are being fetched, SQL query is updated to fetch with rownum. It fetches a range of rows required to fill requested range by REST:


Now let's fetch second page of data. This can be done using another parameter - offset. Change offset to 1 * limit, this will fetch second page of data:


This time ADF BC executes two range paging queries. One for first page and another for second. Results from second query are returned to REST service. The same principal works with ADF Faces table. While this is still better than running VO without range paging, but there should be no query executed for the first page. We are going to log a bug for this with Oracle Support:


Download sample application - ADFBCRestApp_v3.zip. Check my previous post about  CRUD support by ADF BC REST - CRUD with ADF 12.2.1 ADF BC REST.

CRUD with ADF 12.2.1 ADF BC REST

Tue, 2015-12-08 13:22
I had a post about REST support by ADF BC in ADF 12.2.1 - ADF 12.2.1 ADF BC Support for REST. This was introduction, today I will go further and test CRUD (Create Read Update Delete) operations (using Postman REST client). Good news, CRUD are supported by ADF BC REST out of the box, there is no need to code anything. ADF BC REST services are well documented in ADF developer guide - 22 Consuming RESTful Web Services Using the ADF REST Framework.

Operations - Create, Update and Delete are available and enabled by default (see under section -Available Operations):


CREATE. ADF BC REST service is defined on top of Employees EO. I'm going to create new record in Employees table. We should use HTTP POST to insert new record. Very important is to specify Content-Type as application/vnd.oracle.adf.resourceitem+json, otherwise request will fail with parse error:


Data for the new record is supplied in raw format, mapping between row attributes (case sensitive) and attribute values:


New employee #999 record is inserted into DB:


READ. We can read data using HTTP GET operation. There is option to get row by key or you could query data by criteria. There is option to use Row Finder based on View Criteria. In this example I'm using query with criteria, searching for all employees with FirstName starting from J:


UPDATE. To update row data, we should use HTTP PATCH operation. You must provide key for the record and supply attribute/value pair to be updated. Content-Type as application/vnd.oracle.adf.resourceitem+json must be set for operation to succeed:


Salary value is updated in DB:


DELETE. To remove record, execute HTTP DELETE operation by row key:


Download sample application - ADFBCRestApp_v2.zip.

ADF and Oracle JET - Integration Pattern with ADF Regions

Sun, 2015-11-29 10:41
In my previous post I have shared basic example for Oracle JET integration into ADF - Oracle JET and ADF Faces Integration in ADF. Today I would like to share a bit more than that - integration pattern with ADF Regions. This approach would allow to use JET functionality within ADF environment and leverage ADF reusability.

Sample application - DashboardApp_v2.zip, implements ADF dashboard UI and includes one tile rendered by Oracle JET. You can watch video with running sample:


ADF tile renders a bar chart implemented by Oracle JET:


Integration pattern is straightforward, especially if you are familiar with ADF concepts. There must be separate ADF region defined to hold ADF fragment, where JET HTML code will be implemented:


JET HTML is included into ADF fragment, there are no additional ADF Faces components here, besides top grouping:


ADF region is reusable and we can reuse the same JET code in different ADF pages. Here is the example of ADF region (with JET HTML inside) usage in the page:


JET JavaScript function is the same as you would use for typical index.html page, nothing special here for ADF:


Read update for this post - Improved JET Rendering in ADF.

Oracle JET and ADF Faces Integration in ADF

Thu, 2015-11-12 22:49
Oracle JET provides a set of UI components, based on a combination of HTML and JavaScript. ADF Faces is an Ajax-enabled rich JavaServer Faces component framework that uses JavaScript to render client-side components, implement rich component functionality, validate user input and convert user data input. Although it is not officially documented, but obviously Oracle JET components can be integrated into JSF pages implemented with ADF Faces. I think such integration provides many benefits to ADF Faces. Use cases where performance is critically important can be implemented with Oracle JET client components and rich functionality can be implemented with ADF Faces, all in the same ADF application. Probably I would not create dependencies between Oracle JET and ADF Faces components rendered on the same page. Oracle JET should render data coming from REST services, while ADF Faces should work with data obtained from ADF Bindings layer.

I have managed to implement Oracle JET component and ADF Faces UI in the same physical ADF page. Oracle JET group renders input text, user types text and this text appears in the output below (use case is described here - Getting Started Quickly without the JET QuickStart). ADF Faces UI group renders regular ADF data entry form with navigation and save/cancel buttons. It all works together on the same page:


Download sample application implemented with JDeveloper 12.2.1 - SimpleADFApp.zip. I did not delete Oracle JET libraries from the sample application, so you could download and directly run it. Download size is a drawback, Oracle JET is part of application and it occupies around 11 MB.

Some text is entered into Oracle JET field, on enter it is copied into output below:


ADF also works as expected, for example I can change Salary value and commit changes with Save button:


ADF validation also works fine, I remove value for mandatory field and try to save. Required validation message will popup:


Take a look into ADF application structure with Oracle JET elements inside. Basically I just copied Oracle JET files into ADF ViewController public_html folder:


There is Oracle JET JavaScript file, where function is implemented to handle text entry and output update, pretty simple one:


Here it comes the most important part - ADF page. Instead of using HTML page to implement Oracle JET, I'm using regular ADF page based on JSF and ADF Faces. Oracle JET CSS and RequireJS script for Oracle JET are defined in the top of the page, just above the form - this will make sure correct initialisation for Oracle JET:


Oracle JET UI (input text, together with output text) is defined inside ADF Faces Panel Header with HTML div. This is how Oracle JET is rendered inside ADF page, using HTML:


Stay tuned and I will be posting more use cases on Oracle JET integration topic.

ADF 12.2.1 Responsive Dashboard with Masonry Layout

Wed, 2015-11-11 11:07
ADF 12.2.1 is a breakthrough in responsive UI. Never before it was so easy to implement good looking and high performance ADF UI. Masonry layout component allows to develop responsive dashboard made from separate tiles. Tiles can be reordered, resized and even removed. Tiles layout is dynamically constructed based on available screen size.

You should see how it works, check video based on sample application - DashboardApp.zip. Tiles are reordered as I change screen size, and even more - I can reorder them by myself, just with drag and drop:


This is default dashboard layout with four tiles on wide screen:


As resize screen to be more narrow, tiles are recorded to occupy available space:


With even more narrow screen, tiles are reordered to occupy only one column:


User can scroll up/down on narrow screen to see all tiles:


I can move and reorder tiles manually with drag and drop. In this example I reordered tile with employee information to be below employees chart:


If screen width is resized to be even more narrow, ADF 12.2.1 responsive UI template (check my previous post about responsive UI improvements in ADF 12.2.1 - ADF 12.2.1 Responsive UI Improvements) will reorder facets and there will be only one column UI:


Implementation is simple, you should use new ADF Faces component - Masonry Layout. Add any number of UI layout components (tiles) inside. Manual reordering is handled with regular ADF Faces drag and drop functionality:


Each tile must be assigned with masonry layout style class, this will control tile dimensions:


You can watch OTN ArchBeat video, where I'm talking about ADF 12.2.1 and responsive UI:

Oracle JET - Rendering Table from ADF BC REST Service

Sat, 2015-11-07 22:09
Oracle JET - new tool for us to build UI applications with JavaScript. Right now there is no out of the box integration with ADF Faces, I heard on OOW there might be some sort of integration available in the future. At the end of the day this is only JavaScript and you can integrate it into existing ADF page by yourself. Probably you would not want this, ADF Faces offers very rich set of functionalities and there is no need in extra components. Unless you would like to use WebSockets in ADF and would like to push data from JavaScript into DVT components - it could be easier to do this with JET, instead of going through ADF Bindings layer.

JET comes with developer guide, this is the first source of information along with Cookbook examples. I have implemented sample application for today post, based on developer guide section - Creating a CRUD Application Using Oracle JET. Here you can download the sample - SimpleJETApp.zip. If you would like to run it, make sure to add JET JavaScript libraries, you can take them from JET QuickStart. Size of these libraries was too large, this is why I have removed them.

REST service is implemented with ADF BC, I have described it in previous post - ADF 12.2.1 ADF BC Support for REST.

This is how it looks a table rendered with JET from REST data supplied by ADF BC, with pagination support. JET is using Alta UI style, visually there is no much difference comparing to ADF Faces:


Data is displayed from REST generated on top of ADF BC:


Typical JET use case is implemented by combination of JavaScript and HTML files:


JavaScript function contains a logic to invoke and parse REST service, everything is handled by JET API and popular JavaScript modules (such as Knockout, etc.). You can see how REST resource URL is defined and there is parsing rule to apply to the fetch result. I have set to fetch up to 20 rows only:


There is main JavaScript file in JET. You need to include initialisation steps there:


The last step - UI. JET offers table component with pagination support. Pagination happens on client side, this means you should not fetch many rows anyway. UI structure is pretty simple:


I have recorded a video to show how table pagination works. All rows are on client side and still pagination is not super quick, as I would expect it:


For comparison, I have uploaded table pagination performance video for ADF 12c Alta UI. ADF Faces pagination support works pretty quick, if not faster:


I'm happy to have additional Oracle development toolkit available. We are going to use it in our projects in combination with ADF.

OOW'15 Session Slides - Oracle Alta UI Patterns for Enterprise Applications and Responsive UI Support

Wed, 2015-11-04 23:46
You can view slides from recent OOW'15 session (Oracle Alta UI Patterns for Enterprise Applications and Responsive UI Support [UGF2717]) on SlideShare:



I was explaining how to implement responsive layout and fast performance ADF 12c applications with Alta UI. New ADF 12.2.1 features were discussed. Session went pretty well, all demos were working without issues. I was happy with the feedback, for example a tweet from Grant Ronald:


Here you can download session demo application - oow15.zip. This application includes high performance ADF Alta UI dashboard with WebSockets.

ADF 12.2.1 ADF BC Support for REST

Wed, 2015-10-28 13:46
ADF 12.2.1 provides out of the box support for REST. You should read about all available REST functionality in ADF BC here - 16 Creating RESTful Web Services with Application Modules. I have created very quick sample application to test how it works.

Before generating REST on top of ADF BC, you must configure release version for REST. This can be any number:


To generate REST, go to REST Web Service interface in Application Module and add new REST resource. Here you can select VO and provide REST resource name:


JDeveloper generates REST resource where you could configure attributes to expose, custom methods, etc.:


As soon as you generate REST resource on top of ADF BC, JDeveloper creates new project with web.xml. You could use this project to run/test REST (simply right click and choose Run to test on integrated WLS):


I can test REST through URL: http://127.0.0.1:7101/restapp/rest/1/Employees, ADF returns well structured REST response:


ADF is smart to return only a subset of data, it offers a parameter to control how many rows to fetch in a single call, it also shows if there are more rows to be returned in the result set:


I can set limit parameter to retrieve only one row, this is how it works:


Download implemented sample application - ADFBCRestApp.zip.

ADF 12.2.1 Responsive UI Improvements

Tue, 2015-10-27 15:30
ADF 12.2.1 provides much better responsive UI support comparing to previous version ADF 12.1.3. Previously we were using CSS media queries to hide/show facets. This worked, but it was not great from performance point of view. Same region was duplicated into different facets, both loaded into memory, but only one displayed. ADF 12.2.1 comes with new tag af:matchMediaBehaviour, this tag is using CSS media query to detect screen size, and it updates layout component property. No need anymore to use different facets, we can update properties directly.

This is how works, check in the video. Two blocks implemented with ADF regions are re-arranged into top-down layout, when screen size becomes too narrow to render left-right layout:


Here is the example of panel splitter layout component with af:matchMediaBehavior tags:


This tag contains three properties - propertyName, matchedPropertyValue, mediaQuery. You can define property of layout component to override through propertyName. New value for the property is defined by matchedPropertyValue. CSS media query is set to define condition, when layout component property value should be changed based on the screen size (if screen size is less than defined):


Two ADF regions are displayed right to left, when screen size is wide enough:


Same two regions are re-arranged to display in top to down layout:


Download sample application - ADFResponsiveUIApp.zip.