Lazy Initalizing Beans

A questions on the OTN JDeveloper & ADF forum asked how to initialize attributes with data in a bean before showing the attributes.
The first solution which comes to mind is to initialize attributes and data in the constructor of the bean. This however is not a wise thing to do as you can’t predict when the constructor is called and in which phase of the life cycle you are (as it depends on the scope of the bean).
Here you can use a solution I call lazy initializing the data of a bean. It’s based on the assumption that once the page tries to get an attribute from the bean, the life cycle already has done all other initializations (like bindings). Now if we defer the init of the bean data until a (or the first) getter is called we are save.
To implement this we set an attribute to null and check if it’s null in the getter of the attribute. If we find it’s still null, we init the data and set the attribute to a not null value. Here is the sample code:

package de.hahn.blog.lazyinitbean.view.beans;

import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import javax.servlet.ServletContext;

import oracle.adf.model.BindingContext;
import oracle.adf.share.logging.ADFLogger;

import oracle.binding.AttributeBinding;
import oracle.binding.BindingContainer;

public class LazyInitBean {
    private static transient final ADFLogger LOGGER = ADFLogger.createADFLogger(LazyInitBean.class);

    private String myName;

    public void setMyName(String myName) {
        LOGGER.info("set data: " + myName);
        this.myName = myName;
    }

    public String getMyName() {
        // lazy init the data only when it's null
        if (myName == null) {
            LOGGER.info("init data through layz init");
            initData();
        }
        return myName;
    }

    public LazyInitBean() {
        LOGGER.info("LazyInitBean: c'tor");
    }

    private void initData() {
        LOGGER.info("data intialized");
        // this method inits the beans attributes (only one here)!
        myName = "just init myself";
        //Get ServlerContexct
        FacesContext ctx = FacesContext.getCurrentInstance();
        ServletContext servletContext = (ServletContext) ctx.getExternalContext().getContext();
        // get the binding container
        BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();

        // get an ADF attributevalue from the ADF page definitions
        AttributeBinding attr = (AttributeBinding) bindings.getControlBinding("myTestValue1");
        if (attr != null) {
            String old = (String) attr.getInputValue();
            attr.setInputValue("NEW DEFAULT VALUE");
            LOGGER.info("LazyInitBean: setnew default value to 'NEW DEFAULT VALUE' old: " + old);
        } else {
            LOGGER.info("LazyInitBean: bindings not present!");
        }
    }

    /**
     * Force the init of the beans attributes
     */
    public void resetData() {
        LOGGER.info("LazyInitBean: reset!");
        // setting the myName to null causes a re initialization
        myName = null;
        // you can call initData() here too;
        initData();
    }

    public void buttonListener(ActionEvent actionEvent) {
        LOGGER.info("Action initData");
        resetData();
    }
}

Now, whenever in a page or fragment the getter to the bean parameter is called (this can be the getter to every property of a component which can have EL) the bean is checkes if the attribute is already initialized and if not calls the initData() method in the bean. If a value is present, the getter returns the value. The initData() method show that attributes in the binding layer can initialized this way too. This is shown with the myTestValue1 attribute which is defined as pageDef variable. You can overwrite the text in the inputText and when you click the button ‘Clear Data’ the data is initialized again removing the data from the inputText and setting it back to the initial values.
Below is a sample of a fragment which uses the bean to lazy initialize the attribute.

<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <af:panelGridLayout id="pgl1">
        <af:gridRow height="100%" id="gr1">
            <af:gridCell width="100%" halign="stretch" valign="stretch" id="gc1">
                <!-- Content -->
                <af:panelGroupLayout id="pgl2" layout="vertical">
                    <af:outputText value="Lazy Region" id="ot1" inlineStyle="font-size:large;"/>
                    <af:inputText label="Name:" id="it1" value="#{backingBeanScope.LazyInitBean.myName}" partialTriggers="b1 b2"/>
                    <af:outputText value="Hello: #{backingBeanScope.LazyInitBean.myName}!" id="ot2" partialTriggers="b2 b1"/>
                    <af:button text="ShowMessage" id="b2"/>
                    <af:button text="Clear Data" id="b1" actionListener="#{backingBeanScope.LazyInitBean.buttonListener}"/>
                    <af:inputText label="MyTestValue" id="it2" value="#{bindings.myTestValue1.inputValue}" partialTriggers="b1"/>
                </af:panelGroupLayout>
            </af:gridCell>
        </af:gridRow>
    </af:panelGridLayout>
