Andrejus Baranovski

Subscribe to Andrejus Baranovski feed
Blog about Oracle technology
Updated: 10 hours 53 min ago

Generic BigDecimal Formatter in ADF 12.2.1.1

Tue, 2016-08-30 11:39
I have implemented couple of improvements for BigDecimal formatter based on ADF 12.2.1.1. Originally formatter was implemented and described in this post - Handling Format for BigDecimal Numbers in ADF BC. New improvements: option to support trailing zeros and disabling number rounding.

1. Support for trailing zeros

If you type number 3000.10, BigDecimal type attribute will keep it as 3000.10. But in database it will be saved without trailing zero as 3000.1. This would lead to "Another user has changed the row" issue, as there will be mismatch between value in DB and value in ADF BC.

Try to enter 3000.10:


Save, change any other field and try to save again. You will get error:


Double check in DB, value is saved without trailing zero. Thats the reason for the error, data mismatch:


Solution is to parse entered value into BigDecimal without trailing zeros in generic formatter class:


2. Disabling number rounding

By default when you type 2500.209 (and if only 2 digits after dot are allowed):


This will be rounded to 2500.21:


While rounding can be useful, most of the time it will be confusing. There is a way to disable rounding by removing af:convertNumber tag for UI component. Formatting still will be applied through generic formatter class:


If user enters incorrect number, instead of rounding it - formatting error message will be displayed:


Download sample application - ADFFormattingApp_12211.zip.

Oracle JET Hybrid Receiving Mobile Cloud Service Notification

Sun, 2016-08-28 01:50
Oracle JET Hybrid enabled with Cordova Push plugin can receive notifications sent from Oracle Mobile Cloud Service (MCS). You should read how to setup infrastructure in this article - Your first Push notification based Oracle JET Hybrid application!. I will focus on implementation steps and will provide working sample app for download.

Sample JET hybrid application provides login functionality. During login we register device ID with MCS service, this allows to receive notifications:


After login is completed, default dashboard page is displayed. At this point, application is ready to receive notification (even if application will be closed or mobile device screen is locked):


Notification from MCS can be sent programmatically from API implementation. I will show this in the next posts. For now we can use MCS UI to test if notification is working. Mobile Backend provides functionality to send notifications. I can target notification to specific user:


If mobile device registration was successful during login in JET Hybrid, MCS wil send notification and you should see confirmation message (if there will be error, this means registration from Oracle JET Hybrid was unsuccessful):


In few seconds you should see notification received and displayed in notifications screen:


Select notification and it will navigate directly to the app and pass notification message. This would allow to parse it do certain action in the app, for example refresh data, etc.:


To verify if registration with MCS was done correctly during login, you can check logs in Mobile Backend. There must be REST POST /register call logged, just after GET /login:


It would not work to send notification, if there is no Client defined in MCS Backend. You can read more about it from the article mentioned above. Make sure to specify all keys correctly, pointing to Google Cloud Messaging (if you are targeting for Android):


Let's take a look into implementation on JET Hybrid side. Login success callback invokes method to register device to receive push notifications from MCS:


Make sure Cordova Push plugin is installed into your app, otherwise PushNotification will be undefined. It gets registration ID from Google and makes another call to handshake with MCS:


I'm invoking wrapper method, which in turn have access to MCS SDK module in my JET app:


MCS SDK method registerForNotifications is invoked, where REST POST call is made to register device with MCS and allow to receive notifications:


Download sample application (this contains only JET implementation JS/HTML, you should copy it into root src folder of your JET hybrid app) - jet_mcs_notifications.zip.

Oracle JET and Mobile Cloud Service Authentication with OAuth

Sat, 2016-08-20 04:58
I will describe with practical example, how to authenticate against MCS in Oracle JET using OAuth. This is based on sample app from my previous post - Oracle JET and Application Container Cloud (with MCS Integration) (download sample app from there). It would be useful to read through MCS documentation - Authenticating with OAuth in Individual REST Calls.

Oracle JET sample application provides login form:


If login is successful, REST call is done and MCS returns data:


In order to authenticate using OAuth, we need to use Application Key defined in MCS Mobile Backend:


Go to Mobile Backend settings screen and note down OAuth property values for Client ID and Client Secret. We are going to use these values in JET application, to initialize OAuth authentication:


