Monday, January 29, 2018

Avoid Blind SQL Call from ADF Task Flow Method

Keep an eye open on ADF Task Flow Method Call activities where methods from ADF Bindings are called. JDEV 12c sets deferred refresh for ADF binding iterators related to TF Method Call activities and this causing blind SQL to be executed. Blind SQL - query without bind variables.

Let me explain the use case, so that it will be more clear what I'm talking about.

Common example - TF initialization method call where data is prepared. Typically this involves VO execution with bind variables:


Such method call could invoke binding operation either directly (pay attention - bind variable value is set):


Or through Java bean method using API:


My example renders basic UI form in the fragment, after TF method call was invoked:


If you log SQL queries executed during form rendering, you will see two queries instead of expected one. First query is executed without bind variables, while second gets correct bind variable assigned:


What is the cause for first query without bind variables? It turns out - iterator (with setting Refresh = deferred) from page definition mapped with TF method call is causing this. Somehow iterator is initialized not at the right time, when bind variable is not assigned yet and this causing blind SQL call:


Workaround is to set Refresh = never:


With Refresh = never, only one query is executed as expected, with bind variable assigned:


This may look minor, but trust me - with complex queries such fix could be a great help for performance tuning. Avoid executing SQL queries without bind variables.

Download sample application - ADFTFCallBindingApp.zip.

Sunday, January 28, 2018

Oracle Offline Persistence Toolkit - Simple GET Response Example with JET

We have new tool from Oracle which can help to simplify offline logic implementation for JS apps.  In this post I will describe how to use Oracle Offline Persistence Toolkit with Oracle JET. However Offline Persistence is not constrained by JET usage only, this toolkit is available on NPM and can be integrated with other JS solutions.

I should emphasise - offline toolkit primary role is to enable mobile hybrid apps to work offline. In my opinion, toolkit usage doesn't stop here. It can enable user to continue his work, when internet connection is available, but back-end server goes down. Technically user would remain online in this case, but in practice application will be broken - no response from back-end for REST calls. Offline persistence toolkit could help to solve such cases - user could continue working with local cache, until back-end is down.

If you want to learn how offline toolkit works and how to use its API, go to GitHub page - check readme, add it to your JET app and try to run/test. Hands-on is the best way to learn something new.

I will share few hints and sample app.

As per readme, first of all you should add Offline Persistence Toolkit and PouchDB modules from NPM. Run these commands within JET app directory:

1. npm install @oracle/offline-persistence-toolkit

2. npm install pouchdb pouchdb-find

Next you should follow four simple configuration steps and enable JET app to be able to access offline toolkit API.

Step 1 (standard, when adding any additional module)

Add paths to newly added modules in main.js require block:


Step 2 (standard, when adding any additional module)

Add paths to newly added modules in main-release-paths.js:


Step 3 (standard, when adding any additional module)

Added modules would not be copied to build directory automatically. We need to define copying in oraclejet-build.js. Modules should go to build directory. If you need to copy files from given folder and subfolders, use ** for src:


Build content is located in web directory. Offline toolkit and PouchDB modules should be copied to build directory:


Step 4

Initialize window.PouchDB variable in main.js:


Configuration is complete, now we can use Offline Persistence Toolkit API. Add persistence store manager and other modules:


Simplest option is to rely on default fetch listener from offline toolkit. We need to register store factory and map endpoint which we want to cache with persistence manager. When back-end is available - call will go to back-end and response will be cached. Next time, of back-end is not available - data will be fetched from cache. Toolkit intercepts HTTP(-S) request and stores response, if end-point was configured to be listened:


I'm testing offline toolkit with simple Employees REST end-point call from JET. Toolkit allows to execute this call successfully, even if there is no back-end or no connection (of course - if same call was executed at least once before):


UI part is simple - displaying list, when data is fetched:


Data is fetched, we are online:


Offline toolkit will work, if REST response doesn't include Cache-Control header. Make sure there is no Cache-Control header set in response:


ADF BC REST by default sets Cache-Control header, you can remove it in Filter class (defined in ADF BC REST app):