</ui:composition>

Be aware of the fact, that this solution depends on the component(s) which calls the getter which in due course init the data. As the getter methods of the components are called in the order they appear in the component tree you have be careful which getter you use. It should be the first if you want to setup everything up front, but use the last if you want to load data at the end of the page render cycle (e.g. to get more data from a web service but already see the page).

In a comment Aino Andriessen mentioned that you can use the @PostConstruct annotation on a method which then will be called whenever the bean is constructed after all other injections are done. That is the difference to lazy init method. The method is called every time after all other injections are done. If you only want to setup data if the data is really needed this is not possible this way. Nevertheless, to make the sample application show the @PostConstruct method too, I added a method postconstructMethod() in the bean, which writes a log message.

    @PostConstruct
    public void postconstructMethod() {
        LOGGER.info("PostConstruct Called!");
        // init everything here which can be done quickly and is needed to init UI components before showing them
        // or call initData() from here
    }

You can download the sample workspace from the ADF-EMG Sample Project page of get it from GitHub. The sample does not need a DB. The samples are updated to show the @PostConstruct technique.

JDev 12.1.3: Using Parent Action to Navigate Tabs of a af:panelTabbed from Inside a Region

This blog is based on a question in the OTN JDeveloper and ADF forum. The Question was how to navigate from one selected tab to the next tab when the af:showDetailItem in the tab is a region and the button to navigate is inside the region.

We implement two cases, the first is the easy one where the button to navigate is in the page holding the af:panelTabbed. The second one uses a button is inside a bounded task flow which is shown in the af:showDetailItem in a tab to navigate the af:panelTabbed.

We start with creating a new ‘ADF Fusion Web Application’ from the gallery. We only change the application name and the path of the application, otherwise we can just use the default values. The sample is simple and doesn’t need a model project or connection to a DB. You can download the finished workspace using the link provided at the end of the post.

We skip all the needed steps and going right into creating the starting page which holds the af:panelTabbed. It has three af:showDetailItem and a af:Button to navigate the tabs directly from the page. This button implements the first use case.

Start Page with Outer Navigation

Start Page with Outer Navigation

The button has a listener attached which is implemented in a viewScope bean ‘NavigateTabBean’. The listener implements the needed logic to navigate from the selected tab to the next tab. If the last tab is reached the first tab is selected.

    private static ADFLogger _logger = ADFLogger.createADFLogger(NavigateTabBean.class);
    private static final String PANELTAB = &quot;pt1&quot;;

    /**
     * Eventhandler to navigate to the next tab in a af:panelTabbed
     * @param actionEvent event which called the listener
     */
    public void naviGateButtonAction(ActionEvent actionEvent) {
        UIComponent ui = getUIComponent(PANELTAB);
        if (ui == null) {
            _logger.info(&quot;PanelTab component not found!&quot;);
            return;
        }
        if (!(ui instanceof RichPanelTabbed)) {
            _logger.info(&quot;Component is not an af:panelTabbed&quot;);
            return;
        }

        RichPanelTabbed rpt = (RichPanelTabbed) ui;
        int childCount = rpt.getChildCount();
        List&lt;UIComponent&gt; children = rpt.getChildren();
        for (int ii = 0; ii &lt; childCount; ii++) {
            UIComponent uiSDI = children.get(ii);
            if (uiSDI instanceof RichShowDetailItem) {
                RichShowDetailItem rsdi = (RichShowDetailItem) uiSDI;
                if (rsdi.isDisclosed()) {
                    //close current tab
                    rsdi.setDisclosed(false);
                    //calculate next tab to disclose as next_tab_index = (current_tab_index + 1) % number_of_tabs
                    int kk = ii + 1;
                    int jj = kk % childCount;
                    _logger.info(&quot;old disclosed tab: &quot; + ii + &quot; new disclodes tab: &quot; + jj);
                    RichShowDetailItem newSDI = (RichShowDetailItem) children.get(jj);
                    //open new tab
                    newSDI.setDisclosed(true);
                    AdfFacesContext.getCurrentInstance().addPartialTarget(rpt);
                    return;
                }
            }
        }
    }

    // find a jsf component
    private UIComponent getUIComponent(String name) {
        FacesContext facesCtx = FacesContext.getCurrentInstance();
        return facesCtx.getViewRoot().findComponent(name);
    }

    public void nextTab() {
        naviGateButtonAction(null);
    }

