This series of articles aim to show different integration option between ADF and Oracle JET, as there is some tweaking here and there that we have to consider when doing so. The reason for this is that I believe ADF is not dead, but for some use cases we can bring more value to the customer by making ADF and Oracle JET fly together.

The first integration option is when we have to integrate a full Oracle JET application into an ADF application. That means in the ADF application we create one page where we copy the code from index.html, from the Oracle JET application. I’ve took for this article an Oracle JET application generated from a template provided by Oracle JET. Bottom line is that ADF application will provide a secured frame (login page and resources security using ADF Security) and one JSF page (index.jsf). Oracle JET will be initiated in index.jsf and will generate the navigation and the loading of modules.

You can find the source code in GitHub, click here (use branch dev-usecase1).

Here are the steps to do so:

  • Create the ADF application.
  • Create one JSF page, call it index.jsf.
  • Create the login page, the authentication backing bean.
  • Enable ADF Security and secure the page  index.jsf, this will change web.xml.
  • Generate an Oracle JET application, using any template you want, I’ve used “navbar” template.
  • Copy the css and js folder, from src/ folder of the generated Oracle JET application, into the ViewController project public_html/ foder, from the ADF application.

 

Oracle JET application structure

 

ADF Project Structure after copying the resources

  • In the index.jsf page, from ADF Application, copy the code from src/index.html, from the Oracle JET application. Here you don’t have to copy all, see bellow how index.jsf should look like:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE html>
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <af:document title="index.jsf" id="d1">
        <f:facet name="metaContainer">
            <af:group id="metaContainer">
                <f:verbatim>                 <meta name="viewport" content="width=device-width, initial-scale=1"/>                       </f:verbatim>
            </af:group>
        </f:facet>
        
    <!-- This is the main css file for the default Alta theme -->
    <!-- injector:theme -->
    <link rel="stylesheet" href="../css/alta/3.2.0/web/alta.min.css" id="css" />
    <!-- endinjector -->
    
    <!-- This contains icon fonts used by the starter template -->
    <link rel="stylesheet" href="../css/demo-alta-site-min.css" type="text/css"/>

    <!-- This is where you would add any app specific styling -->
    <link rel="stylesheet" href="../css/override.css" type="text/css"/>
    
    <!-- Copied from JET application index.html body section -->
    <!-- ****************************************************-->
    <!-- Template for rendering navigation items -->
    <script type="text/html" id="navTemplate">
    <![CDATA[
      <li><a href="#">
        <span data-bind="css: $data['iconClass']"></span>
        <!-- ko text: $data['name'] --> <!--/ko-->
      </a></li>
      ]]>
    </script>

    <div id="globalBody" class="oj-web-applayout-page">
      <!--
         ** Oracle JET V3.2.0 web application navigation bar and header patterns.
         ** Please see the demos under Cookbook/Patterns/App Shell: Web
         ** and the CSS documentation under Support/API Docs/Non-Component Styling
         ** on the JET website for more information on how to use this pattern.
      -->
      <header role="banner" class="oj-web-applayout-header">
        <div class="oj-web-applayout-max-width oj-flex-bar oj-sm-align-items-center">
          <div data-bind="css: smScreen() ? 'oj-flex-bar-center-absolute' : 'oj-flex-bar-middle oj-sm-align-items-baseline'">
            <span role="img" class="oj-sm-only-hide oj-icon demo-oracle-icon" title="Oracle Logo" alt="Oracle Logo"></span>
            <h1 class="oj-web-applayout-header-title" title="Application Name" data-bind="text: appName"></h1>
          </div>
          <div class="oj-flex-bar-end">
            <!-- Responsive Toolbar -->
            <div data-bind="ojComponent: {component:'ojToolbar'}">
              <button id="userMenu"
                data-bind="ojComponent: {component: 'ojButton', label: userLogin,
                display: smScreen() ? 'icons' : 'all',
                icons: smScreen() ? {start: 'oj-icon demo-appheader-avatar', end: null} : {end: 'oj-component-icon oj-button-menu-dropdown-icon'},
                chroming: 'half', menu: '#menu1'}">
              </button>
              <ul id='menu1' data-bind="ojComponent: {component: 'ojMenu'}" style="display:none">
                <li id="pref"><a href="#">Preferences</a></li>
                <li id="help"><a href="#">Help</a></li>
                <li id="about"><a href="#">About</a></li>
                <li id="out"><a href="#">Sign Out</a></li>
              </ul>
            </div>
          </div>
        </div>
        <div role="navigation" class="oj-web-applayout-max-width oj-web-applayout-navbar">
          <div data-bind="ojComponent: {component: 'ojNavigationList',
            navigationLevel: 'application', display: smScreen() ? 'icons' : 'all',
            item: {template: 'navTemplate'}, data: navDataSource,
            selection: router.stateId, edge: 'top'},
            css: smScreen() ? '' : 'oj-md-condense oj-md-justify-content-flex-end'">
          </div>
        </div>
      </header>
      <div role="main" class="oj-web-applayout-max-width oj-web-applayout-content" data-bind="ojModule: router.moduleConfig">
      </div>
      <footer class="oj-web-applayout-footer" role="contentinfo">
        <div class="oj-web-applayout-footer-item oj-web-applayout-max-width">
          <ul data-bind="foreach: footerLinks">
            <li><a data-bind="text : name, attr : {id: linkId, href : linkTarget}"></a></li>
          </ul>
        </div>
        <div class="oj-web-applayout-footer-item oj-web-applayout-max-width oj-text-secondary-color oj-text-sm">
          Copyright © 2014, 2017 Oracle and/or its affiliates All rights reserved.
        </div>
      </footer>
    </div>

    <script type="text/javascript" src="../js/libs/require/require.js"></script>
    <script type="text/javascript" src="../js/main.js"></script>

    <!-- END Copy -->
    <!-- ****************************************************-->
    <af:form id="f1"></af:form>
    </af:document>
