Core ADF11: UIShell with Dynamic Tabs

Last update on 28-aug-2013 Sample added for JDeveloper 12.1.2, see bottom of post.

In this old post in the Core ADF11 series, I explained the various options you have in designing the page and taskflow structure. The preferred approach in my opinion that maximizes flexibility and reusability, is to build the application using bounded taskflows with page fragments. You then have various ways to disclose these task flows to the user. You can use a dynamic region that displays the taskflow, as described in this post. You can also go for a more advanced user interface pattern that provides multi-tasking capabilities to the end user by dynamically adding tabs that represent independent tasks for the end user. This patterns is described in more detail here and covers more than only the dynamic tabs. Oracle provides a sample implementation named "Oracle Dynamic Tabs Page Template" of this user interface pattern as an extension to JDeveloper  that can be installed through the JDeveloper Help -> Check for Updates option.  While this implementation might be sufficient in your case, I discovered the need for additional related functionality not provided out-of-the-box by this extension, as well as the need for easier customization options. As I started to implement this pattern at various customers I added more and more functionality to my implementation of this pattern that started off with a more or less one-to-one copy from the Oracle extension implementation. The end result is quite different from the Oracle extension, also because I optimized the implementation for JDeveloper 11.1.2, leveraging the new multiregion binding. For my presentation of this topic at Oracle OpenWorld 2011 I created a showcase application that includes all the code and templates for the dynamic tabs implementation and illustrates all the functionalities my customers asked for, including:

  • Open new tabs in various ways: Using a menu, using a global quick search, from within another tab, and conditionally based on a tab unique identifier that is used to check whether there is already a tab open with the same UID.

  • Close a tab in various ways: using the close icon on the tab, using a close tab button inside the tab region, or auto-closing a tab when the user finished the task.
  • Transaction handling: Each tab should have an independent transaction, a tab needs to be marked dirty with a visual indicator indicating the dirty tab state, and a warning should be shown when the user tries to close a tab with pending changes.
  • Miscelleanous requirements: Update browser window/tab title based on currently selected tab, initially display tabs, prevent tabs from being closed automatically, set maximum number of tabs the user is allowed to open, and update of the tab label based on the current data shown in the region.

If you have similar requirements, then this sample application might be useful to you. You can download the application below, feel free to copy and paste the infrastructure classes, templates and declarative components to your own application. For an explanation of the implementation, see the slides of my OOW presentation.

Downloads: 

Update 13-nov-2012: The implementation in the sample applications has been improved. It is no longer needed to define the managed bean for a tab that is initially displayed in view scope rather than request scope. By improving this implementation of initially displayed tabs, the following issues have been fixed:

  • Closing and re-opening an initially displayed tab caused an NPE (11.1.1.x only)
  • It was not possible to launch another tab from within an initially displayed tab

Update 28-aug-2013: Dynamic Tabs Sample For JDeveloper 12.1.2

Initially, I had problems getting the sample to work in JDev 12.1.2. I logged the following bugs against 12.1.2 that could be reproduced when opening  the 11.1.2 sample in 12.1.2:

  • Bug 17158398 - COMMAND COMPONENTS DO NOT WORK WHEN OPENING REGION IN DYNAMIC TAB
  • Bug 17156672 - UI NOT RENDERED CORRECTLY DUE TO CONTEXT PARAM DEFAULT_DIMENSION
  • Bug 17156560 - JAVA.LANG.ILLEGALSTATEEXCEPTION: COULD NOT FIND COMPONENT TO STREAM
  • Bug 17158597 - UPDATES ARE LOST WHEN DEFINING REGIONCONTROLLER IN PAGEDEF CONTROLLERCLASS PROP