The logic in the action listener first searches for the af:panelTabbed in the viewRoot and gets the number of children from it. Each child is one of the af:showDetailItem representing a tab. Then we iterate over the child list and search the currently disclosed tab. We close this tab and the next tab in the list gets disclosed. If the currently selected tab is the last in the list, the first tab is disclosed (see the comments in the code section).

To Implement the second use case, the one we really want to talk about, we first need to implement three bounded task flows which we later use as regions in the tabs.

Bounden Task Flow with Parent Action

Bounden Task Flow with Parent Action

The image shows the bounded task flow for one tab. The other bounded task flows are build in the same way and are just showing different text. The reason for this is that you normally would use different regions aka different task flows in the tabs. We could have used only one bounded task flow with a parameter to change the text shown in the fragment. In the sample you’ll find this implemented for tabs 4 and 5.
The region is simple and only shows one fragment which has a button to navigate to the next tab and a test to distinguish the regions when navigating. The whole magic is the parent action in the bounded task flow. This parent action executes a navigation case ‘nextTab’ in the parent task flow.

Unbounded Task Flow with Start Page

Unbounded Task Flow with Start Page

In the image above we the the unbounded task flow which is the parent of the bounded task flow. Here a wild card rule navigates to a method call activity ‘selectNextTab’ using the navigation case ‘nextTab’ we entered to the parent action of the regions.
The method action calls the ‘nextTab()’ in the managed bean from the code section above. All this method does is to call the action listener which is called from the af:Button of the start page (Start.jsf). As the action listener needs an ActionEvent as parameter, which we don’t use in the code we pass ‘null’ when we call the listener from the method call activity.

This concludes the implementation. Here are some images from the running application

The sample application can be downloaded form ADFEMG Sample Project.

A version of the software build with JDeveloper 11.1.1.7.0 can be downloaded from GitHub

JDev 12.1.3: Use Default Activity Instead of the Deprecated Invoke Action

Since JDeveloper 12.1.3 the invoke action used in earlier version has been deprecated. Users still using the old invoke action to load data on page load should migrate their code to using the default activity in a bounded task flow instead. This article describes how to use the executeWithParams method as a default activity in a bounded task flow (btf) to load data to be shown in a region. For this we implement a common

Use Case:
in a text field the user enters a string which should be used to look-up data in the DB and show the data as a table in a region.
For this we use the HR schema and build a look-up for locations after the name of the city of the location. In a page the user can insert the name or part of a cities name into a text field. This input is send as parameter to a bounded task flow. The default activity of the btf calls a method in the view object which uses a view criteria to search for cities starting with the given input data. In a second implementation the same technique is used but a where clause is used in the VO and the VO is called with executeWithParams. The result of the search is displayed as a table in a region.

Implementation

Model Project:
We start by creating a new ‘Fusion Web Application’ and creating a model project of the HR DB schema. Here we only use the location table for which we create entity object and view object.
Now we create the view criteria which we use to find locations by part of the city name.

Next step is to create the java class for the view object including the method to safely access the created bind variable. In the class we add a method to apply the created view criteria which we expose in the client interface well as the methods to access bind variables.


Finally we have to make sure that the locations view object is part of the data model of the application module.
Resulting Application Module Data Model

Resulting Application Module Data Model


Next we add another view object to the data model which we use to implement the use case a second time. This time we use the view criteria we defined in the view object LocationsView and select it as the default where clause.

ViewController Project:
We start implementing the view controller project by first adding a start page, ‘Start’, to the unbounded task flow in adfc-config.xml. For this page we use a quick layout (One Column, Header stretched).

