2016-09-13

Oracle JET 2.1.0. missing --web=true serve parameter in hybrid grunt template

Many developers try to work WYSIWYG-style on their projects. Especially in mobile/hybrid projects, many times it comes in handy to develop against a web browser instead of a mobile phone or emulator.

In Oracle JET 2.0.1 it was possible to develop a JET Hybrid application and serve the app via 

grunt serve --platform=android --web=true

which would prebuild the sources for android devices but create a local nodeJS server that runs the application. This meant very fast development, especially in trial and error phases of development.

Since Version 2.1.0 Oracle turned grunt tasks towards own oraclejet grunt tasks (coming with the npm package grunt-oraclejet), which seem not to work well with the old parameters. So the given command results in:

Warning: Flag 'web' not supported! Use --force to continue
Aborted due to warnings.

Even forcing does not change anything to this matter. There might be a "parameter passing" option to the oraclejet grunt build file, but I did not find anything like that. So to keep up the style of developing, we just want to create a new grunt task.

First, we need to use some additional npm packages:

grunt-contrib-connect
grunt-open

You may need to install the packages via 

npm install grunt-contrib-connect --save-dev

resp.

npm install grunt-open --save-dev

You can then change the Gruntfile.js of your project to be the following:


'use strict';

var path = require('path');
module.exports = function(grunt) {

  require("load-grunt-config")(grunt,
  {
    configPath: path.join(process.cwd(), "scripts/grunt/config")
  });

  grunt.loadNpmTasks("grunt-oraclejet");
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-open');

  grunt.initConfig({

  connect: {
    dev: {
      options: {
        port: 8090,
        base: 'hybrid/www',
        keepalive: true
      }
    }
  },
  open : {
    dev : {
      path: 'http://localhost:8090',
    }
  }
});

  grunt.registerTask("build", (buildType) => {
    grunt.task.run([`oraclejet-build:${buildType}`]);
  });

  grunt.registerTask("serve", (buildType) => {
    grunt.task.run([`oraclejet-serve:${buildType}`]);
  });

  grunt.registerTask("test", (buildType) => {
    grunt.task.run(["build","open:dev"]);
  })

  grunt.registerTask("startServer",(buildType) => {
    grunt.task.run(["connect:dev"]);
  })
};

With this gruntfile you can start a local nodeJS Server on your "hardcoded-but-default" web-target folder (hybrid/www) via 

grunt startServer

The command 

grund test

will clean and build your sources in the default platform (android for hybrid apps in OracleJET 2.1.0) and then open your default browser to load the newly build page. 

This is by far not as effective as the --web=true serve-parameter, but it is better than nothing ;)

Have fun to try it yourself, just scaffold your hybrid app (eg:  yo oraclejet:hybrid app --appName="Sample Oracle JET App" --template=navdrawer --platforms=android) and change the gruntfile.js.

Happy Coding! 

2016-08-17

Oracle JET Open Online Course

If you want to get in touch with the new Oracle Java-Script Framework to create some fancy user experience focused applications or want to see how easy it is to create hybrid mobile applications to your complex backend, you might want to enroll to the
Oracle JET MOOC

This online course (beginning August 22nd - ending September 12th) offers some video exercises a week, so it is your chance to keep up with a new Oracle Framework even after work. Some of the Features to be shown include:
  • Apply basic JET principles to create Oracle JET application including JET modules, layouts and components
  • Apply more advanced JET functionality, including navigation, routing, validation, layouts, and responsive design.
  • Create hybrid mobile applications with Cordova in combination with Oracle JET.
  • Integrate with the world outside Oracle JET, e.g., JQuery components and the Oracle Cloud.
  • Deal with the remaining enterprise-level challenges, i.e., internationalization, accessibility, and security.

So there should be some content for everybody out there. Hope to see you in class!

2016-05-31

LOV from Shared Application Modules with a different data source - table or view not found

In many cases lookups are being used to create a readable image of a key column inside a database table. Many of these lookups are globally defined for many applications inside the company. So in general it is a good idea to generate a base package / project containing business components for these lookup references.

Preparation:

A sampe project setup could look something like this.



In this case, we used one project for two application modules, the SharedModule stating the (session) shared application module from the base packages. This allows to use the same view object instances across a user session:



It references the oracle schema Salary with the table SALARY_STEPS (table def can be found in the database project, just import it to a different schema than HR).

The main data ApplicationModule HRService connects to the oracle default HR schema. Inside the ViewObject EmployeesView and a list of values is defined on the attribute Salary using the ViewObject instance from shared am instance:



Issue:

When starting the HRService Application Module with the AM-Tester (right-click -> run), the simple data model is shown.

 

Double clicking the EmployeesView Instance we will receive a ORA exception that the SALARY_STEPS table is not found and we see, that the lov of the Salary attribute is empty



Analysis:

The main issue is, that the Application Module SharedModule uses the same connection as the HRService, since (as a session shared application module) it is always nested inside the Root Application Module of the View Object that uses a view object instance as a view accessor from the shared AM. So per definition of session shared application modules, it is not possible declaratively to use a different data source to the main data source.

Solution:

If we go back to the Model.jpx and change the type of the shared application module from session scoped to application scoped, the behaviour of the shared module changes drastically.



Each shared application module in this scope will provide a separate singleton root application module, so one database connection will be opened for each shared application module. But this feature is necessary for declarative lov definition on shared application modules. So running the HRService with this settings, we see that the LOV is correctly defined and we can use it as any other LOV View Accessor






So even if you do only use one data source, it might come in handy to use a shared application module view object instance for your lookups, especially when encountering large result sets for the lov, which could be stored in memory for each user session or even across the whole application.

If you want to give it a try, head over to the new German ADFCommunity github [https://github.com/ADFCommunityDE/SharedAMMultiDataSource.git] and pull the sources :)

By the way, this Application was created using JDeveloper 12.2.1 but the topic is useable for 11g R1 and R2 as well!

Cheers!