JDeveloper & ADF: Carefully Select the Data Control Scope of Bounded Task Flows

A customer asked me to look into an error which showed up in one of their applications. Without going into the details of real use case I like to bring this issue to your attention as it might happen to you too.

Use Case
I set up a mock use case to show the problem as this: A page (.jspx or .jsf) includes one (or more) other task flows as a region. The base page retrieves some data using a method call exposed in the data control, which should be displayed in the region for information purpose.

Implementation
If the task flows share their data controls this is not a big deal to implement this. You can download the sample using the link provided at the end of this blog. The sample uses the HR schema and was build using JDev 11.1.1.5.0 and was additional tested with JDev 11.1.1.1.6.0 and JDev 11.1.2.2.0, which show the same behavior.

On the base page I set up an inputText which I use to pass a parameter to the method (callMeTest) which retrieves some info from the application module. The callMeTest method simply returns the passed parameter together with a ‘nice’ message:

    public String callMeTest(String name) {
        _logger.info("Called with: "+name);
        return "Call me Test "+name;
    }

The return value is then displayed on the base page at the bottom under the button and should be displayed in the region, under the table, too. The sample just uses one region. When no value is present ‘****’ is used as parameter. The image below shows the application after starting it.

Start Screen

Start Screen

After entering a value into the inputText field below the table and hitting the ‘callMeTest’ button underneath it, you see that the return value is displayed below the button on the base page and under the table inside the region. If the button is hit with another value, both values are updated.

After entering a value and hitting the button

After entering a value and hitting the button

Nothing unusual so far. Now, for some unknown reason, after a change to another part the application, that functionality did not work any longer. The value in the base page still updates after the call to the method, but the value in the region stopped updating.

Screen after next deployment

Screen after next deployment

The reason for this behavior is a simple one. A look into the task flow properties of the region, revealed that the checkmark for the ‘Share data controls with calling task flow’ was not set, meaning that the task flow get its own data control frame. The result is that the method outcome from the base page is not visible in the region.

TaskFlow properties (1)

TaskFlow properties (1)

The question was how did this happen, when the change which results in the new deployment had nothing to do with this part of the application?

Analysis
It turned out, that when you create a new bounded task flow this property value is set to ‘default’. This is shown in the ‘Overview’ of the task flow as bluish shade in the check box. No checkmark is set and a look into the source reveals that the whole section

    <data-control-scope>
      <....../>
    </data-control-scope>

is just missing from the XML file.

TaskFlow after creation

TaskFlow after creation

Once you click on this property in the property editor you can just switch between ‘isolated’ or ‘shared’.

TaskFlow properties (2)

TaskFlow properties (2)

The only possible way to get the bluish shade back is to delete the section in the source view of the task flow.

TaskFlow properties in 'Source Mode'

TaskFlow properties in ‘Source Mode’

So this checkbox has three states ‘bluish’, ‘isolated’, and ‘shared’. Well, there is a forth state which you get if you open the property editor in source mode and select ‘default’. The following table shown all states together with their meaning:

State  Meaning
Bluish  Shared
Check marked  Shared
Unchecked not bluish  Isolated
Data-control-scope empty  Isolated

While the application works according to the meaning of the flag, I find it not intuitive how JDev handles this setting. The programmer who made the change to the application clicked this property, but meant to do so on a different task flow. So he unchecked the ‘Share data controls with calling task flow’ property as he remembered that it was not set before.

Recommendation
My advise is to set the flag whenever you create a task flow so you know which share mode the task flow uses. This avoids errors like the one described in this blog.

UPDATE
In the meantime Chris Muir raised the issue with the UX specialists (Oracle intern) and Bug 14390576 has been raised for this issue.
Thank you Chris!

The sample uses the HR schema and was build with JDeveloper 11.1.1.5.0, tested with 11.1.1.6.0 and 11.1.2.2.0 . You can download the sample work space form ADF Samples: Source Code

JDeveloper ADF af:query Component: How to Toggle Display Modes

ADF af:query component comes with many functions and layout possibilities. This post describes how to toggle between the ‘basic’ and the ‘advanced’ display mode from java code.
Fist lets see the difference between ‘basic’ and ‘advanced’ mode.

af:query in 'basic' mode

af:query in ‘basic’ mode

and the same component switched to ‘advanced’ mode:

af:query in 'advanced' mode

af:query in ‘advanced’ mode

You see the difference is that the user can change the conjunction used for each attribute. There is a button available on the af:query component which you can click to toggle the mode. However there are use cases where you need to do this from inside a java bean. When you check the properties available for hte component you’ll notice, that you can change the position and the visibility of the button