After opening the page (which creates it) we add a third grid row to the panelGridLayout we got from the quick layout which later holds the result table. In the first grid row we add a captain for the page, ‘Execute with param sample’, the second grid row we add an af:inputText which holds the users input for the city name to search for.
The page looks 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="Start.jsf" id="d1">
        <af:form id="f1">
            <af:panelGridLayout id="pgl1">
                <af:gridRow height="50px" id="gr1">
                    <af:gridCell width="100%" halign="stretch" valign="stretch" id="gc1">
                        <!-- Header -->
                        <af:outputText value="ExecuteWithParams Test" id="ot1" inlineStyle="font-size:x-large;"/>
                    </af:gridCell>
                </af:gridRow>
                <af:gridRow height="50px" id="gr2">
                    <af:gridCell width="100%" halign="stretch" valign="stretch" id="gc2">
                        <!-- Content -->
                        <af:inputText label="City" id="it1" value="" autoSubmit="true"/>
                    </af:gridCell>
                </af:gridRow>
                <af:gridRow id="gr3">
                    <af:gridCell id="gc3">
                        <!-- REGION HERE -->
                    </af:gridCell>
                </af:gridRow>
            </af:panelGridLayout>
        </af:form>
    </af:document>
</f:view>

Now we create a pageDefinition for the page, where we define a variable and an attribute binding which holds the users input into the inputText we added to a grid row below the header.


The final inputText look like

<af:inputText label="City" id="it1" value="#{bindings.searchCityName1.inputValue}" autoSubmit="true"/>

As you see we set the autoSubmit property to true as we don’t have (and need) a button to submit the data to the binding layer.

The next task is to create a new bounded task flow which has one input parameter, which is used to search for locations with cities starting with the given parameter from the inputText component.

Once the bounded task flow is created we can drag this btf onto the start page and drop it in the girdCell in the third gridRow and wire the parameter for the task flow to the value we have stored in the in the variable iterator via the inputText.

Finally we make the region refresh whenever the inputParamter of the task flow changes by setting the regions refresh property to ‘ifNeeded’.
The final ‘Start’ page layout looks 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="Start.jsf" id="d1">
        <af:form id="f1">
            <af:panelGridLayout id="pgl1">
                <af:gridRow height="50px" id="gr1">
                    <af:gridCell width="100%" halign="stretch" valign="stretch" id="gc1">
                        <!-- Header -->
                        <af:outputText value="ExecuteWithParams Test" id="ot1" inlineStyle="font-size:x-large;"/>
                    </af:gridCell>
                </af:gridRow>
                <af:gridRow height="50px" id="gr2">
                    <af:gridCell width="100%" halign="stretch" valign="stretch" id="gc2">
                        <!-- Content -->
                        <af:inputText label="City" id="it1" value="#{bindings.searchCityName1.inputValue}" autoSubmit="true"/>
                    </af:gridCell>
                </af:gridRow>
                <af:gridRow id="gr3">
                    <af:gridCell id="gc3">
                        <af:region value="#{bindings.showlocatiobycitybtf1.regionModel}" id="r1"/>
                    </af:gridCell>
                </af:gridRow>
            </af:panelGridLayout>
        </af:form>
    </af:document>
</f:view>

This concludes the first implementation and we can run the application

The sample application can be downloaded form ADFEMG Sample Project. It contains a second page (Start2) which uses the other view object (LocationsWithParamsView) inside the region. It’s build like the first version. The difference is that the default activity nor is the executeWithParams from the VOs operations instead the self implemented method from the VO. You spare writing the method and exposing the method in the client interface this way.
Be aware that the sample uses the HR DB schema and you have to change the connection information to point to your DB.

JDeveloper 12.1.3: Using File Templates

Since JDeveloper 12.1.2 Oracle added a feature called ‘File Templates’. Only there was absolutely no documentation for this. We only had the ‘File Templates’ node in the preferences. I filed a bug (ADFEMG-150) for this.
In the current JDeveloper 12.1.3 release the ‘inital’ documentation for the ‘File Templated’ has been added.
To get to the ‘File Templates’ via the Tools->Preferences->’File Tempalates’ and see the below image.