Now I turned my connection to be offline, clicked on Get List button - JS calls REST and instead of getting network error, it executes successfully and returns data from cache through offline toolkit functionality:


You should open details for network call and check initiator. You will see that all calls mapped to offline endpoint are going through persistenceManager.js:


Let's double check - may be we are tricked somehow? Remove offline toolkit registration API in the code and re-run application:


As expected - network error is received and fetch fails. This proves - offline toolkit works :)


Sample JET application with offline toolkit configuration is available on GitHub (run ojet restore and ojet serve).

Tuesday, January 16, 2018

Linear Regression - Machine Learning with TensorFlow and Oracle JET UI Explained

Machine learning topic is definitely popular these days. Some get wrong assumptions about it - they think machine could learn by itself and its kind of magic. The truth is - there is no magic, but math behind it. Machine will learn the way math model is defined for learning process. In my opinion, the best solution is a combination of machine learning math and algorithms.  Here I could relate to chatbots keeping conversational context - language processing can be done by machine learning with neural network, while intent and context processing can be executed by programmable algorithms.

If you are starting to learn machine learning - there are two essential concepts to start with:

1. Regression
2. Classification

This post is focused around regression, in the next posts I will talk about classification.

Regression is a method which calculates the best fit for a curve to summarize data. Its up to you which type of curve to choose, you should assume which type will be most suitable (this can be achieved with trial and error too) based on given data set. Regression goal is to understand data points by discovering the curve that might have generated them.

In this example I will be using simplest regression possible - linear. Line is described by equation y = W*x + b. Where b is optional and can be 0 (line will cross (0, 0) point). For complex data sets, we might use polynomial equations and generate curves.

Here is Python code which implements linear regression with TensorFlow API (I have provided comments for all steps, reading code should be self explanatory):


Key element in any kind of machine learning - cost. The higher the cost, the worse is learning output. In linear regression, cost is typically defined by the sum of errors. The error in predicting x is calculated by the squared difference between the actual value f(x) and the predicted value M(w, x). The cost is the sum of squared differences between the actual and predicted values.

As you can see in the code above, we define cost function and ask TensorFlow to run optimizer to find the optimal values for model parameters. All the hard math calculation is happening in TensorFlow, our job is to prepare training data and choose right learning approach with correct equation.

Let's run JET UI, which talks to TensorFlow through REST. Training data is randomly generated (always 100 points) during each training session.

Training Epochs - number of learning iterations during training session
Learning rate - learning speed, smaller rate - more careful learning
W - learned model parameter to calculate equation y = W*x
Cost - value which shows how successful learning was, lower cost is better

1. We start from 1 training epoch and learning rate 0.001:


Learning result is not good - red line is result of linear regression, it doesn't represent best fit for training data. Cost is pretty high too, which indicates that learning wasn't successful.

2. 10 training epochs and learning rate 0.001:


As we repeat multiple learning iterations within the same training session - learning result is better. Cost becomes smaller and linear regression calculated line fits better, but still not ideal.

3. 100 training epochs and learning rate 0.001:


It helps to increase learning iterations, cost is significantly improving and line fits much better. This means outcome for W parameter learning is pretty good.

4. 1000 training epochs and learning rate 0.001



Let's make model to learn even harder and repeat more times - cost is becoming even better.

5. 2000 training epochs and learning rate 0.001


We could increase learning iterations further, but at some point it will not help. Learning process will start to suffer from overfitting. You can think about it - learning and repeating so many times, that at the end you start forgetting things. Cost is getting worse when repeating learning iterations further.

6. 2000 training epochs and learning rate 0.0001


It should help to make learning rate smaller, which result in more careful learning. This should allow to get better learning results with higher number of learning iterations. We get best learning cost result here and the most optimal line. You may ask - what is the use of that line? It can help to predict y values which were not available in training dataset.

7. 2000 training epochs and learning rate 0.01


On contrary if we increase learning rate, learning process will be faster - optimizer will run faster. This will result in decreased model output quality, cost will be higher and W parameter value will not produce such best fit line as in previous training run.

