Showing posts with label NetBeans. Show all posts
Showing posts with label NetBeans. Show all posts

Thursday, September 7, 2017

Oracle JET Simple Table with Fake JSON Server

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

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

npm install -g json-server


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


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

json-server --watch db.json


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


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


JET UI table component renders data directly from CollectionTableDataSource:


Table UI is rendered based on REST call:


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


Response is visible too:


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

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 1, 2017

Oracle JET Router State Control

In my use case there is requirement to navigate to JET module, without displaying it in menu structure. Navigation is a simple task, more complex is to make sure current menu item will be unselected after navigation to invisible module (so that later we are able to re-open it).

There is accounts module in JET sample app (download it from GitHub - JETModularArchitecture):


Accounts module is included into router, but not included into array of visible menu items:


On button click (dashboard module) we call function, where router navigation happens to accounts module:


Let's see how this functionality works. I click on Accounts button to call a function and force router navigation:


Accounts module will be opened (through router navigation), but currently highlighted menu item will stay as it was (Dashboard). This makes it impossible to navigate back to Dashboard (unless we navigate to another module and then navigate to Dashboard):


Solution for this problem is to change selection property of ojNavigationList component in HTML:


Instead of pointing to router stateId directly, we should point to computed function. This will help to control currently selected menu item. But we still need to update router state, when menu item is selected. For that reason I'm using beforeSelect property, which points to function, where router state is changed:


Selection property value is calculated by function, which returns NULL, if accounts is currently selected module. This allows to remove focus from Dashboard menu item, after navigation to accounts. Once focus is removed, we can click back on Dashboard and navigate. For all other modules - current router state ID is returned. Select handler call router API to navigate to the module:


Navigation to accounts module from dashboard. Dashboard menu item doesn't remain focused anymore:


Navigation back to dashboard work too:

Sunday, April 2, 2017

Slides from Oracle PaaS Forum 2017 - Oracle JET and ADF BC REST Production Experience with Oracle Java Cloud

My colleague Florin Marcus (twitter: @FlorinMarcus) was attending and presenting at Oracle PaaS 2017 forum in Split, Crotia last week. He was explaining our production experience with Oracle Java Cloud Service and running Oracle JET/ADF BC REST system on Cloud instance.

Slides are uploaded on slide share, you can go through and read about real production app built with JET and ADF BC REST running on Oracle Java Cloud. If you are interested in more details - let me know, I could show a demo:



Exciting news from Oracle PaaS Forum 2017 - Red Samurai won award for Outstanding Java Cloud Service Contribution 2017:


This award was received for implementing Oracle JET/ADF BC REST app and running it on Oracle Java Cloud in production. Read more about it - Red Samurai and Oracle PaaS JCS Success - JET/ADF BC REST Cloud Production Application.

Monday, March 20, 2017

Red Samurai and Oracle PaaS JCS Success - JET/ADF BC REST Cloud Production Application

I would like to share our success in Oracle PaaS service - Java Cloud (JCS). We have managed to implement JET/ADF BC REST system in short period of time and deploy it in production running on Oracle JCS. UI is implemented entirely with JET, while back-end REST services are running on top of ADF BC. Secure access is controlled by unique ID managed by server side ADF Security.

Production application implements custom invoice processing logic for startup candy factory/distributor in Lithuania. Oracle Cloud doesn't require administration and provides all mandatory services to run custom application. This is primary reason why decision was made to use Oracle Cloud. In the next phase we are going to implement warehouse management logic, tightly integrated with invoice processing.

JET UI

Home screen displays dashboard with financial data for orders, customers and invoice items:


Menu structure (JET Router) is focused around implemented business logic:

1. Dashboard - statistical data display
2. New Invoice - invoice creation module
3. Template Setup - invoice template setup, to speed up invoice creation
4. Invoice Search - search through all invoices
5. Customer Setup - customer data management
6. Supplier Setup - supplier data management

Invoice Search screen implements form block and results table with pagination. This screen is using a set of JET components, starting from input list to responsive UI:


User have option to select invoice for editing. Various invoice fields can be changed in this screen. UI remains responsive and can be rendered on mobile device or JET Hybrid application - this was one of the key requirements:


Invoice items are edited in JET dialog. This is very convenient approach, JET dialog works really fast and allows to switch from one item to another in a quick way:


Development process - Oracle Developer Cloud Service

Application was developed using Oracle Developer Cloud Service. We think Agile boards/sprints defined in DevCS are really helpful. Offered functionality simplifies task management/monitoring process and you can see the progress in the sprint:


DevCS provides Git source control repository, agile board and issue tracking. It also gives you Build Automation. We were using Build Automation to re-build changes committed in ADF BC REST repository:


After build process completes - there is a an option to redeploy latest EAR package directly to JCS. This helps to save time, no need to repeat redeployment routine steps yourself each time when new build completes:


Application Structure

Application is divided into two parts (two separate deployments): ADF BC REST and JET UI implementation.

ADF BC REST implements back-end REST services and provides authentication/authorisation control. We are using regular ADF BC development, together with REST interface provided out of the box starting from ADF 12.2.1:


JET UI application is following modular architecture approach. Each use case is implemented in separate module. Common logic (REST service definition, etc.) is moved out into controller modules. Client side business logic is implemented in JET module JavaScript functions and rendered with JET UI components:


Oracle Cloud Deployment

We are using Oracle Java Cloud Service instance to run both ADF BC REST app and JET. ADF can't be deployed to Oracle Application Container Cloud service, but you can host JET from Java Cloud. For this reason it was more sense for us to use only Java Cloud and run both server side and host client side from the same instance.

Both demo and prod environments run from the same Cloud instance, targeted to different Managed Servers (to simplify maintenance):


If we take a look into application runtime statistics, ADF BC REST application mainly executes ADF REST servlet (to produce REST request response), our custom PDF servlet and ADF authentication servlet to execute session logout:


JET wrapper application doesn't run any server side logic, it simply return JET application content to the client - only File Servlet is invoked in operation:


Performance

JET runs on client side, there are much less server side calls comparing to ADF Faces application. In this example we change invoice status to Submitted. In result several REST calls are executed, each running below 100 ms. and transferring just a bit of info. Key difference between JET and ADF Faces - REST call doesnt block client functionality. REST call may execute asynchronously and user can continue to work with the application:


In the example below, we navigate to invoice list screen. Invoice MAR-36 status was changed to submitted, invoice line data is re-fetched to display up-to date information in the table for particular row. Invoice row data is re-fetched below 100 ms.:


Let's check navigation in the table. We navigate to the last page. REST request is completed in around 100 ms., and it returns only a set of rows for the last page:


When user log's our from JET application, we execute request for adfAuthentication servlet with parameter logout=true. This allows to close ADF BC REST session on the server side:


Summary

1. JET UI and ADF BC REST server side can be used in production system

2. JET UI and ADF BC REST runs great on Oracle Java Cloud

3. Oracle Developer Cloud Service is useful for JET and ADF development

Wednesday, January 18, 2017

Multi Language Support in Oracle JET

There is great post from Geertjan Wielenga about Translating Oracle JET Applications. If you want to introduce multi language support into JET app - this is great place to start reading from. We are building production Oracle Cloud app with ADF BC REST and JET. This app requires multi language support - English and Lithuanian. I will describe below how we integrated multi language into various areas in the app.

Download or browse through sample application in GitHub repo - JETPlaygroundApp.

In JET we could set default language in index page html root tag. By default it is set to en-US, but it can be set to lt-LT for Lithuanian language or any other language:


Translation texts are located in message bundles. There is one default message bundle for English and translations are located in sub folders. English bundle:


Lithuanian bundle with translations for the same message keys:


Multi language bundle support must be registered in main.js (bundle file name can be anything):


Values for all labels/texts must be defined as observables and initialised from JET translation API by passing message key - this will bring default text:


When language is changed, we need to update observable values and reset language value in HTML tag. I'm changing menu labels as well by re-configuring JET router:


On UI in index.html message key is referenced directly from observable variable:


We can access message key defined in appController from individual JET module UI through $parent. For example, I'm using dueDate message key in incidents module:


Same message key is reused in another module - customers:


This is how language switch looks on UI - language change is available in preferences:


When we switch to Lithuanian language - texts are changed (the ones assigned with translatable messages):


Menu labels are also changes, JET Router is reset:


Labels are change in built-in JET components - such as date. Though is not translated completely for Lithuanian language (Today text remains in English):