JDeveloper: Task Flow with optional Parameters

In one of my current projects, I came across a wired problem concerning a task flow which uses parameters to configure the flow. To make it simple to understand the problem I made up a fictive use case.

Use Case

This is not a real use case, but an abbreviation of it just to show the problem and how to resolve it. It might not make sense in real life, but it allows to show the problem.

We like to see a form to enter some data. One of the fields the user can enter should be used to select a specific layout of the following pages. Ony Layout should be horizontal and one should be vertical.

The layout should allow showing a title with a number, a text part, and a footer part. Each of the parts is optional, only the layout must be specified.

The flow can be used at different points in different flows in the application.

Implementation

The implementation is easy. We build a task flow, build with pages, and add 5 parameters to it. This task flow looks like this:

In a router component, we check the required parameter to decide which layout to use. The ‘none’ page is used if the parameter is not ‘v’ or ‘h’.

For the layout pages, which implement the layout part, I used a af:panelGridLayout with the right number of rows and columns. Here is the vertical.jsf page

Or the source view

The other pages can be found in the sample which was built using JDeveloper 12.2.1.3. You can download the sample using the link at the end of the blog.

Now that we have the reusable task flow we need another task flow (adfc-config.xml in this case) to show how to use the use of the task flow.

We see an index page which calls the task flow using three different navigations (toPageNoParam, toPageAllParam and toPageTextOnly). The difference between the navigations are the parameters set to the task flows.

Here they are

Running the application we get the following output after filling in the form on the index page

WAIT, this doesn’t look right. The page with text only parameters displays the text in the footer section instead of the text section. If we look at the parameters defined for this task flow call we see

Yes, we added the value to the wrong parameter, ‘footer’ instead of ‘text’!

Easy change, we copy move it over to the ‘text’ parameter using copy and paste:

And we get

Great, this looks like it should be.

Problem(s)

WAIT again, in the log window we now get an error message

<oracle.adf.model> <ValueMappingXmlImpl> <parse> 
   <ADFc: /WEB-INF/adfc-config.xml: Failed to parse element input-parameter: null value found for value.>

Why’s that?

If you look closely at the parameters, you’ll notice, that the ‘footer’ value is empty, whereas the other not set values showing a ‘-’. So we add the ‘-’ to the footer parameter:

To get this output running the app:

The error message in the log window is gone 🙂

Hm, but now we see the ‘-’ for the footer value. The value for the ‘title’ parameter looks identical to the parameter ‘footer’. However, we don’t see the ‘-’ for the ‘title’ in GUI.

Solution

Looking at the XML of the task flow call shows:

Now the problem is, that JDeveloper shows a ‘-’ for a parameter which is not set in the XML representation, meaning that the parameter is not in the XML structure at all!

The ‘-’ we typed into the ‘footer’ parameter is visible as value for the parameter and thus it printed when running the application.

The final solution is to remove the ‘footer’ parameter from the XML structure:

This will get us the following display in JDeveloper

The resulting running page now looks like

And we don’t see the error message in the log.

Sample Download

You can download the final application from GitHub BlogTaskFlowParameter. The sample was built using JDeveloper 12.2.1.3.0 and doesn’t need a DB connection.

Advertisements

JDeveloper 11.1.1.5.0 : Use Router to Create New Row or Edit Existing

Based on a question on the OTN ADF forum I wrote a small sample to show how to use a router in a bounded task flow to either edit an existing row, or create a new row and present it to enter data.

Use Case
Based on a query which returns either zero or one row an edit form should should be presented to the user. This form show the data from the row found, or an empty form to allow creation of a new row.

Implementation
The sample workspace, which you can download from the ADF Samples webside using the link at the end of this post, uses a very simple model. It contains only one view object, based of the LOCATIONS table of the HR schema.
The view object has one custom method implemented which search for a location record by an id. This method is used as query which returns either one row (if the location is found) or no row (if the location is not found).
The UI is build with one page which has a splitter component. On the left facet we find an simple form which we use to input the location id to search for and a button to execute the query. To allow to save or cancel the actions we add a rollback and a commit button. On the second facet we see a region which shoes the panelForm to either edit the existing record or to enter data into a new created record.
The image below shows the page layout.

General page layout

General page layout

Running

The next image shows the running application with a location id found

Running application with Location Id found

Running application with Location Id found

and then with a location id not found

Location ID not found

Location ID not found

You clearly see the empty from to enter new row data.

Now, to implement this the first splitter facet has a button to executes the query (find location by id) with the id given in the inputText. The region on the second splitter facet refreshes itself as we set the ‘Refresh’ property to ‘ifNeeded’. To make this work we need to change an input parameter to the region. This is done by binding the input parameter of the region to the inputText component for the location id.

Setup of input parameter of the region

Setup of input parameter of the region

So whenever the input parameter changes the region gets restarted. this effect we use in the bounded task flow to check if we have to create a new row and thus show a empty form, or to just edit an existing row. For this the bounded task flow uses a router component as start activity. This router checks if the iterator of the locations view object contains zero rows or more.

Bounded task flow

Bounded task flow

The router uses the estimatedRowCount of the underlying view object in an expression to check the number of rows:

EL to check if iterator has zero rows

EL to check if iterator has zero rows

The router navigates to the ‘insert’ case if the EL evaluated to true, to the ‘edit’ case otherwise. That concludes the use case.

You can down load the sample work space from ADF Samples Repository. The sample was build using JDeveloper 11.1.1.5.0 but should work using 11.1.1.6.0 and 11.1.2.x too. It uses the HR schema and you need to correct the db credentials to run the sample.