Few hints related to Oracle JET UI. You can achieve very good data visualization with JET chart components. For example I could control marker type rendered for training data points:


Line which represent learning result, can be displayed as reference line:


To display reference line, I'm using y-axis property which comes with JET chart:


References:

- Example for Linear Regression with Python and TensorFlow - Gist
- JET UI example - GitHub
- Accessing TensorFlow model through REST - Machine Learning with Oracle JET and TensorFlow
- Book - Machine Learning with TensorFlow 

Wednesday, December 27, 2017

JET UI Shell with Dynamic Tabs Implementation

I will describe and provide sample code - how to implement dynamic tabs in Oracle JET. This is useful for module loading, default JET template comes with static tabs - this works OK for the apps with smaller number of modules. When menu structure is more complex, it makes sense to load tabs for each module dynamically, when module is selected from the menu. This allows user to focus on modules he is working on, well just same as tabs in your Web browser.


Dynamic tabs are only visual placeholders, I'm using JET router to load module and keeping tab selection in synch. There are multiple benefits for such approach - module loading is following standard JET implementation with router, visually it looks like we have modules loaded using tabs. Overall implementation for dynamic UI Shell tabs with JET becomes quite simple, when relying on JET router.

In this post I will describe how to:

1. Add new tab and select module
2. Select existing tab from the menu/by clicking on the tab itself and select module
3. Remove tab and select next available module

Dashboard module is default one, it is loaded once application is accessed and we dont allow to remove it. Other modules are accessible from menu list:


Multiple menu items are opened with tabs displayed below. Let's see how tab removal works. If I remove Incidents tab:


Next tab on right will be selected as current:


If tab is removed, which is not selected -  Customers, current tab will remain selected:


If there is no tab on the right, while removing current tab About, first tab on the left will be selected:


Implementation part - menu list is implemented in this example with JET menu component (in real application you would use more complex menu structure, may be hierarchical):


Dynamic tabs solution is based on JET tab bar component, with removable option (you can try it in JET Cookbook - Add/Remove tab example):


Application defines array of tabs and variable to to keep track of current module:


Once menu item is loaded, we check first if same was opened already. If yes - we open it, instead of opening the same tab twice. Tab array is updated with new item and JET router navigates to current module, this is how module gets displayed, no additional magic:


When user selects tab, current module is loaded through JET router:


Tab removal is handled in delete method. Here calculation is done, which tab should be focused after current tab removal. Item is removed from array of tabs and JET router state is updated:


Sample JET code is available on my GitHub repository.

Thursday, December 21, 2017

Recipe for JQuery Menu integration into ADF Faces

May be you are thinking to add some fresh looking element into your ADF app? I would propose JQuery menu. Advantage of such menu - it is purely client side implementation and it allows user to navigate through items really fast. Besides fast navigation, it looks great too and can be easily customized.

In this post I will describe how to achieve JQuery menu integration into ADF Faces and provide sample ADF application. I'm using JQuery menu from here - Animated Responsive Drop Down Menu. There is no need to implement JQuery menu component, we can use one of the existing implementations.

I have recorded short example, you can see how convenient is client side menu navigation. Each menu item loads ADF region:


JQuery menu integrated into my ADF sample:


It can display menu items for multiple levels:


Integration into ADF Faces is very simple, you need to copy JS and CSS files into ADF application:


Define JS and CSS resources in ADF main page, make sure to reference JQuery too:


Menu structure is defined in ADF fragment using HTML tags. Once menu item is selected, call to ADF is made through combination of client/server listeners (check WBClient.menuNavigation method). In my future posts I will describe how to construct similar menu structure dynamically. If your application is secured, make sure to define ADF Security permissions to TF's properly, any unprotected TF can be loaded from the menu:


Client listener method menuNavigation constructs params with target TF address and calls server listener, which in turn displays ADF dynamic region:


Menu fragment with HTML tags is integrated into ADF page template:


Download sample application - ADFJQueryMenuApp.zip.