Product development has investigated some of these bugs, and this is the result:

  • The behavior described in bug 17156560 was caused by the fixed value specified for the id property in the af:region tag. Unlike JSP, facelets does not ensure uniqueness when stamping out multiple components, in this case multiple regions inside the af:forEach loop. By removing the id property (facelets will then auto-generate a unique id), or making it unique using an EL expression like id="reg_${vs.index}"  the issue was resolved. See this blog post from Duncan Mills for more info.
  • After applying the fix for bug  17156560 , the behavior reported in bugs 17158398 and 17158597 was no longer seen. These bugs are now closed as "not a bug".
  • The work around for bug 17156672 is simple. The top-level af:decorativeBox in the page template should have the dimensionsFrom property set to "parent" when the DEFAULT_DIMENSIONS context param is set to 'auto' in web.xml. However, since JDeveloper should ensure upwards compatibility, it should never automatically add the DEFAULT_DIMENSIONS web.xml context param to an existing application. So, the bug has been changed to a design-time bug to prevent this from happening. 
With these fixes, the 12.1.2 sample is now working correctly and can be downloaded here.

Comments:

Thanks Steve. Your building reusable task flow session was great.

Zeeshan

Posted by Zeeshan Biag on October 13, 2011 at 07:11 AM PDT #

Hi Steve,

Very nice post. I downloaded and deployed the sample application for JDeveloper 11.1.2 successfully.
I have a problem, databound elements work fine in task flows but not in the template. For instance, I drag and drop DepartamentName in DepartamentsView1 from the data control to the template, but when I run the application, it doesn't show any data.

Posted by Fredy Gil on November 08, 2011 at 01:29 AM PST #

Hi Steve,

Just downloaded sample app JDev 11.1.1.4, and wondering, how did you create the file
davelaar.demo.ui.view.pageDefs.DynTabsTemplatePageDef.xml ?

I can see, this is a 'path' atrribute value in the UIShellPageDef :
<page id="dynTabsTemplateBinding"
path="davelaar.demo.ui.view.pageDefs.DynTabsTemplatePageDef"../>

but have no idea how did you create that file ?

And just anothe question :

in the DataBindings.cpx, there is:

<page id="DynTabsTemplatePageDef"
path="davelaar.demo.ui.view.pageDefs.DynTabsTemplatePageDef"/>

Did you manually added this entry, and why he should be there ?

Thanks in advance,...

Posted by guest on April 01, 2012 at 09:18 PM PDT #

I created the file DynTabsTemplatePageDef manually. The dynTabsTemplateBinding <page> entry in DataBindings.cpx is not needed, you can remove it and it will still work.

Steven.

Posted by guest on April 02, 2012 at 04:24 AM PDT #

Hi Steven,

Suppose we have two opened tabs, and in the one of them, we have mandatory input fields. In such one situation, we cannot switch between tabs, because mandatory fields validation.

Is there a way to switch to another tab ?
As I can see (correct me if I am wrong), in the DynamicTabs.jsff declarative component (11.1.1.4), there is af:commandNavigationItem with immediate="false". What happens if I change the value to true ?
Most important - will it have some other (non-desirable) consequences?

Posted by guest on April 22, 2012 at 03:25 AM PDT #

It is a functional choice to set immediate to true or not:

- true: you can switch tabs while required fields are empty, drawback
is that tab is only marked dirty after a request has been sent to the server so if you change tabs while changes have not been sent to the
server yet, the tab you leave is not marked dirty. (JSF Model update phase is not executed when immediate=true)

- false: if you switch tabs, the latest change is first processed in JSF Model Update phase, so the tab is marked dirty. Drawback is that you cannot switch tabs when validation errors occur.

Steven.

Posted by guest on April 22, 2012 at 04:08 AM PDT #

Hi,

Did you ever tried to raise Contextual event from embedded RichPopup containing region (bounded task flow) ?
Raising such one event and registering consumers simply hides popup.
Do you have any one working example regarding this stuff ?

Posted by guest on April 23, 2012 at 09:20 AM PDT #

No, I try to avoid using contextual events, and so far I always found an alternative technique that is easier/faster. So, no working sample, sorry.

Posted by guest on April 25, 2012 at 11:03 AM PDT #

Hi Steven,

we changed our implementation with the new dynamic multi region concpet and working fine for most of the scenario's.

In some scenario's where we are opening the two tabs in a single request is giving the second tab with blank. second region itself is not loading.

In you sample you have mentione two scenario like panelTabed and CommandNavigation concepts. In those we are using the PanelTabed and ShowDetailItem. But in this we have done a small change like separating the ShowdetailItem and region in two diffrent for loops. is this will give any issue.