File Templates in Preferences

File Templates in Preferences


Loading the extension you get
FileT emplates Inital Dialog

File Templates Inital Dialog


The only help I found can be reached by clicking the Help button in the dialog which will get you
File Templates Help

File Templates Help


This is not much to work with. I you find more help on using this feature, drop me a note, please. All I present in this blog was found out using try and error. There seams to be a difference if you use a Windows or Unix based machine. Later in the blog I’ll give more info on this.

Let’s start with my findings. Clicking through the tree shown in the image above you quickly get the intention of the file templates. This feature allows us to define template for files (e.g. java classes) which can be used to define repeating code and generate the files from it. The sample which is provided by Oracle builds a template for a java class containing copyright and licence information.


However, there is no button or menu to create your own template from scratch. The pencil icon in the top right corner is disabled for each of the files. The only way to create a new template file is to copy an existing one by using the ‘Copy’ button. The first time you click the copy button for one of the files in the you get a note that you can’t change the files in place:
Confirm Modify Template

Confirm Modify Template


confirming the dialog with yes, a copy the content of the sample template from the jar will be created into a file you can edit. All custom template files are written to system12.1.3.0.41.140521.1008\o.jdeveloper.filetemplate\ folder by default. While copying the files you can change the ID, description, the Name and the file name of the template.

Please not the properties in the dialog which allows to define where you later find the template in the gallery.
Once we have copied all files from the tree we can start to modify them. The file suffix of the templates is ‘ftl’. The copied files are automatically opened in the JDev editor. Here comes the first glitch in the extension. If you change *.ftl files in the JDev editor and hit the ‘Save All’ button, the files are not saved. The caption of the tabs remains italic, meaning that the content of the tab has changed and is not saved. You need to hit the ‘Save’ button to save each file by itself.
Once the templates are copied into an accessible path, you can use the ‘Pencil’ button to open them again in the JDev editor, or you can make small changes directly in the editor window in the dialog.
Looking at the content of the files you see that ‘copyright-hahn-java.ftl’ inludes ‘license-hahn-txt.ftl’ which then includes ‘copyright-hahn-content.ftl’. This is the first file we change to change the copyright notice
Changed Copyright Text

Changed Copyright Text


To make the licence ‘license-hahn-txt.ftl’ pick up the changes copyright text we have to change the include statement in the licence template
Change Include  of Copyright in Licence Template

Change Include of Copyright in Licence Template


and finally we have to change the ‘copyright-hahn-java.ftl’ to pickup the changes licence template
Change Include of Licence in Template

Change Include of Licence in Template


After saving all changes (remember to save each file separately) we can test the template. For this we select a package in a project, right click the package we want the file created in and select ‘New’->’From Gallery…’
Select 'New'->'From Gallery...'

Select ‘New’->’From Gallery…’


When we save the java call template we saved the information where the template shows up via the ‘Category’, ‘Folder’ and ‘Feature’ properties of the template dialog (these properties define where the template shown up in the gallery). Select ‘Java’ and you should see
Select the Template from the Gallery

Select the Template from the Gallery


Please notice the name which is the ID we chose for the template and the description which comes from the save dialog too. Select the template and you get the file save dialog
File Save Dialog

File Save Dialog


In the JDev editor you get the generated java class
Generated Class from Template

Generated Class from Template


Please note the error in line 26 of the generated java class

package de/hahn/blog/test1213/.model/adfbc/;

should be

package de.hahn.blog.test1213.model.adfbc;

This only happens on Windows machines, Unix machines generate the right package statement. You have to correct this yourself. I’ll file an bug this.

Now that we have seen this sample, let’s ask what’s missing.

    1) Documentation: if you look at the templates you seethe usage of variables in the templates like ‘${name}’ or ‘${package}’, however, I could not find if there any other valuables as the once you see in the sample. Same is true for the language behind the template mechanism. The sample show some kind of ternary operator, question is what other options do we have. The file suffix ‘.ftl’ and some other information I gathered for this blog post, suggests that the templates are using a tool named ‘FreeMarker’.
    2) Use cases: I would like to use templates at other points like java classes generated for ViewObjectImpl, EntityObjecImpl or ApplicationModuleImpl. This is not possible right now. It would be handy e.g. to generate files with ADFLogger directly implemented. You can insert the ADFLogger into the class using the template, but as this is only done for classes you create via the template most of the other generated classed need to be changed by hand.
    3) applying the template to an existing class is not possible. If you like a copyright statement in each class you can’t attach it from a template.

