8.1. 개요

플로우 상속은 한 플로우가 다른 플로우 설정을 상속할 수 있게한다. 상속은 플로우와 스테이트 수준에서 모두 발생할 수 있다. 가장 흔한 유즈케이스는 상위 플로우로 전역적인 트랜지션과 예외 핸들러를 정의하고 하위 플로우로 그 설정을 상속받는 것이다.

상위 플로우를 찾으려면 다른 플로우들처럼 flow-registry에 추가해야 된다.

8.2. 플로우 상속은 자바 상속과 비슷한가?

상위에 정의한 요소를 하위에서 접근할 수 있다는 측면에서는 자바 상속과 플로우 상속이 비슷하다. 하지만 주요 차이점이 있다.

하위 플로우는 상위 플로우의 요소를 재정의 할 수 없다. 상위와 하위 플로우에 있는 같은 요소는 병합(merge)된다. 상위 플로우에만 있는 요소는 하위 플로우에 추가된다.

하위 플로우는 여러 상위 플로우를 상속받을 수 있다. 자바 상속은 단일 클래스로 제한된다.

8.3. 플로우 상속 타입

8.3.1. 플로우 수준 상속

플로우 수준 상속은 flow 엘리먼트의 parent 속성으로 정의한다. 이 속성은 콤마로 구분한 상속받을 플로우 식별자 목록을 명시한다. 하위 프로우는 목록에 명시된 순서대로 각각의 상위 플로우를 상속 받는다. 첫 번째 상속으로 상위 플로우에 있는 요소와 내용을 추가하고 나면 그것을 다시 하위 플로우로 간주하고 그 다음 상위 프로우를 상속 받는다. 그런식으로 계속 이어진다.

<flow parent="common-transitions, common-states">

8.3.2. 스테이트 수준 상속

스테이트 수준 상속은 플로우 수준 상속과 비슷하다. 유일한 차이점은 플로우 전체가 아니라 오직 해당 스테이트 하나만 상위로 부터 상속 받는다.

플로우 상속과 달리 오직 하나의 상위만 허용한다. 또한 상속받을 플로우 스테이트의 식별자가 반드시 정의되어 있어야 한다. 플로우와 스테이트 식별자는 #로 구분한다.

상위와 하위 스테이트는 반드시 같은 타입이어야 한다. 예를 들어 view-state는 ent-state를 상속받을 수 없다. 오직 view-state만 상속받을 수 있다.

<view-state id="child-state" parent="parent-flow#parent-view-state">
           
8.4. 추상 플로우

종종 상위 플로우는 직접 호출하지 않도록 설계한다. 그런 플로우를 실행하지 못하도록 abstract로 설정할 수 있다. 만약 추상 플로우를 실행하려고 하면 FlowBuilderException가 발생한다.

<flow abstract="true">

8.5. 상속 알고리즘

하위 플로우가 상위 플로우를 상속할 때 발생하는 기본적인 일은 상위와 하위 플로우를 병합하여 새로운 플로우를 만드는 것이다. 웹 플로우 정의 언어에는 각각의 엘리먼트에 대해 어떻게 병합할 것인가에 대한 규칙이 있다.

엘리먼트에는 두 종류가 있다. 병합 가능한 것(mergeable)과 병합이 가능하지 않은 것(non-mergeable이 있다. 병합가능한 엘리먼트는 만약 엘리먼트가 같다면 병합을 시도한다. 병합이 가능하지 않은 엘리먼트는 항상 최종 플로우에 직접 포함된다. 병합 과정 중에 수정하지 않는다.

노트
상위 플로우에있는 외부 리소스 경로는 절대 경로여야 한다. 상대 경로는 두 플로우를 병합할 때 상위 플로우와 하위 플로우가 위치한 디렉토리가 다르면 깨질 수 있다. 일반 병합하면, 상위 플로우에 있던 모든 상대 경로는 하위 플로우 기준으로 바뀐다.

8.5.1. 병합 가능한 엘리먼트

만약 같은 타입의 엘리먼트고 입력한 속성이 같다면 상위 엘리먼트의 내용을 하위 엘리먼트로 병합한다. 병합 알고리즘은 계속해서 병합하는 상위와 하위의 서브 엘리먼트를 각각 병합한다. 그렇지 않으면 상위 플로우의 엘리먼트를 하위 플로우에 새로운 엘리먼트로 추가한다.

대부분의 경우 상위 프로우릐 엘리먼트가 하위 플로우 엘리먼트에 추가된다. 이 규칙에 예외로는 시작할 때 추가 될 액션 엘리먼트(evaluate, render, set)가 있다. 상위 액션의 결과를 하위 액션 결과로 사용하게 한다.

병합이 가능한 엘리먼트는 다음과 같다.

  • action-state: id
  • attribute: name
  • decision-state: id
  • end-state: id
  • flow: 항상 병합
  • if: test
  • on-end: 항상 병합
  • on-entry: 항상 병합
  • on-exit: 항상 병합
  • on-render: 항상 병합
  • on-start: 항상 병합
  • input: name
  • output: name
  • secured: attributes
  • subflow-state: id
  • transition: on and on-exception
  • view-state: id

8.5.2. 병합 할 수 없는 엘리먼트

병합할 수 없는 엘리먼트는 다음과 같다

  • bean-import
  • evaluate
  • exception-handler
  • persistence-context
  • render
  • set
  • var