Saturday, December 17, 2016

JET Application - Generate with Yeoman - Debug in NetBeans

Let's take a look today how to debug JET application (tested with JET 2.2.0) which is initially generated with Yeoman. We could debug in NetBeans, but by default application generated with Yeoman is not runnable in NetBeans, we need to add manually some config files - I will describe how. Also note - JET application created with NetBeans can't be directly served with grunt from command line, it also would require manual changes in the config. It would be nice if Oracle would make JET applications generated with Yeoman automatically runnable in NetBeans and vice versa.

I would recommend to read Geertjan post on similar topic - Avoiding Hiccups in Building Oracle JET Applications. My point is different though - I describe how to run application generated with Yeoman in NetBeans without using grunt command, to be able to use NetBeans debugger for sources in src folder.

I will go step by step through the process (first I would recommend to go through JET Getting Started):

1. JET application creation with Yeoman and build with Grunt
2. Manual configuration to be able to open such application in NetBeans
3. JET CSS config to be able to run such application in NetBeans

1. JET application creation with Yeoman and build with Grunt

Run command: yo oraclejet basicjetapp --template=basic. This creates simple JET application with one module:


Scripts and various modules are being generated. JET content can be located under src folder - generated application structure:


This is the most simple JET application possible, based on basic template. I have added chart into main page (I'm using Atom text editor to edit JavaScript):


Supporting variables for the chart are created in Application Controller module:


Application Controller module is included into JET main module, where bindings are applied based on Application Controller module and JET context is initialized:


You can build minified JET structure ready for deployment with Grunt command build:release. Navigate to application root folder and run it from there: grunt build:release:


This will produce web folder (name can be changed) with JET minified content:


We could run JET application with Grunt using server:release command: grunt serve:release:


JET application is running:


2. Manual configuration to be able to open such application in NetBeans

---UPDATE 2016-12-27---

You can open JET application generated with Yeoman in NetBeans and after Run - it will display Project Properties window:


Change Start File to point to src folder:


Now you should be able to run JET application in NetBeans, make sure to fix CSS, refer to point 3.

By default NetBeans assigns oraclejet-app name, you can change it:


Same steps can be done manually by editing nbproject folder files, described below.

---END UPDATE---

To debug JET application generated with Yeoman we would need to open it in NetBeans. Unfortunately this is not available by default. NetBeans doesn't recognize JET project and shows disabled icon:


We need to copy manually NetBeans nbproject folder from any other JET application created with NetBeans into our application root folder:


Change project.xml file and update project name property:


Update web context root in project.properties file:


Update application paths in private.xml file:


After these changes, NetBeans can recognize JET application and it can be opened:


JET application generated with Yeoman is successfully opened in NetBeans:


But there is issue when trying to run application in NetBeans - it can't find JET Alta UI CSS. JET is running, but with ugly look:


3. JET CSS config to be able to run such application in NetBeans

JET application generated with Yeoman points to CSS location which doesnt exist in folder structure:


After we run Grunt command grunt build:release it automatically updates CSS location. This is why it works with grunt serve:release:


Things are a bit different for JET application created with NetBeans. JET application created with NetBeans indeed contains JET Alta UI CSS in the folder originally referenced by JET application created with Yeoman:


I copied this folder into JET application generated with Yeoman:


This time JET application runs and displays as it should in NetBeans:


Don't forget to remove duplicate (we need it only to run/debug in NetBeans) JET Alta UI CSS files folder from release if you run grunt serve:release:


Download sample JET application from GitHub directory - basicjetapp.

Saturday, December 10, 2016

Early ADF Model Update with Process Updates Method

This use case specifically useful for ADF UI value change listener. If there is business logic to be invoked when field value is changed, we can can call ADF BC custom method from assigned value change listener. However new value is not yet propagated down to ADF BC model - we would need to pass it as parameter to custom method. What if want to have new value to be available in ADF BC model without passing new value from value change listener as parameter? This is possible if we call processUpdates method in value change listener, before calling custom ADF BC method.

In my example - ADFProcessUpdatesApp.zip, I have created sample method testCall in VO Row implementation class. This method is accessing salary attribute value from current row. I'm going to call this method through bindings from value change listener and lets see what it will print out:


Let's use value change listener with custom method call without calling processUpdates initially:


Change salary attribute value to call value change listener:


Custom ADF BC method is invoked from value change listener and it prints value before change:


How to get new value in ADF BC custom method, without passing it as parameter from value change listener? Call processUpdates on UI component, before calling custom method in value change listener:


Change value once again:


This time new value is visible in ADF BC custom method instantly, when value change listener is invoked:

Thursday, December 8, 2016

Video - Live Webinar - Master Class - ADF Bindings Explained

Posting 2 hours long video recording for yesterday webinar - Master Class - ADF Bindings Explained. Thanks to everyone for attending. It was large crowd, nearly 100 attendees live. I enjoyed answering to all of your questions, hopefully this will be useful in your daily work.


Webinar topics:

1. ADF Bindings overview. Why ADF Bindings are required and how they are useful
2. Drill down into ADF Bindings. Explanation how binding object is executed from UI fragment down to Page Definition
3. ADF Binding types explanation. Information about different bindings generated, when using JDeveloper wizards. What happens with ADF Bindings, when using LOV, table, ADF Query, Task Flow wizards.
4. Declarative ADF binding access with expressions
5. Programmatic ADF binding access from managed beans
6. ADF binding sharing and access from ADF Task Flows. How to create binding layer for Task Flow method call or router activities.
7. Best practices for ADF Bindings
8. Your questions

Download webinar ADF 12c app from GitHub - ADFAltaApp

Monday, December 5, 2016

Simple CRUD Implementation with Oracle JET - Part III

This is third and last part in JET CRUD series. I already had a post about JET CRUD few months ago - Very Practical CRUD with JET and ADF BC - POST and DELETE Methods. But current approach is more simple and better structured. I will go through CREATE, UPDATE and DELETE operations.

You can download or view source code (JET app and ADF BC REST app) directly in GitHub  repository - jetcrud.

CREATE

We need to initalize new model when creating new row, this is done in addCustomer.js - empty model is initialized. Model is initialized from common module definition - customController (read more about it in my previous post - Better Oracle JET Code Structuring with Your Own Modules - Part II):


Important trick which will save lines of code - you can reference model attributes directly, no need to list all of them in advance. Data bind form component to JET model variable:


Each input could point to the attribute, this is UI will get/set value to View Model:


New model must be posted through JET model API create operation. Here we can convert model to JSON and use it as parameter for create:


This is how it looks on UI - form with new customer data. Press Save button:


Behind the scenes REST POST method will be executed and data will be posted to the backend, where it will be processed and inserted into DB:


New row is saved and visible in the results table:


UPDATE

Edit form implementation is very similar to create, actually it can be even combined into one. The only difference is how you initialize current row for editing (check - Oracle JET CRUD - Search and Edit Form - Part I). And how you save the changes - must use different method from Oracle JET model API - save. The rest is very similar to create operation handling:


Edit form UI - it renders different set of fields:


Behind the scenes it executes REST PATCH method, which will update only changed attributes:


DELETE

This is the simplest operation from all three. You should get instance of row to delete. This can be done through JavaScript promise, JET would not return actual model instantly. It return promise and you get model asynchronously. Call JET model API destroy operation to remove row entry:


Row is selected and removed:


Behind the scenes it calls REST DELETE method and removes row from backend:


Read previous posts:

1. Oracle JET CRUD - Search and Edit Form - Part I
2. Better Oracle JET Code Structuring with Your Own Modules - Part II

Sunday, December 4, 2016

Oracle Developer Cloud Service and ADF Build/Deployment Automation Summary

We are moving our internal development to Oracle Cloud production instance. This weekend I was going through build automation and deployment process with Oracle Developer Cloud Service. I would like to share few hints with you.

There are excellent video tutorials recorded by Shay Schmeltzer, I would not repeat here all the steps, will post only key steps in the process and few extra tips. Watch Shay's videos to get understanding how it works and how to configure Developer Cloud Service (UI was changed since then, but still all config steps are valid):

1. Using Oracle Developer Cloud Service for Git and code review with JDeveloper Applications

2. Oracle ADF Build Automation on the Oracle Developer Cloud Service

Download ADF 12.2.1.1/12.2.1.2 example configured with Ant scripts for build automation on Dev CS - ADFAltaApp.

JDeveloper/ADF version. When I run OJDeploy build in Dev CS (Developer Cloud Service), I can see in the log it prints version 12.2.1.1. This means currently Dev CS supports ADF up to 12.2.1.1:


Locally I prefer working on 12.2.1.2, since JDeveloper is more stable in 12.2.1.2. When I was trying to build code commited from 12.2.12, Dev CS complained it can't open project file. I have solved it by changing 12.2.1.2 to 12.2.1.1 in *.jws and *.jpr files (luckily my local JDeveloper 12.2.1.2 doesn't complain about it and continues to work with the application). With such changes, Dev CS is able to recognize project files and runs build process. Change in the project file:


Development process is centralized around pushing your local changes to Dev CS Git repository branch (this can be done directly from JDeveloper):


In this example, I commit my local changes into fixbugs branch, later changes can be merged into master branch through Dev CS UI:


Build. To merge changes in Dev CS into master branch, we need to register merge request. In the wizard you can specify Git repository name, target branch and review branch (the one from where we are going to get changes and apply to master branch):


You can specify approvers and later when changes are approved, they are merged to master branch.

Next step is build automation (this can invoked on demand or automatically). You can associate build process to Git branch and review past build results:


If you are building with Ant, make sure to add build.properties and build.xml files into ADF application (described in Shay's video). Here is example of build.properties file I'm using in the sample app for ADF 12.2.1.1/12.2.1.2:

Example of build.xml file to run build automation in Dev CS for ADF 12.2.1.1/12.2.1.2:

At first build process was always returning success, even I there were compilation issues left in the code on purpose. In order to force build process to return failure when it should, you need to check "Archive the artifacts" option in Post Build section of build job configuration. This will force build process to produce EAR and if this fails (because of compilation issues), it marks build process failure:


Deploy. Dev CS knows how to deploy EAR into Java Cloud Service. This can be done on demand or automatically, when build is successfully completed. Configuration is simple and straightforward, you need to provide connection details to Java Cloud Service and it works - you can deploy or redeploy:


Application is successfully deployed to Java Cloud Service and visible in EM:


Besides all this, Dev CS offers Wiki's, issue tracking and bunch of other useful features for day to day work in development. So far no complaints, good job Oracle.

Thursday, December 1, 2016

Better Oracle JET Code Structuring with Your Own Modules - Part II

You can end up into long lines of JavaScript code when implementing more complex use cases in JET. This will complicate maintenance and make code hardly readable. To prevent this - plan code structure carefully and use your own modules. Structure code into different modules - to reuse common code across multiple use cases.

Check my JET/ADF BC sample available on GitHub - jetcrud. This sample implements one common module - Customer Controller. Module is responsible to define ADF BC REST service connection. It contains REST service URL, JET model definition with ID attribute and JET collection created based on JET model and assigned with fetch size. This allows not to repeat same definitions again and again in each of JET modules implementing use cases (edit, add, etc.):


Such module is created as any other JET module with define header. We can use it in any other JET module, by specifying module name in define block. For example customers.js module imports Customer Controller through define block:


Within customer.js module we access function from Customer Controller to obtain collection.

Same Customer Controller module is reused inside another module editCustomer.js. Here we are accessing function from Customer Controller to obtain model:


Such approach allows to simplify JavaScript code and render different UIs based on one module. Readonly table is based on customerController.js:


Edit form is based on same customerController.js:


Read previous post - Oracle JET CRUD - Search and Edit Form - Part I.