Individual Frame Layout in ADF 12c via custom RichRenderer Class

In one of our Forms to ADF modernization projects, one of our customers wanted to keep the UI structure more or less the same. For many components, there are best practices to map one Oracle Forms UI Component to ADF Structures, but in our case, we had to provide a solution to the following UI-Container Pattern:

The idea of this pattern is to provide help for the user to see a categorization of UI Items. In general ADF, this might be done via UI Categorization via UI Hints at View Object Level. Unfortunately, this resolves into af:group containers on UI, which are interpreted by the parent container to make sense out of the items. So all in all, we are limited by the frameworks default implementations.

To solve the problem, we thought about the general solution in free html/css context. Here the problem is easy to solve. See


for a sample solution. To reach the explicit HTML code you need out of JSF components is (in most cases) not possible.

Again, ADF supports the creation of own declarative components, but typically we just join other JSF compontents to our liking.

So we have to go one step further. The next steps show you how to create a "component/renderer" mashup to achieve the NamedFramePattern in ADF.

1. Create a declarative container component that has only a panel group layout and a content facetRef. Be sure to add a ComponentClass to your Declarative component for easier access and uniqueness afterwards.

(The Group layout inside is necessary, since all declarative components are not rendered per definition of the UIXBaseComponent-Renderer because it is only a reference for a JSF include).

2. Create a RichRenderer that is based on the renderer for ADF Group Layouts and add additional HTML code to the rendered feature. This can be done by overriding the encodeAll(...) method of the parent class.

package de.teampb.ir.templates.nf;

import java.io.IOException;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;

import javax.faces.context.ResponseWriter;

import oracle.adf.view.rich.component.rich.fragment.RichDeclarativeComponent;
import oracle.adf.view.rich.component.rich.layout.RichPanelFormLayout;
import oracle.adf.view.rich.render.ClientComponent;
import oracle.adf.view.rich.render.RichRenderer;

import oracle.adfinternal.view.faces.renderkit.rich.DeclarativeComponentRenderer;

import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.context.RenderingContext;
import org.apache.myfaces.trinidad.render.CoreRenderer;

import oracle.adfinternal.view.faces.renderkit.rich.PanelGroupLayoutRenderer;

public class NamedFrameRenderer extends PanelGroupLayoutRenderer {
    public NamedFrameRenderer() {

    private static final String DEFAULT_COLOR = "#AAAAAA";

    private static final String IMPORTANT_COLOR = "#FFAAAA";

    protected void encodeAll(FacesContext facesContext, RenderingContext renderingContext, UIComponent uIComponent,
                             ClientComponent clientComponent, FacesBean facesBean) throws IOException {
        ResponseWriter rw = facesContext.getResponseWriter();
        if (uIComponent.getParent() instanceof NamedFrame) {
            NamedFrame nf = (NamedFrame) uIComponent.getParent();
            rw.startElement("div", null);
            rw.writeAttribute("style", "border: 2px solid " + getColor(nf) + "; margin: 5px; padding: 5px", null);
            rw.startElement("h2", null);
                              "text-indent: 30px;\n" + "    margin-top: -10px;\n" + "    height: 10px;\n" +
                              "    line-height: 20px;\n" + "    font-size: 15px;", null);
            rw.startElement("span", null);
            rw.writeAttribute("style", "background-color:#FFFFFF; color:#000000;", null);
            rw.writeText(nf.getTitle(), null);
            super.encodeAll(facesContext, renderingContext, uIComponent, clientComponent, facesBean);
        } else
            super.encodeAll(facesContext, renderingContext, uIComponent, clientComponent, facesBean);

    private String getColor(NamedFrame nf) {
        if ("important".equals(nf.getType())) {
            return IMPORTANT_COLOR;
        } else
            return DEFAULT_COLOR;


The idea is that the renderer overrides the default Renderer for Panel Group layouts. So we have to keep the default implementation (the inside super.encodeAll line).

(The HTML code could be beautified by using classes instead of inline style, but I think you get the idea)

3. Add renderer to faces-Config.xml in the consuming ViewController Project.

4. Use declarative component as usual to achieve the layout addition by the renderer.

As you can see from the last image, since the JDeveloper design view uses the internal renderer classes we also get the advantage of what-you-see-is-what-you-get development. The resulting ADF application then looks as follows:

Please feel free to download the sources at


and pull the sources. To run the application, you need access to an HR schema. Then Run the hr-main.xml Task-Flow.



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:


You may need to install the packages via 

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


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) {

    configPath: path.join(process.cwd(), "scripts/grunt/config")



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

  grunt.registerTask("build", (buildType) => {

  grunt.registerTask("serve", (buildType) => {

  grunt.registerTask("test", (buildType) => {

  grunt.registerTask("startServer",(buildType) => {

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! 


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

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!


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.


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:


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


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.


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!