Problem Installing MAF on WIN 7 64bit System

Aside

The documentation states that installing JDeveloper 12.1.3 on a Windows 7 system (32 or 64) requires administrators rights (Select an Installation User). This is a known fact.
A side effect on my Windows box was, that installing ‘Mobile Application Framework’ (MAF) failed. When I tried installing MAF on my Win 7 laptop via ‘Check for updates’ and confirming the dialog which ask for a restart of JDeveloper, it never came back on. Using the task manager, it turned out that JDeveloper started but that there are other processes waiting for something.
Using some System Internal’s tools I found out that Jdev started opatch to install a needed patch before applying the MAF extension. As the processes are started from Jdev internally, it’s kind of hard to find out the real problem. Readings the doc and searching the file system found a log file, opatch writes into the opatch log folder. The information from this log is that opatch can’t lock or create a folder needed for internal use.

[04.07.2014 19:49:58]        OUI-67064:OPatchSession kann den Bestand für das angegebene Oracle-Standardverzeichnis nicht laden R:\JAVA\12130~1.0\ORACLE\MIDDLE~1. Mögliche Ursachen sind:
                                Keine Lese- oder Schreibberechtigung für ORACLE_HOME/.patch_storage
                                Zentrales Bestandsverzeichnis ist von einer anderen OUI Instance gesperrt
                                Keine Leseberechtigung für zentrales Bestandsverzeichnis
                                Die Lock-Datei ist in ORACLE_HOME/.patch_storage vorhanden
                                Das Oracle-Standardverzeichnis ist in dem zentralen Bestandsverzeichnis nicht vorhanden
[04.07.2014 19:49:58]        OPatch will clean up 'scratch,backup' directories.

Here is the english message

[04.07.2014 19:57:34]       OUI-67064:OPatchSession cannot load inventory for the given Oracle Home R:\JAVA\12130~1.0\ORACLE\MIDDLE~1. Possible causes are:
                                No read or write permission to ORACLE_HOME/.patch_storage
                                Central Inventory is locked by another OUI instance
                                No read permission to Central Inventory
                                The lock file exists in ORACLE_HOME/.patch_storage
                                The Oracle Home does not exist in Central Inventory

The problem is that installing Jdev as administrator put rights onto the file system (Understanding User Permissions) which prevents creating and locking the folder for the normal use running Jdev. This fact can be found in the doc too

When managing a product installation (for example, applying patches, or starting Managed Servers), you must use the same user ID as was used to perform the initial product installation.

To fix the problem start Jdev as administrator and the installation of the MAF extension should work.

JDev 12.1.3 Reorder Fields in Query Panel Clarification

Aside

Reading the ‘What’s new in this release’ document, I found

Reorder Fields in Query. Added ability to reorder fields in Query search panel.

I thought that we now can change the order of the fields in the af:query component at design time, like in an af:gridLayout, and started searching the documentation.
Sadly it turned out that this is not a design time option, as I thought, but a run time option!
This is documented at ‘33.2 Creating Query Search Forms’. Below you see the images from a query in advanced mode with the reorder button (down right) and the reorder dialog.


To reorder the fields at design time you can only use the technique blogged by Luc Bors ADF 11g: Change attribute order in query component

My Personal Bug Parade of JDev 12.1.2 fixed in JDev 12.1.3

Last week (June, 26th 2014) JDev 12.1.3 arrived, today (June, 30th 2014) the ADF Mobile Extension for 12.1.3 was published. You can get it via the menu Help->”Check for Updates…”
However, the first thing I did over the weekend was to check my personal bug parade.
In the list below you see the bugs and there status
UPDATE (July, 18th 2014): Added ADFEMG-118

