Статьи

Поток задач ADF: управляемые области компонентов для фрагментов страницы

Введение

Когда мы работаем с потоками задач ADF и нам нужно реализовать некоторую бизнес-логику для конкретного потока или сохранить некоторую информацию, связанную с потоком, мы обычно используем управляемые bean- объекты pageFlowScope . И когда нам нужно обслуживать действия просмотра потока (страниц или фрагментов страниц), мы используем более короткие области для таких управляемых bean-компонентов. Обычной практикой является использование областей requestScope , backingBeanScope и viewScope для бинов- компонентов страниц / фрагментов. В этом посте я собираюсь поиграть с этими тремя вариантами и обнаружить различия в поведении фрагментов на основе Task Flow.

Допустим, у меня есть простой шаблон потока задач task-flow-template.xml:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<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>

Он имеет один вид активности MainView и два поддерживающих бина. FlowBean имеет область действия pageFlow и отвечает за хранение информации о потоке. ViewBean имеет область запроса (мы будем играть с этим), и он обслуживает активность представления ManView.

У flowBean есть следующий метод, возвращающий заголовок потока задач:

1
2
3
public String getFlowTitle() {
    return null;
 }  

ViewBean имеет некоторое строковое поле testString для хранения входного значения:

1
2
3
4
5
6
7
8
9
protected String testString;
 
public void setTestString(String testString) {
    this.testString = testString;
}
 
public String getTestString() {
    return testString;
}

MainView показывает заголовок потока задач и имеет inputText для testString . Это выглядит так:

У нас также есть два потока задач, построенных на шаблоне потока задач — определение первого потока и определение второго потока. Они переопределили управляемые бобы.

Для определения первого потока :

01
02
03
04
05
06
07
08
09
10
11
12
<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>
01
02
03
04
05
06
07
08
09
10
public class FirstFlowBean extends FlowBean {
    public FirstFlowBean() {
        super();
    }
     
    public String getFlowTitle() {
        return "FirstFlow";
     }  
    
}
01
02
03
04
05
06
07
08
09
10
11
public class FirstViewBean extends ViewBean {
    public FirstViewBean() {
        super();
         
    }
     
    @PostConstruct
    public void init() {
        testString = "FirstFlow"
    }
}

Таким образом, заголовок и значение по умолчанию для testString — «FirstFlow».

Для определения второго потока :

01
02
03
04
05
06
07
08
09
10
11
<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>
01
02
03
04
05
06
07
08
09
10
public class SecondFlowBean extends FlowBean {
    public SecondfFowBean() {
        super();
    }
     
    public String getFlowTitle() {
        return "SecondFlow";
     }  
     
}
01
02
03
04
05
06
07
08
09
10
11
12
public class SecondViewBean extends ViewBean {
    public SecondViewBean() {
        super();
        
    }
    
    @PostConstruct
    public void init() {
        testString = "SecondFlow";
    }
    
}

Таким образом, заголовок и значение по умолчанию для testString — «SecondFlow».

ОК. Время экспериментировать. Давайте разместим на нашей странице две области с потоками задач определения первого потока и определения второго потока:

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

requestScope

Оставляя область видимости для viewBean как requestScope, мы получим следующий результат:

В SecondFlow мы видим testString из экземпляра FirstViewBean. Мы можем иметь только один экземпляр bean-компонента requestScope для каждого запроса. ViewBean был создан для потока задач FirstFlow, и тот же экземпляр был снова использован для SecondFlow.

backingBeanScope
 

Кто-нибудь может порекомендовать использовать backingBeanScope для viewBean вместо requestScope. BackingBeanScope обычно используется для управления регионами и декларативными компонентами. Он имеет такой же срок службы, что и requestScope, но для разных экземпляров регионов / декларативных компонентов у вас будут отдельные экземпляры управляемых bean-компонентов beingBean. В нашем случае у нас есть два разных региона, поэтому давайте попробуем:

И, да, backingBeanScope устранил проблему. У нас есть два экземпляра viewBean — для регионов r1 и r2.

Но давайте сделаем процесс определения первого потока немного более сложным:

Теперь мы можем вызывать дочерний поток задач (того же определения) из MainView. И давайте повторим эксперимент. На начальном рендеринге:

Все идет нормально. Давайте что-нибудь введем во входной текст FirstFlow и нажмем «вызвать дочерний поток задач»:

Oooops! У нас есть только один экземпляр viewBean для региона r1 во время запроса. Таким образом, значение «FirstFlow111111», введенное в родительском потоке задач, было снова отображено в дочернем потоке задач.

viewScope
 
А теперь давайте изменим область видимости viewBean на viewScope и проведем тот же эксперимент. На начальном рендеринге:

ОК. Ввод того же мусора в inputText:

И нажав «вызовить дочерний процесс»:

И все в порядке. У нас есть не только отдельные экземпляры компонентов ViewScope для разных идентификаторов области просмотра (для разных регионов и экземпляров потока задач), но и контроллер сбрасывает viewScope в процессе навигации. Но сыр не бесплатный. Вы должны платить по памяти. Если requestScope или backingBeanScope живут не дольше, чем запрос, viewScope остается в памяти до тех пор, пока не будет изменен идентификатор области просмотра. Возможно, в моих дальнейших сообщениях я покажу, как справиться с проблемой с помощью backingBeanScope.
Итак, когда вы выбираете подходящую область действия для ваших управляемых bean-компонентов фрагмента, подумайте, как будет использоваться поток задач. Вероятно, для того, чтобы получить действительно высокий поток задач многократного использования, использование viewScope — лучший подход для фрагментированных компонентов.

Это оно!

Ссылка: управляемые области bean-компонентов для фрагментов страницы в потоке задач ADF от нашего партнера по JCG Евгения Федоренко из блога ADF Practice .