Wednesday, August 16, 2017

Oracle Java Cloud Service - Scaling and Cluster Setup for ADF

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:

Saturday, August 12, 2017

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

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.

Saturday, July 29, 2017

Oracle JET Busy Context API to Control Asynchronous REST Calls

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:

Saturday, July 22, 2017

ADF Goes Client Side - UI Performance Boost with JavaScript

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.

Sunday, July 16, 2017

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

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.

Monday, July 10, 2017

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

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.

Thursday, July 6, 2017

Working with Location and Permissions in JET Hybrid

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.