BB

Posted by guest on October 17, 2012 at 09:54 PM PDT #

BB,

If you can send me a testcase that reproduces your issue I can have a look. I'll send you an e-mail, so you can reply with testcase attached.

Steven.

Posted by guest on October 19, 2012 at 03:08 AM PDT #

Hi Steven.

Are there plans to support the new UI Shell 2.0 Template? The new version seems to be much more richer and more polished than the 1.0 Template.

Thanks,

BradW

Posted by BradW on January 09, 2013 at 10:07 AM PST #

Hi, thanks for this valuable information.
Unfortunately, I have problems with your 11.1.2 version with my
JDEV 11.1.2.3. JDEV is not accepting a componentRef Tag inside the an ui:composition tag in your DynamicTabs.jsff and DynamicTabsNavPane.jsff facelet files.
Can you provide some help here?

Thanks in advance
Stephan

Posted by Stephan on March 02, 2013 at 03:10 AM PST #

Hi Steven,

Have you ever tried to run two instances of the same TF, one in the dynamic tab, and second one as a static region inside af:popup, from the another dynamic tab (TF) ? I have strange problem regarding showing jsff fragment. Can you please take a look at :

https://forums.oracle.com/forums/thread.jspa?forumID=83&threadID=2506119

Posted by guest on March 03, 2013 at 10:23 PM PST #

Does the TF shown in both the tab and the popup has UI components with the binding property bound to a managed bean not in backing bean scope?
That might cause rendering problems in this use case.

Steven.

Posted by guest on March 04, 2013 at 12:33 AM PST #

Stephan,

Yes, JDev complains about the componentDef tag but the app runs fine.
Anyway, you can remove the enclosing ui:composition tag and move the namespace declarations to the componentDef tag:

<af:componentDef xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
xmlns:f="http://java.sun.com/jsf/core" var="attrs">

Steven.

Posted by guest on March 04, 2013 at 12:45 AM PST #

@"Does the TF shown in both the tab and the popup..."

Steven,

Excellent !
That was the problem !
I had property bounded to backing bean in the request scope, not in the backingBeanScope.
Is this normal behavior? Can you elaborate more on that ?

Thanks a lot !

Posted by guest on March 04, 2013 at 02:43 AM PST #

Yes, this is expected behavior.
When rendering the page, the JSF UI tree also contains the UI components of the TF page under the hidden dynamic tab. So, a UI component in this TF that binds to a request-scoped bean actually occurs twice in the UI tree (the second time inside the popup that renders the same TF). However, there is only one instance of the request-scoped bean, while two components are trying to bind to it. That is not supported and therefore rendering fails.
The use case of using one TF multiple times in a page (hidden or not) is the only reason for the existence of this backingBean scope.

Posted by guest on March 04, 2013 at 03:07 AM PST #

Steven, thanks for the response. Great, it works fine.

Just trying to extend your solution to a two level navigation approach.

Is is usally necessary to clear the pageFlowScope on my own or will do ADF the work?

Good day.

Stephan

Posted by guest on March 04, 2013 at 09:11 PM PST #

If you return from or abandon a task flow, the corresponding pageFlowScope will be cleared automatically.

Posted by guest on March 06, 2013 at 12:07 AM PST #

Hi Steven,

Do you have a plan to support new JDeveloper 12c too ?

Posted by guest on July 31, 2013 at 12:33 AM PDT #

Yes, but there are some serious issues with this sample in JDEveloper 12c. I have logged a number of bugs against ADF 12c, see the update at the bottom of the post

Posted by guest on August 09, 2013 at 01:53 AM PDT #

https://blogs.oracle.com/groundside/entry/foreach_and_facelets_a_bugfarm

Posted by Duncan on August 28, 2013 at 02:15 AM PDT #

Thanks for the link Duncan, missed that blog post!
What I don't understand though is why the sample worked fine in 11.1.2 which is also using facelets.

Steven.

Posted by guest on August 28, 2013 at 02:20 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Java EE Consultants - JHeadstart, ADF, JSF

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today