Bug Status Info
ADFEMG-118
af:poll with interval set to 5000 and timeout set to 5001 doesn’t stop polling after on roundtrip
OPEN The behavior has changed but still not as expected. You still get refresh events after the timeout.
ADFEMG-120
JDeveloper 11.1.1.7.0: can’t create af:tree or af:treetable on a jspx page
OK
ADFEMG-149
JDeveloper 12.1.2.0.0: Completion Insight doesn’t show javadoc for ADF classes
OK without the ADF source code, which you can get filing a SR with support.oracle.com (payed support contract needed), you only see a notice that ‘No ducumentation is available’ instead the api java doc.
ADFEMG-150
JDeveloper 12.1.2.0.0: Missing documentation for usage of ‘File Templates’
OK
ADFEMG-154
JDeveloper 12.1.2.0.0: Completion Insight ‘ctrl-space’ doesn’t do a ‘Declaration Insert’
OK
ADFEMG-156
AttributeValues assigned to variables iterator loose their assigned iterator after clicking on other attribute values in the same pageDef
OK There are some hints that this bug is somehow not fixed for all circumstances. However, my test case works out OK. Whenever someone has a reproducible test case I reopen the bug. Please drop a note then.
ADFEMG-157
JDeveloper 12.1.2.0.0: Filter on af:table doesn’t show up if VO is only based on a SQL query
OK
ADFEMG-159
JDeveloper 12.1.2.0.0: ViewCriteria editor behavior differs from 11g and generated SQL from VC is suboptimal
OK
ADFEMG-160
JDeveloper 12.1.2.0.0: Property Inspector changes properties of not selected component
OK
ADFEMG-179
JDeveloper 12.1.2.0.0: ViewObject with hidden bind variable in where clause crashes application module tester
OK
ADFEMG-189
JDeveloper 12.1.2.0.0: af:inputFile with multiple files to upload duplicates files
OPEN

Good work! Only one bug didn’t make it into the first 12.1.3 release!

Working through all the test cases was kind of fun. My impression of the product is that it’s stable and easy to use. OK, I had no time playing around with the new features. This will be my task in the next weeks. Stay tuned for more on JDeveloper 12.1.3.

JDeveloper 12.1.3 is out!

Oracle JDeveloper 12cR1 aka JDeveloper 12.1.3 finally arrived. We had to wait almost a year for this version.
From my first day working with it I can say that it was time well spent. Some nasty bugs from version 12.1.2 are fixed, others still need checking. This will take me a couple of days.
I spare you listing all new features which you can find at ‘What’s new’.

You can download the version from the JDev home page.

Interestingly there are only three install packages, one for Windows, one for Linux and the generic installer. The platform specific install packages are only for 64 bit systems. A look into the certification matrix shows that 32 bit systems are only listed under ‘Other Operating Systems’. I’m not sure if this means that you can’t run this version on 32 bit Windows, or if 32 bit Windows is just ‘others’. I don’t have a 32 bit OS available, do I can’t test this. However, to install on a 32 bit system you have to download the generic installer (size 1.8GB).

The installation went smooth, under 1 minute on my 64GB i7 server with a big SSD running Ubuntu 14.04!
Be advised that some things in the configuration have changed. Stuff you are used to change in Jdev.conf (like jdk) has been moved to a new file product.conf which is stored at your home/.JDeveloper folder. This makes it easier to change the configuration like setting the ide.user.dir and some memory options. More information on this can be found in the ‘Installation Guide’.

It’s going to be a busy weekend checking out all the new stuff. Have fun using Jdev 12.1.3!

Book Review: Oracle ADF Faces Cookbook by Amr Gawish