There is one test user defined in Mobile Backend - redsam. We can use these user to login from JET over OAuth:


MCS offers to download SDK Java Script code, we could use it in JET application, to authenticate against MCS service through OAuth, Basic or Facebook login. Download SDK from getting started page:


I'm using mcs.js from MCS SDK, you could find helper method in this class - it executes REST POST to authenticate through OAuth and gets temporary access token in return. This token can be used for subsequent requests in the same session:


There is one more wrapper JS file - mbe.js. Here you define mobile backend connection keys. Authentication type is specified as oAuth:


Make sure to add mcs.js module into main.js paths:


Key point - mbe.authenticate() method (call it from JET module, make sure to reference mbe module in require block). Provide username/password and callbacks for login success and login failure:


In login success callback, I'm reading temporary token and passing it through header Authorization : Bearer. This token can be used for REST requests to MCS:


UI component is displayed when authentication is successful:

Oracle JET and Application Container Cloud (with MCS Integration)

Tue, 2016-08-16 13:44
I have deployed JET application with Mobile Cloud Service (MCS) integration into Oracle Application Container Cloud service. It works perfectly well, you can try to access it yourself (until my trial cloud account expires on 15th of August) by URL: https://rsjetnodejsapp-deoracleem99369.apaas.us2.oraclecloud.com.

Follow excellent blog article written by Lucas Jellema on details how to deploy JET into Application Container Cloud - Deploying an Oracle JET application to Application Container Cloud and running on Node.js.

First step is to generate empty Node.js application, you can do this from command line (install Node.js and express generator before):

express RSJETNodeJSApp

Navigate into generated application folder and add dependencies using npm:

npm install

Node.js application is created and you could run it by:

npm start

You could test JET app locally with the same command, as soon as you add JET content into Node.js app.

Once you access deployed JET application by URL: https://rsjetnodejsapp-deoracleem99369.apaas.us2.oraclecloud.com. You should get into Home tab, where static chart data is rendered (no integration with MCS yet):


I did a test to check how same screen looks on mobile device. JET renders perfectly, template is adjusted, as well as chart itself:


Go to People tab, this is where integration with MCS is done. I have implemented oAuth security authentication in JET, against MCS service (I will describe it in the next post). You can login with redsam/Wel_come1 user:


Same login screeen is rendered on mobile device nicely:


Once login is successful, JET app executes REST call to MCS endpoint and fetches data (originally returned by ADF BC REST service deployed on Java Cloud and accessed by MCS Connector):


Mobile device view doesn't dissapoint again, same page UI looks great:


JET implementation code is copied into Node.js structure public folder. You can open app in NetBeans, this would simplify editing:


I have deployed this app to Application Container Cloud by creating zip archive (make sure to create manifest.json file). Don't include root folder into archive, include application folders/files directly. Deployment is straightforward, create new Node.js application in Application Container Cloud:


Upload archive, give application name and wait few minutes to initialize. All done:


Here you can download complete example of Node.js app with JET content (and all libraries) I was using to deploy to Application Container Cloud - RSJETNodeJSApp.zip.

Oracle JET Hybrid - Calling Oracle Mobile Cloud REST

Sun, 2016-08-14 13:59
Oracle JET allows to build mobile hybrid apps, based on Cordova and deploy to Android or iOS platform. Read more about it here - Go Mobile with Oracle JET As Easy As 1 2 3. In my previous post I have described how to call REST endpoint running on Oracle MCS from JET - Calling Mobile Cloud REST Service from Oracle JET. Its time to demonstrate the same from JET hybrid app, running on my Android phone.

Here is the screen capture of JET hybrid app running on Android device and displaying data fetched from MCS REST endpoint:


To test data re-fetch, I have updated one record directly through MCS endpoint tester UI, using REST PATCH:


In mobile app, I navigated outside Customers screen and back - data is re-fetched, chart is changed:


What is great about JET hybrid, you could use identical code for JET rendered on the Web and JET rendered on mobile device. You could copy paste the same code between Web and mobile hybrid implementations. Here is example from sample app, where chart and list are displayed:


JET model points to MCS endpoint and defines data collection, same as it would be done for JET rendered on the Web:


Data is fetched in special method - handleActivated. This method is invoked automatically when View Model becomes active (user opens it from the menu). This is quite handy, to have such entry points in the app:


Download sample app code - js_jethybrid_v1.zip, where I have packaged Java Script and HTML examples. You should copy it into application with JET libraries to run.

To build JET hybrid app use:

grunt build:dev --platform=android

To deploy to Android device use:

grunt serve --platform=android --destination=device

Read more about how to create JET hybrid app here - Go Mobile with Oracle JET As Easy As 1 2 3.

Calling Mobile Cloud REST Service from Oracle JET

Wed, 2016-08-10 09:51
Let's take a look how we can consume REST service exposed from Mobile Cloud Service (MCS). I will show how you could display data coming from MCS endpoint in Oracle JET. I will be using simple scenario in this post, based on HTTP Basic authentication method offered by MCS. In my next post I plan to review more advanced authentication described in this article - Hybrid Mobile Apps: Using the Mobile Cloud Service JavaScript SDK with Oracle JET.

JET application (download release package with sample code - release_jet_mcs_v1.zip) renders bar chart with data retrieved from MCS endpoint returning information about employees:


Once data is retrieved, I can see invocation statistics logged and reported in MCS dashboard. Calls are executed successfully:


To call MCS service from Oracle JET, we need to pass to extra headers - Authorization and Oracle-Mobile-Backend-ID. Values for both headers can be obtained from MCS dashboard. Go to Mobile Backend and navigate to Settings section. You will find required info under HTTP Basic section:


To bypass CORS issue, you can specify Security_AllowOrigin property in MCS (you need to be admin for this). Read more about it in MCS Developer Guide - Environment Policies and Their Values.  Download property file to your local environment, change it and upload back:


For test purposes, I have specified Security_AllowOrigin=allow:


Oracle JET application JS module is pointing to REST URL handled by MCS:


Fetch operation is configured to pass two headers specific to MCS - this will allow to complete REST request and get response:


NetBeans tool Network Monitor displays request headers (both MCS headers are included):


If request is successful, you should see data returned in the response:


Oracle MCS with ADF BC REST Connector

Mon, 2016-08-01 14:17
We already learned how to deploy and access ADF BC REST services from Oracle Java Cloud - ADF BC REST 12.2.1.0 Running Live in Oracle Java Cloud. It's time to see how ADF BC REST can be consumed by Oracle Mobile Cloud Service (MCS). In my point of view, key benefit of MCS is ability to simplify Web Service access for mobile clients, by aggregating these Web Services from different sources and simplifying them. I will try to describe it in very structure way, how to define MCS interface based on ADF BC REST.

Let's start from the top - MCS Web Service interface visible to mobile clients. I have defined four endpoints in MCS, based on ADF BC REST service - list of employees, new employee, employee by ID and update employee. As you can see from MCS tester, implementation details are hidden from the user and you would not know there is ADF BC REST is working in the background.

POST

Create new record. Data is supplied through Body:


You should see newly created record data in the response:


PATCH

Update existing record by ID. If value is invalid, ADF BC REST returns validation message:


When we fix value and try to update again, attribute value is changed:


GET by ID

This can be used to fetch resource by key:


GET

Returns a list of resources


At this point you should be familiar with implemented endpoints. Next I will describe how REST Connector, Custom API and Mobile Backend are configured in MCS.

REST Connector

Connector is defined to point to ADF BC REST service deployed on Oracle Java Cloud. We need connector in order to be able to call external Web Service. Connector is named as EmployeesList:


ADF BC REST service is protected by ADF Security. For this reason there is one rule defined to provide authorization header for REST requests:


Custom API

This is a proxy between connector calling external Web Service and service exposed to mobile client. Here we define available endpoints and implement calls to connectors or other MCS services (storage, notifications, etc.) through Node.js:


Endpoints for REST service are defined here, same ones as described above in MCS tester. We have /employees and /employees/{employeeId} endpoints:


Endpoint /employees is suppose to return a list of employees, without specifying a key or to execute POST to create new employee. GET method is defined to return list of employees:


POST method is defined for /employees and is supposed to create new employee:


GET method for /employees/{employeeid} is supposed to return employee by ID:


PATCH method for /employees/{employeeid} is supposed to update attributes for given employee:


Next important thing in custom API is implementation. This is the place where Node.js transformation between Web Service connector and MCS interface is defined. It can't be edited directly in the cloud, you should download JavaScript package to your environment and edit there. Upload it back when done. Download implementation for my sample app - employees_v3.0.zip:


Let's check implementation. This is the structure of implementation archive. JavaScript file employees.js contains implementation for MCS endpoint interaction with REST connector. JSON file package.json provides metadata for the implementation:


Endpoint GET method is implemented to call EmployeeList connector and to retrieve Employees resource (by calling GET). ADF BC REST supports onlyData=true parameter to return data only, we can pass it through HTTP parameters. Callback for successful result transfers data from REST connector to MCS:


GET by ID is implemented in similar way. Only difference - we add EmployeeId to Employees resource, this constructs REST URL Employees/100:


PATCH is a bit more complex. It needs to set Employee ID, pass request body (with JSON String including attributes to update) and specify ADF BC REST supported Content-Type. This makes it easy for mobile consumer, no need to worry about such things as Content-Type, etc. There is also option to log data, it could be useful for debugging purposes:


POST is pretty much similar to PATCH, it calls post method through connector:


Read more about Connector API in developer guide - Calling Connector APIs from Custom Code.

You must explicitly register Connector to be accessible from API implementation, this is done in package.json:


Mobile Backend

I will show how to read debug messages logged in Mobile Backend, when testing endpoints defined by Custom API. We execute PATCH:


All operations are executed through Mobile Backend, this is the place where we can check statistics and see the flow of REST calls and other actions:


These five actions where invoked during PATCH. You can see payload body content printed, this is done from Custom API implementation function:

ADF BC REST 12.2.1.0 Running Live in Oracle Java Cloud

Wed, 2016-07-27 04:22
It passed almost two years since my previous post about Oracle Java Cloud and ADF - End-To-End ADF Cloud Deployment Process. There is huge improvement in Oracle Cloud, great progress done in these two years by Oracle. Access and management of Oracle Cloud environment is so smooth now, it is even hard to say you are working with your own on premise servers or cloud machines. This is great, I'm impressed - well done Oracle.

I have implemented ADF BC REST application with JDEV 12.2.1.0 and deployed it to Java Cloud. You can access REST service yourself from this URL: http://140.86.3.179/restapp/rest/1/Employees (username: redsam, password: welcome1).

I can monitor deployed application with ADF BC REST through Enterprise Manager in the Cloud. ADF BC REST request/response is going through Oracle RESTServlet, this is visible in the statistics:


There are no changes required to ADF application to be deployed to the Cloud. Simply make sure to provide correct datasource name, to be able to load data from Database Cloud. I have created jdbc/HrDS data source in Java Cloud, to point to Database Cloud. Using the same data source for AM configuration, this AM will be responsible to return data from ADF BC for REST requests:


Database Cloud offers public IP, it can be used to access DB from outside. If you want to reference DB schema from data source created in Java Cloud, instead of using public IP you should use DB instance name (example: RedSamuraiDB) and service name for pluggable DB created in Database Cloud (example: PDB1.ltredsamurai.oraclecloud.internal):


ADF applications deployed on Java Cloud will be fetching data from Database Cloud through data source.

Make sure to define WAR deployment profile for ADF application and specify context root:


ADF application should contain EAR deployment profile, which will reference WAR profile:


Uncheck "Auto Generate and Synchronize WebLogic JDBC Descriptors During Deployment" option in Application Properties (we don't need to deploy internal JDBC connection to Cloud):


Oracle Cloud offers services control dashboard. Here we can monitor active services, create new ones or stop existing ones. There is a list of options how to manage Java Cloud instance. Since my ADF BC REST application is enabled with ADF Security, I could go to WebLogic Server Console and create test user directly in DefaultAuthenticator:


Test user can be created exactly in the same way as on WebLogic running on-premise:


You can deploy ADF app on Oracle Cloud through EAR, using Enterprise Manager (don't forget to activate changes and start application). Application status can be reviewed from deployments list:


Try to access ADF BC REST service http://140.86.3.179/restapp/rest/1/Employees and enter redsam/welcome1 for login:


You should see JSON format data in response from ADF BC REST:


Download sample ADF BC REST application, the one I was using to deploy to Java Cloud - ADFBCRestApp_v9.zip.

Serving Oracle JET Application from WebLogic

Sun, 2016-07-24 03:43
Oracle JET application can be served from WebLogic as static content (HTML/JavaScript), JET code will be downloaded and executed on the client. Read more about packaging and deploying JET applications in developer guide - Packaging and Deploying Web Applications.

Here is demo JET application served on WebLogic server, port 7101. JET index.html page is referenced through application context root, registered on WebLogic during deployment of static content:


Required steps:

1. Generate JET application from basic template (use sudo on Mac OS):

yo oraclejet RSJETDemoApp --template=basic

2. Navigate to JET application folder and run grunt command to generate minified JET app structure under release folder:

grunt build:release


3. In order to serve JET as static content from WebLogic, we need to add WEB-INF folder and web.xml file. This will allow to deploy it as application to WebLogic. Create web.xml file with empty structure:


4. Final structure should look like this, web.xml and WEB-INF folder inside release:


5. Go to WebLogic Console and in deployment screen navigate to folder location, where release is located:


6. As for any other Web application deployment, choose Install this deployment as an application:


7. Provide application name and specify deployment accessible for the folder location:


8. Deployment should be completed without errors:


There is no other job for the server as to transfer HTML and JavaScript to the client. Code is running on the client.

Workaround for ADF BC REST Custom Method Configuration

Sun, 2016-07-17 13:34
This post is based on JDEV 12.2.1.1, it seems like there is issue with ADF BC REST custom method definition in this release. I'm glad it is not runtime issue, but related to design time JDEV wizard incorrect functionality. I will explain how to bypass it, when you want to expose custom REST method in 12.2.1.1.

Sample application (ADFBCRestApp_v8.zip) implements custom method, exposed through ADF BC REST - calculateEmployees. This method is created in VO Implementation class and it accepts two parameters - firstName and lastName. Method works correctly, I can execute it through POST, by passing predefined payload with method name and parameters (read more in developer guide - 22.12.5 Executing a Custom Action):


Make sure not to forget to specify Content-Type, otherwise POST request to ADF BC REST will fail:


Let's see custom method implementation and where workaround is required. Custom method is using View Criteria to filter VO and return estimated row count. All fine here:


Method should be exposed through VO client interface:


We should generate custo method binding registry in REST resource custom methods section (client interface). In JDEV 12.2.1 this works by clicking checkbox for Enable, but in JDEV 12.2.1.1 the same throws error (can't enable custom method to be called through REST):


Luckily there is a workaround. We can define method binding manually, go to source mode in REST resource definition dialog and add methodAction for custom method. You can replace method name, ID, instance name, etc. REST resource definition looks very similar to page definition file we are using to define bindings available for ADF Faces. ADF BC REST interface seems to be designed on common principles with ADF bindings, at least from definition point of view:

ADF BC REST Authentication with JSESSIONID Cookie

Tue, 2016-07-12 09:46
I have described how to apply ADF Security for ADF BC REST in my previous post - Oracle JET and ADF BC REST Basic Authentication. I will show how you can authenticate on first request and for the next requests rely on JSESSIONID cookie from the first request. This is useful for mobile clients and JET, there is no need to keep user credentials during requests (enough to keep cookie), as this is sensitive data.

Let's see how it works. In the first request we must authenticate. We are going to use basic authentication with GET operation and provide user credentials:


Request is authenticated and data is returned:


Along with data, extra information is returned with response - cookie and header. Cookie JSESSIONID value identifies authenticated session context. We can use this value for the next requests, this way server would assume us as trusted and would not ask to authenticate again (similar principle as in ADF web). Copy cookie value:


Now you can close and open Postman, to guarantee nothing is shared from previous request. Remove authentication header and add new header variable called Cookie. Value must be set as JSESSIONID=Cookie Value. Execute GET operation:


If session associated to this cookie is still active on the server, you will get response data, as it would be expected (no need to provide user credentials again):


ADF BC REST sample application - ADFBCRESTApp_v7.zip is protected by ADF Security with authentication and authorization:


REST servlet is mapped with appropriate security constraint in web.xml:

ADF 12.2.1.1 Improved Support for Programmatic View Object

Sat, 2016-07-09 13:15
ADF 12.2.1.1 brings improved support for programmatic VO creation. Such VO's are handy, when we want to base VO on alternative data source, such as PL/SQL ref cursor. In ADF 12.2.1.1 developer don't need to worry which framework methods to override, now it is enough to extend from Programmatic View Object Implementation class. This is special framework helper class, designed for programmatic VO support. See example below.

Sample application (ADF12211App.zip) is based on one regular VO, which renders employees table. Programmatic VO renders data for tag cloud component, located below table:


Steps to create programmatic VO are much more simple in ADF 12.2.1.1. Select data source option to be Programmatic in VO creation wizard:


JDEV will create VO with Java implementation classes, extended from ProgrammaticViewObjectImpl class and ProgrammaticViewRowImpl class. These classes will take care for special lifecycle required for programmatic VO behavior. See extends part:


Generated class contains getScrollableData extended method. This is the place to supply data collection for the VO. In my example, I'm creating ArrayList (VO rows) of HashMap's (one HashMap, represents row data of attribute/value pair). Attributes are populated with values and collection is returned back to the framework to manage it. Method is being called automatically by the framework. There are other methods available, to retrieve row by key, etc.:


New framework class allows to work with programmatic VO's easier and leverage framework features. I would expect it would provide better support for programmatic VO data filtering.

VO data is accessed on UI through regular binding expressions:


Initialized by ADF bindings layer:

Red Samurai Oracle JET Mobile Hybrid App Live on Android

Wed, 2016-06-22 10:38
We have implemented Oracle JET mobile hybrid app in less than 30 minutes and deployed it to Android device. This was done as a demo to the customer and could prove Oracle JET offers effective approach for hybrid mobile app development. Development process isn't much complicated with JET once you familiarize yourself with JavaScript development process and learn how to interact with REST services.

Red Samurai app based on JET (using out of the box JET template NavDrawer) is deployed on Android:


Out of the box JET allows to implement form validation, multi select and date entry controls:


Charts are rendered fast, animation is not lagging behind:


JET offers various grouping controls, to arrange content on the page:


Various types of charts can be rendered in responsive layout dashboard and are resized out of the box:


JET allows to build more complex screens, with large amount of UI components:


I'm happy with JET mobile hybrid offering. Stay tuned for more posts on this topic in the future.

Go Mobile with Oracle JET As Easy As 1 2 3

Mon, 2016-06-20 18:38
Oracle JET allows to build and run mobile hybrid applications. It is using Cordova to run on mobile device and provide access to device services. This is cool and what is great about it - it allows to get you started with mobile development in minutes. Besides all this - it is free.

I will describe steps I followed, to generate JET mobile hybrid app and run it in local browser (in the next posts I will describe how to run it on simulator and actual device).

First of all you must install Node.js and npm on your machine. This will allow to run shell environment to execute various commands related to JET app generation, setup, build and deployment. Read this article and you will learn how to do it - Installing Node.js and updating npm.

Next follow Step 1 and install Cordova in Step 5 from JET Get Started list.

You are ready to generate JET mobile hybrid app at this point. If you are on Mac OS, don't forget to use sudo, otherwise there will be permission related errors. Run Yeoman to generate the app:

yo oraclejet:hybrid JETMobileApp --template=navBar --platforms=ios

At this stage you can choose predefined JET template, here I'm generating it with navBar template for  iOS platform. It must complete with Done, without errors message:


Make sure to navigate to app folder with cd AppName:


Build generated app with grunt. Command I was using to build it for iOS (you can see from the log, it is producing *.app file, which can be deployed to mobile device as application):

grunt build:dev --platform=ios

It must complete with Done, without errors:


Run application to test in local web browser. See more options (deploy to simulator or device) here - Serve a Hybrid Mobile Application with Grunt. Use grunt command:

grunt serve --platform=ios --web=true --disableLiveReload=true

I'm running it with disableLiveReload=true for a reason. It seems like live reload initialization takes long time to start. Template based JET mobile hybrid app is started (in web browser, for testing):


Generated project can be opened in NetBeans, simply select project from the folder:


Under src folder you will find JET content. Try to change text in any of the generated pages:


Rebuild and serve application, you should see changes deployed for customers page in this case:

ADF BC Range Paging and ADF UI Table Pagination Use Case

Sat, 2016-06-18 09:45
ADF UI table pagination and ADF BC range paging sounds like a perfect combination. But to make it work perfect, a bit of extra effort is required. In the case of search/edit implementation, it can't remember updated record when navigating back to search screen (VO runs with Range Paging and UI table is displayed with pagination). I will explain how to solve it and show how to keep UI table displaying current page and prevent jumping to the first page.

Here is the working use case (download sample application - SearchEditApp.zip). Navigate to any page except first in UI table and select a record:


On edit, selected record should be opened in the fragment. Both buttons Save and Close/Close would return back to search screen, where current record and page should be preserved:


Close button will trigger Rollback operation, but current row should not be lost (see solution here: ADF Rollback Operation and Stay On Current Row):


Current row and page remains selected on return to search fragment:


Huge advantage of Range Paging mode for VO - faster navigation between UI table pages. This is especially important now, when we support pages. It is much easier for the user, to navigate to the last page (one click, without scrolling). We must ensure fast navigation in the table. This can be achieved with Range Paging - it will force VO to generate SQL query with ROWNUM and what is also very important - it will fetch only a subset of data (by default, ADF BC would fetch all rows until last, when navigating to the last page). Here we navigate to the last page:


Example of SQL query generated by VO enabled with Range Paging and subset of row data fetched for last page:


To force UI table to return display to correct page (navigation to search from edit), when Range Paging is enabled in VO - make sure to set first property for UI table (see solution here: ADF Rollback Operation and Stay On Current Row). We should keep track of current range start before navigating away from search screen and reset it back to the same value, when navigating from edit. I'm keeping this value in pageFlowScope variable managed through the bean method invoked on edit:


This is the method - it keeps track of current range start and updates pageFlowScope variable (later referenced from first property on UI table):


Bonus - see example how to refresh VO data (this is useful, when you want to display latest data to the user, before he starts editing it) and keep current row. When Range Paging is enabled, current row can be retained by re-setting current row key obtained from iterator binding (this executes SQL with find row by key and returns only current row):

Using the Oracle JET QuickStart Template

Tue, 2016-06-14 09:38
I will show in the post, how you can create single page applications with multiple modules in Oracle JET. As a starting point, you should use the Oracle JET QuickStart template, read about it here. This template comes with sample structure and you could follow it to split application functionality into different groups.

Download sample application, which is based on Oracle JET QuickStart template - JETCRUDApp_v10.zip (you must run ADF BC REST application in JDEV 12.2.1 and JET in NetBeans 8). QuickStart application is extended with new module, it contains CRUD implementation in JET (read more here).

I have slightly modified template and removed boxes for navigation and complimentary areas. It renders main content block stretched on the screen:


Under Employees tab, CRUD functionality to manage employees data is rendered. This includes CRUD functionality described in my previous posts about JET (see link above). Now it is part of real JET application:


Let's take a look into structure. QuickStart template comes with structure, where each module is separated into HTML/JavaScript files. There is a group available for employees CRUD - employees.html and employees.js:


Main page logic is implemented in index.html. This file includes page structure and references block with dynamic module (loaded through menu structure):


List of available modules is registered in main.js file router:


JET CRUD functionality use case HTML part is copied into employees.html file (this will be loaded through main.js router):


JavaScript part is copied into employees.js file:


JavaScript logic is changed to handle table row selection event through JavaScript listener method. Constructed employees view model is returned to be accessible from the router:

How To Control Row Removal in ADF BC

Sat, 2016-06-11 11:28
There is a flaw in ADF BC remove operation. Row could be successfully removed in ADF BC - it dissapears from UI as well, but if there is DB integrity constraint violation - row is not removed in DB and error message is displayed to the user. This could be misleading to the user, he sees message about failed removal, but at the same time row is not present anymore.

Easier to explain with example. Let's imagine we want to remove IT_PROG job (there are employees assigned with this job and row removal would fail in DB):


On delete, row is removed from ADF BC and UI, but operation fails in DB and error is returned:


ADF BC completes row removal before row is really removed in DB. This is why ADF BC doesn't really know about failed row removal and is not able to keep it.

Technically such behavior is valid, but hardly understandable for business user. If row is not removed it should stay in the application.

We could solve it by overriding doDML method and executing row removal through custom method defined in VO implementation class. In doDML we can catch DML constraint exception during delete and execute refresh for removed row. Removed row is accessible in doDML, it is not dead yet. Calling refresh would allow to fix row state. We should throw exception and catch it in VO implementation class method, to refresh rowset and set back current row:


Custom method to execute remove in VO implementation class. Current row key is saved before remove and restored in case of exception. We must call executeQuery to refresh rowset, before setting back current row. In this example, commit is called right after row is removed. This allows to produce DB constraint error and process it in the context of VO. You may implement similar logic from global commit method, in such case you would need to include information about VO to be refreshed into exception message (raised in doDML):


Try to remove the same IT_PROG row now:


Failed row removal message is displayed and row remains in the application:


Download sample application - ADFDeleteControlApp.zip.

UKOUG Slides - Forms, ADF and JET a Non-Aggression Pact

Thu, 2016-06-09 13:43
Florin Marcus was presenting topic on Forms modernization during UKOUG Development SIG seminar in London. Session was based on our production experience from recent Forms modernization project to ADF 12c and Alta UI.

Highlights:

- Who integrates Forms and ADF?

- Java Plugin to be Discontinued. Consequences for Oracle Forms.

- Why Yet Another Web Framework? Oracle JET.

- Forms and ADF and JET - Business Integration Patterns

- Forms Developer's perspective: life after learning ADF

Go through the slides and learn more about it:

Oracle JET Executing Dynamic ADF BC REST URL

Tue, 2016-06-07 10:56
I'm going to explain how to call ADF BC REST service from JET API and how to control parameters passed through to REST URL. Most of the time, REST should return data based on different parameter values, URL is not static. I will be exploring two cases - search functionality, where parameter value is entered by the user and LOV functionality, where current employee key is submitted to fetch colleagues list.

You can go through the slides from my AMIS25 session - Oracle JET CRUD and ADF BC REST. I explain similar concepts:


Download sample application (you must run ADF BC REST application in JDEV 12.2.1 and JET in NetBeans 8) - JETCRUDApp_v9.zip.

1. Filter implementation

We should take a look first, how filter/search functionality is implemented. User enters keyword for Last Name and filters data in JET table:


User can reset search results, change filter criteria. Filtering is done using startswith operator, by ADF BC VO (it creates temporary bind variable from REST URL parameter q=LastName LIKE value):


Filter block is implemented in a separate HTML div. Filter value is mapped with observable variable registered in JET View Model:


Table collection is based on collection with dynamic REST URL. URL is calculated through customURL property (referencing JavaScript method) in the collection. On filter event, we clear up all dependent data and call JET collection API method - refresh(). This ensures reload for collection and REST URL re-calculation. Similar is done on reset:


Method getURL is responsible to read filter value and construct REST URL accordingly (this will be used to re-fetch collection content):


Here you can see generated REST request URL logged by NetBeans Network Monitor. This URL contains filter information supplied through dynamic REST URL defined for the collection:


2. LOV data fetch implementation

There is LOV in ADF BC, which returns current employee colleagues (employees from the same job, except employee himself). ADF BC REST encapsulates parameters complexity and allows to simplify REST request. JET UI renders LOV data in a chart:


Each time when employee record is selected, we execute dynamic REST call (with new employee ID) to fetch colleagues collection:


This is chart definition in JET UI, it references observable variables for series/groups from JET View Model:


Similar as in the case with Filter, we supply dynamic URL for the collection, using property customURL:


Differently than in the Filter implementation, here we dont refresh collection. We execute JET API method fetch(...), to retrieve new collection and we push contents into observable variables, referenced by chart component in the UI:

Oracle JET Handling ADF BC 12.2.1 REST Validation Event

Sat, 2016-05-28 11:32
I already had a post about how to handle ADF BC validation messages in Oracle JET - Handling ADF BC 12.2.1 REST Validation in Oracle JET. There is an improvement I would like to share. JET submits data to ADF BC REST and there happens validation. In JET perspective data is correct, however it may fail validation in ADF BC and we need to reset values back to original in JET. Previously I was re-executing entire JET collection, drawback of this approach - current selected row was lost and control was returned to the first page in the table configured with pagination.

With improved solution, current row remains selected one, even if ADF BC returns failure for validation event. As you can see in the example below:


Callback method for JET model save API is set to parse ADF BC validation messages and at the end to refresh current row model. Current row is refreshed by re-fetching row data, only one row data will be re-fetched from REST. Previously entire collection was refreshed, causing current row reset:


Download sample application - JETCRUDApp_v9.zip (you must run ADF BC REST application in JDEV 12.2.1 and JET in NetBeans 8).

Pages