</f:view>
  • In order to solve the issue of loading the resources through faces/ servlet you have to adapt a bit the path to css/ and js/ Oracle JET resources. See the above code snippet, but you also have to add the following in web.xml (make sure you copied in the right location):
<servlet-mapping>
    <servlet-name>resources</servlet-name>
    <url-pattern>/css/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
        <servlet-name>resources</servlet-name>
        <url-pattern>/js/*</url-pattern>
</servlet-mapping>
  • In the code you copied from index.html to index.jsf there is some knockout specific code, like:
<!-- ko foreach: footerLinks -->
    <li><a data-bind="text : name, attr : {id: linkId, href : linkTarget}"></a></li>
<!-- /ko -->

This will not work because Faces servlet is removing the HTML code from the JSF pages. There are two places where you have to change a bit the code, the template for the Oracle JET navigation needs to use <![CDATA[]]> to escape the code that utilize the HTML comment tags:

<script type="text/html" id="navTemplate">
    <![CDATA[
      <li><a href="#">
        <span data-bind="css: $data['iconClass']"></span>
        <!-- ko text: $data['name'] --> <!--/ko-->
      </a></li>
      ]]>
</script>

This technique is used also in the footer of the Oracle JET application, here you have two options, you could change from the HTML comment fashion to a data-bind approach, like:

<ul data-bind="foreach: footerLinks">
    <li><a data-bind="text : name, attr : {id: linkId, href : linkTarget}"></a></li>
</ul>

or you use af:outputText tag along with escape=”false” attribute, like:

<af:outputText escape="false" value="&lt;!-- ko foreach: footerLinks --&gt;&lt;li&gt;&lt;a data-bind='text : name, attr : {id: linkId, href : linkTarget}'&gt;&lt;/a&gt;&lt;/li&gt;&lt;!-- /ko --&gt;"/>