During my short vacation I spend some time reading books. One of them was ‘Oracle ADF Faces Cookbook’ by Amr Gawish (http://bit.ly/PhWTlR).

Oracle ADF Faces Cookbook

Oracle ADF Faces Cookbook


The book is written as a cookbook, as the name says, for ADF Faces in the version 12c (12.1.2.0.0 to be accurate). The book offers 10 chapters:

  1. Building Your ADF Faces Environment From the Ground Up
  2. Here you get information about how to install JDK 1.7, Oracle XE Database, JDeveloper and how to tune the environment to work best together. Finally you can download the code used throughout the book from a GIT repository.Make sure to download the code and have it ready while reading the book!

  3. Getting Started with ADF Faces and JDeveloper
  4. In this chapter you get the very basics about development of Fusion Web Applications, building an workspace, connection to the DB, creating a business service, defining page flows and pages and how to run an ADF Faces application from within JDev.

  5. Presenting Data Using ADF Faces
  6. Here we start with use cases used for presenting data. You get info on how to present single records and different master – detail use cases, using different techniques. Finally a first glance on internationalization.

  7. Using Common ADF Faces Components
  8. Here you get a walk through to the normal adf faces components for input, output, selection, loading of data as well as pop-up, code editor, menu model, links, trains and dynamic components.

  9. Beautifying the Application Layout for Great User Experience
  10. Is about page templates, skins, responsive design and flat design techniques.

  11. Enriching User Experience with Visualization Components
  12. This chapter handles maps, graphs, gauges, Gantt charts, hierarchy, sunburst and timeline components.

  13. Handling Events and Partial Page Rendering
  14. Here events (client and server), partial triggers and behavior components are introduced. Polling, Drag & Drop, Active Data Service and WebSocket are described too in this chapter.

  15. Validating and Converting Inputs
  16. Is about conversation of data, custom converters, validation (client and server) and faces messaging.

  17. Building Your Application for Reuse
  18. Picking up from chapter 2 we learn about page templates, exception handling task flow parameters, contextual events, ADFLibraries and finally Meta Data Service (MDS).

  19. Scaling your ADF Faces Application
  20. The final chapter is about performance and recommendations as well as some advances options like Content Delivery Network (CDN) and ADF caching of resources.

The cookbook uses its own db schema which looks kind of familiar, as it’s build from the well known HR schema.

While reading the book I found some recipes hard to understand for novice developers, without reading the provided code in parallel. This is because the book is all about ADF Faces but spares most about the ADF Business Components Model layer. Here the reader has to know how things are working and how to set things up.
For experienced developers some of the covered topics are nothing new, we work with them every day. The uses cases covered are mostly basic in nature and you often see links to the original documentation. Here you find the missing information which is not covered in the cookbook itself. I would have liked some more deep going information on how properties work together for some often used components like af:table or af:panelGridLayout.

I personally found it hard to understand why the author used task flows build from pages for some of the use cases just because ‘it’s easier’. One of the main advantages are task flows build of fragments. They allow reuse and help divide a task into smaller pieces. Tools like the ADF-EMG Task Flow Tester are not even mentioned. Using this tool makes it easy to run task-flows build on fragments without the need to build a JSF Page to host the region.
There are no use cases which handle region specific questions like when regions are refreshed or how regions are restarted. Transaction management and data control sharing are not covers too.

The real interesting part of the book starts with chapter 5, where page templates, skins and at least some layout techniques are introduced. Very interesting is the use case about using SAAS (Syntactically Awesome Style Sheets) and Compass to build more dynamic css files which can be used in ADF. The chapter covers Responsive Web Design and Flat Design Techniques (which are trying to minimize the design) too.

Also interesting are the samples which are build in chapter 6 for graphs, gauges, maps, pivot table, Gantt charts (calendar is missing), timeline and sunburst. However I personally find them hard to digest as they have many ingredients (steps in this case) which you have to follow. Again the model layer is pre-build for you, which means you have to find out yourself how and if there are something special in the model to cook the dish. Nevertheless, samples in this area are hard to find, and these samples do work!

The chapter about event handling and ppr is a very nice summary of how things work in ADF. Easy to understand samples are making it easy to follow the concepts. Here you find samples for ADS (Active Data Service) and WebSocket too. Nice!
Contextual events are handled in a later chapter (‘Building Your Application for Reuse’) but they are not described in great detail. It’s enough to get a first impression.

The final chapter is a nice summary of performance increasing methods and techniques which is worth reading. After reading the techniques it make sense to test them on your system!

Summary:
Novice developers learn basic ADF Faces techniques and components by building samples. Some recipes are too complicated to understand by just reading them. As the book uses its own DB schema you should have this ready, as well as the code, to work through them.