ADF Task Flow: Managed bean scopes for page fragments

Introduction

When we work with ADF Task Flows and need to implement some flow specific business logic or store some information connected with the flow, we usually use pageFlowScope managed beans. And when we need to service view activities of the flow (pages or page fragments) we use shorter scopes for such managed beans. The common practice is to use requestScope, backingBeanScope and viewScope scopes for pages/fragments backing beans. In this post I’m going to play with these three options and discover the differences in the behavior of fragment based Task Flow.

Let’s say I have some simple task flow template task-flow-template.xml:

   
    <managed-bean id="__5">
      <managed-bean-name id="__3">viewBean</managed-bean-name>
      <managed-bean-class id="__2">com.cs.blog.ViewBean</managed-bean-class>
      <managed-bean-scope id="__4">request</managed-bean-scope>
    </managed-bean>
    <managed-bean id="__15">
      <managed-bean-name id="__13">flowBean</managed-bean-name>
      <managed-bean-class id="__12">com.cs.blog.FlowBean</managed-bean-class>
      <managed-bean-scope id="__14">pageFlow</managed-bean-scope>
    </managed-bean>

    <view id="MainView">
      <page>/MainView.jsff</page>
    </view>
    

It has one view activity MainView and two backing beans. The flowBean has pageFlow scope and is responsible to store flow information. The viewBean has request scope (we will play with that) and it services the ManView view activity.

The flowBean has the following method returning the tittle of the task flow:

    public String getFlowTitle() {
        return null;
     }   

The viewBean has some string field testString to store input value:

    protected String testString;
    
    public void setTestString(String testString) {
        this.testString = testString;
    }

    public String getTestString() {
        return testString;
    }

The MainView shows the task flow’s title and has an inputText for the testString. It looks like this:

We also have two task flows built on the task-flow-template – first-flow-definition and second-flow-definition. They have overridden managed beans.

For the first-flow-definition:

    <managed-bean id="__5">
      <managed-bean-name id="__3">viewBean</managed-bean-name>
      <managed-bean-class id="__21">com.cs.blog.FirstViewBean</managed-bean-class>
      <managed-bean-scope id="__4">request</managed-bean-scope>
    </managed-bean>    
    
    <managed-bean id="__15">
      <managed-bean-name id="__13">flowBean</managed-bean-name>
      <managed-bean-class id="__12">com.cs.blog.FirstFlowBean</managed-bean-class>
      <managed-bean-scope id="__14">pageFlow</managed-bean-scope>
    </managed-bean>
 
public class FirstFlowBean extends FlowBean {
    public FirstFlowBean() {
        super();
    }
    
    public String getFlowTitle() {
        return "FirstFlow";
     }   
   
}
public class FirstViewBean extends ViewBean {
    public FirstViewBean() {
        super();
        
    }
    
    @PostConstruct
    public void init() {
        testString = "FirstFlow";  
    }
}

So the title and default value for testString is “FirstFlow”.

For the second-flow-definition:

    <managed-bean id="__5">
      <managed-bean-name id="__3">viewBean</managed-bean-name>
      <managed-bean-class id="__21">com.cs.blog.SecondViewBean</managed-bean-class>
      <managed-bean-scope id="__4">request</managed-bean-scope>
    </managed-bean>    
    
    <managed-bean id="__15">
      <managed-bean-name id="__13">flowBean</managed-bean-name>
      <managed-bean-class id="__12">com.cs.blog.SecondFlowBean</managed-bean-class>
      <managed-bean-scope id="__14">pageFlow</managed-bean-scope>
    </managed-bean>
public class SecondFlowBean extends FlowBean {
    public SecondfFowBean() {
        super();
    }
    
    public String getFlowTitle() {
        return "SecondFlow";
     }   
    
}
public class SecondViewBean extends ViewBean {
    public SecondViewBean() {
        super();
       
    }
   
    @PostConstruct
    public void init() {
        testString = "SecondFlow"; 
    }
   
}

So the title and default value for testString is “SecondFlow”.

Ok. It’s time to experiment. Let’s put on our page two regions with first-flow-definition and second-flow-definition task flows:

              
<af:region value="#{bindings.firstflowdefinition1.regionModel}" id="r1"/>
<af:separator id="s1"/>           
<af:region value="#{bindings.secondflowdefinition1.regionModel}" id="r2" />

requestScope

Leaving the scope for the viewBean as requestScope we will get the following result:

In the SecondFlow we see the testString from the FirstViewBean instance. We can have only one instance of the requestScope bean per request. The viewBean was created for the FirstFlow task flow and the same instance was used again for the SecondFlow.

backingBeanScope
 

Somebody could recommend to use backingBeanScope for the viewBean instead of requestScope. The backingBeanScope is commonly used to manage regions and declarative components. It has the same length of life as the requestScope but for different instances of regions/declarative components you will have separate instances of backingBean scoped managed beans. In our case we have two different regions, so let’s try:

And, Yes, the backingBeanScope has fixed the problem. We have two instances of the viewBean – for the regions r1 and r2.

But let’s make the first-flow-definition task flow a bit more complicated:

Now we can call child task flow (of the same definition) from the MainView. And let’s repeat the experiment. On the initial rendering:

 

So far, so good. Let’s input something in the input text of the FirstFlow and press “call child task flow”:

Oooops! We have only one instance of the viewBean for the region r1 during the request. So, value “FirstFlow111111″ entered in the parent task flow was rendered again in the child task flow.

viewScope
 
And now let’s change the viewBean’s scope to the viewScope and have the same experiment. On the initial rendering:

 

Ok. Inputting the same garbage in the inputText:

And pressing the “call child task flow”:

And everything is ok. We have not only separate viewScope beans instances for different viewport IDs (for different regions and task flow instances), but additionally the controller is resetting the viewScope during the navigation process. But the cheese is not free. You have to pay by memory. If requestScope or backingBeanScope live not longer than the request, viewScope lives in memory until the viewport ID is changed. Perhaps in my further posts I will show how to manage the issue with the backingBeanScope.
So, when you choose the appropriate scope for your fragment managed beans, consider how the task flow is going to be used. Probably, in order to get really high reusable task flow, using the viewScope is the best approach for fragment beans.

That’s it!

Reference: Managed bean scopes for page fragments in ADF Task Flow from our JCG partner Eugene Fedorenko at the ADF Practice blog.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

Leave a Reply


8 + two =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books