Properties to Change the Toggle Button

Properties to Change the Toggle Button

So the user is able to change the two modes by clicking the button. The problem is that you can’t start in advanced mode. Only when you create your own ViewCriteria in the ViewObject you can switch to the ‘UI Hints’ tab and select how you like to start the query region:

Select Display Mode for ViewCriteria

Select Display Mode for ViewCriteria

So you either create your own ViewCriteria and select to start in ‘advanced’ or you need to do it from a java bean as described below. The sample application is build using JDeveloper 11.1.1.5.0 and uses the HR schema. The link to download the sample can be found at the end of the post.

Use Case: lets assume we want to show an af:query panel in advanced mode to only a specific user named ‘King’. All other users should only see the ‘basic’ af:query panel. For this we use an inputText on the left side of a af:panelSplitter which is used to input the user name. When the value of this inputText changes we check if the name is ‘King’ and switch the af:query to ‘advanced’ mode, otherwise we set it to ‘basic’.

Implementation:
To implement the use case we have to do two things. First we need an inputText to enter the user name. In reality this name should be get from a security context. Here it’s enough to store the value entered by the user to a binding attribute, set the inputText component to autoSubmit and implement a valuechangeListener where we put the logic to switch the mode of the af:query to ‘advanced’ or to ‘basic’.
We start with setting up a variable in the executable section of the pageDef:

Create a Variable in Executable Section of pageDef

Create a Variable in Executable Section of pageDef

Name the Variable

Name the Variable

Create an Attribute Binding for the Variable

Create an Attribute Binding for the Variable

Create Attribute Binding 2

Create Attribute Binding 2

Create Attribute Binding 3

Create Attribute Binding 3

Create Attribute Binding 4

Create Attribute Binding 4

Create Attribute Binding 5

Create Attribute Binding 5

Now after the attribute binding is in place we can set up the inputText for the name and set the value property to the created binding attribute, set the autoSubmit property and the valueChangeListener to a bean method

Set value Property

Set value Property

Set autoSubmit and valueChangeListener Properties

Set autoSubmit and valueChangeListener Properties

The valueChangeListener we bind to a bean in request scope (BTAFQBean) and implement the method ‘nameChangeListener’ as

    public void nameChangeListener(ValueChangeEvent valueChangeEvent) {
        // get the queryPanel which is bound to the bean property
        RichQuery qp = getQueryPanel();
        Object newValue = valueChangeEvent.getNewValue();
        String nameNew = (String)newValue;
        Object oldValue = valueChangeEvent.getOldValue();
        String nameOld = (String)oldValue;
        // if old value != King and new value == king  set advanced
        if ("King".equalsIgnoreCase(nameNew) &&
            !("King".equalsIgnoreCase(nameOld))) {
            // switch queryPanel to advanced mode
            qp.getValue().changeMode(QueryDescriptor.QueryMode.ADVANCED);
            //ppr the query panel
            AdfFacesContext.getCurrentInstance().addPartialTarget(qp);
        } 
        // if New value != King and old value == kng switch to basic
        else if ("King".equalsIgnoreCase(nameOld) &&
                   !("King".equalsIgnoreCase(nameNew))) {
            // switch queryPanel to basic mode
            qp.getValue().changeMode(QueryDescriptor.QueryMode.BASIC);
            //ppr the query panel
            AdfFacesContext.getCurrentInstance().addPartialTarget(qp);
        }
    }

The af:queryPanel is bound to a bean property in the BTAFQBean for convenience. This makes it easy to get the component and sent it a PPR from java code. The essential part of the code is located in line 12 and 20. The method to switch the mode is hidden in the query descriptor which you get as the value of the af:query component. gp.getValue() get us the QueryDescriptor which exposes the changeMode() method. The parameter is a constant, either QueryDescriptor.QueryMode.BASIC or QueryDescriptor.QueryMode.ADVANCED.

When you run the application and enter e.g. ‘peter’ into the inputText field and leave the field (or hit return) the query panel looks like

Query Panel in BASIC Mode

Query Panel in BASIC Mode

Now type ‘king’ into the name field and leave the field. As a result you see

Query Panel in ADVANCED Mode

Query Panel in ADVANCED Mode

You can download the sample workspace, build with JDev 11.1.2.1.0 and depending on hte HR db schema, from here: http://java.net/projects/smuenchadf/sources/samples/content/BlogToggleAFQuery_V1.zip