[[_system_setup]]
== System Setup

This chapter shows you how to set up the Web Flow system for use in any web environment.

[[_system_config_options]]
=== Java Configuration and the XML Namespace

Web Flow provides dedicated configuration support for both Java- and XML-based configuration.

To get started with XML based configuration, declare the `webflow` config XML namespace, as follows:

====
[source,xml]
----
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:webflow="http://www.springframework.org/schema/webflow-config"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/webflow-config
           https://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd">

    <!-- Setup Web Flow here -->

</beans>
----
====

To get started with Java configuration extend `AbstractFlowConfiguration` in an `@Configuration` class, as follows:

====
[source,java]
----
import org.springframework.context.annotation.Configuration;
import org.springframework.webflow.config.AbstractFlowConfiguration;

@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {

}
----
====

[[_system_config_basic]]
=== Basic System Configuration

The next two sections show the minimal configuration required to set up the Web Flow system in your application:

* <<_basic_setup_flow_registry>>
* <<_basic_setup_flow_executor>>

[[_basic_setup_flow_registry]]
==== Registering a `FlowRegistry`

You can register your flows in a `FlowRegistry` in XML, as follows:

====
[source,xml]
----
<webflow:flow-registry id="flowRegistry">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>
----
====

You can register your flows in a `FlowRegistry` in Java, as follows:

====
[source,java]
----
@Bean
public FlowDefinitionRegistry flowRegistry() {
    return getFlowDefinitionRegistryBuilder()
        .addFlowLocation("/WEB-INF/flows/booking/booking.xml")
        .build();
}
----
====

[[_basic_setup_flow_executor]]
==== Deploying a `FlowExecutor`

You can deploy a `FlowExecutor`, the central service for executing flows in XML, as follows:

====
[source,xml]
----

<webflow:flow-executor id="flowExecutor" />
----
====

You can deploy a `FlowExecutor`, the central service for executing flows in Java:

====
[source,java]
----

@Bean
public FlowExecutor flowExecutor() {
    return getFlowExecutorBuilder(flowRegistry()).build();
}
----
====

See the <<_spring_mvc>> and <<_spring_faces>> sections of this guide on how to integrate the Web Flow system with the MVC and JSF environment, respectively.

[[_flow_registry]]
=== `flow-registry` options

This section explores flow-registry configuration options.

[[_flow_registry_location]]
==== Specifying Flow Locations

You can use the `location` element to specify paths to flow definitions that you want to register.
By default, flows are assigned registry identifiers equal to their filenames minus the file extension, unless a registry base path is defined (see <<_flow_registry_base_path>>).

The following example specifies a flow location in XML:

====
[source,xml]
----
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
----
====

The following example specifies a flow location in Java:

====
[source,java]
----
return getFlowDefinitionRegistryBuilder()
        .addFlowLocation("/WEB-INF/flows/booking/booking.xml")
        .build();
----
====

[[_flow_registry_location_id]]
==== Assigning Custom Flow Identifiers

You can specify an ID to assign a custom registry identifier to a flow.

The following example shows how to assign custom flow identifiers in XML:

====
[source,xml]
----
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" id="bookHotel" />
----
====

The following example shows how to assign custom flow identifiers in Java:

====
[source,java]
----
return getFlowDefinitionRegistryBuilder()
        .addFlowLocation("/WEB-INF/flows/booking/booking.xml", "bookHotel")
        .build();
----
====

[[_flow_registry_location_attributes]]
==== Assigning Flow Meta-attributes

You can use the `flow-definition-attributes` element to assign custom meta-attributes to a registered flow.

The following example shows how to assign flow meta-attributes in XML:

====
[source,xml]
----
<webflow:flow-location path="/WEB-INF/flows/booking/booking.xml">
    <webflow:flow-definition-attributes>
        <webflow:attribute name="caption" value="Books a hotel" />
    </webflow:flow-definition-attributes>
</webflow:flow-location>
----
====

The following example shows how to assign flow meta-attributes in Java:

====
[source,java]
----
Map<String, Object> attrs = ... ;

return getFlowDefinitionRegistryBuilder()
        .addFlowLocation("/WEB-INF/flows/booking/booking.xml", null, attrs)
        .build();
----
====

[[_flow_registry_patterns]]
==== Registering Flows by Using a Location Pattern

You can use the `flow-location-patterns` element to register flows that match a specific resource location pattern.

The following example shows how to register a flow in XML:

====
[source,xml]
----
<webflow:flow-location-pattern value="/WEB-INF/flows/**/*-flow.xml" />
----
====

The following example shows how to register a flow in Java:

====
[source,java]
----
return getFlowDefinitionRegistryBuilder()
        .addFlowLocationPattern("/WEB-INF/flows/**/*-flow.xml")
        .build();
----
====

[[_flow_registry_base_path]]
==== Flow Location Base Path

You can use the `base-path` attribute to define a base location for all flows in the application.
All flow locations are then relative to the base path.
The base path can be a resource path (such as `/WEB-INF`) or a location on the classpath (such as `classpath:org/springframework/webflow/samples`).

The following example shows how to set the base path in XML:

====
[source,xml]
----
<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
    <webflow:flow-location path="/hotels/booking/booking.xml" />
</webflow:flow-registry>
----
====

The following example shows how to set the base path in Java:

====
[source,java]
----
return getFlowDefinitionRegistryBuilder()
        .setBasePath("/WEB-INF")
        .addFlowLocationPattern("/hotels/booking/booking.xml")
        .build();
----
====

With a base path defined, the algorithm that assigns flow identifiers changes slightly.
Flows are now  assigned registry identifiers equal to the the path segment between their base path and their file name.
For example, if a flow definition is located at `/WEB-INF/hotels/booking/booking-flow.xml` and the base path is `/WEB-INF`, the remaining path to this flow is `hotels/booking`, which becomes the flow ID.

.A directory for each flow definition
TIP: It is a best practice to package each flow definition in a unique directory.
This improves modularity, letting dependent resources be packaged with the flow definition.
It also prevents two flows from having the same identifiers when using the convention.

If no base path is not specified or if the flow definition is directly on the base path, flow ID assignment from the filename (minus the extension) is used.
For example, if a flow definition file is `booking.xml`, the flow identifier is simply `booking`.

Location patterns are particularly powerful when combined with a registry base path.
Instead of the flow identifiers becoming `*-flow`, they are based on the directory path.
The following example combines a base path with a flow location pattern in XML:

====
[source,xml]
----
<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
    <webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
----
====

The following example combines a base path with a flow location pattern in Java:

====
[source,java]
----
return getFlowDefinitionRegistryBuilder()
        .setBasePath("/WEB-INF")
        .addFlowLocationPattern("/**/*-flow.xml")
        .build();
----
====

In the preceding example, suppose you had flows located in the `/user/login`, `/user/registration`, `/hotels/booking`, and `/flights/booking` directories within `WEB-INF`.
You would end up with flow IDs of `user/login`, `user/registration`, `hotels/booking`, and `flights/booking`, respectively.

[[_flow_registry_parent]]
==== Configuring `FlowRegistry` Hierarchies

You can use the `parent` attribute to link two flow registries together in a hierarchy.
When the child registry is queried, if it cannot find the requested flow, it delegates to its parent.

The following example establishes a parent relationship for two flow registries in XML:

====
[source,xml]
----
<!-- my-system-config.xml -->
<webflow:flow-registry id="flowRegistry" parent="sharedFlowRegistry">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>

<!-- shared-config.xml -->
<webflow:flow-registry id="sharedFlowRegistry">
    <!-- Global flows shared by several applications -->
</webflow:flow-registry>
----
====

The following example establishes a parent relationship for two flow registries in Java:

====
[source,java]
----
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {

    @Autowired
    private SharedConfig sharedConfig;

    @Bean
    public FlowDefinitionRegistry flowRegistry() {
        return getFlowDefinitionRegistryBuilder()
                .setParent(this.sharedConfig.sharedFlowRegistry())
                .addFlowLocation("/WEB-INF/flows/booking/booking.xml")
                .build();
    }
}

@Configuration
public class SharedConfig extends AbstractFlowConfiguration {

    @Bean
    public FlowDefinitionRegistry sharedFlowRegistry() {
        return getFlowDefinitionRegistryBuilder()
                .addFlowLocation("/WEB-INF/flows/shared.xml")
                .build();
    }
}
----
====

[[_flow_registry_builder_services]]
==== Configuring Custom `FlowBuilder` Services

You can use the `flow-builder-services` attribute (in XML) or the `FlowBuilderServices` object (in Java) to customize the services and settings used to build flows in a flow-registry.
If no `flow-builder-services` element is specified, the default service implementations are used.
When the element is specified, you need only reference the services you want to customize.

The following example shows how to create a custom flow builder service in XML:

====
[source,xml]
----
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
    <webflow:flow-location path="/WEB-INF/flows/booking/booking.xml" />
</webflow:flow-registry>

<webflow:flow-builder-services id="flowBuilderServices" />
----
====

The following example shows how to create a custom flow builder service in Java:

====
[source,java]
----
@Bean
public FlowDefinitionRegistry flowRegistry() {
	return getFlowDefinitionRegistryBuilder(flowBuilderServices())
            .addFlowLocation("/WEB-INF/flows/booking/booking.xml")
            .build();
}

@Bean
public FlowBuilderServices flowBuilderServices() {
    return getFlowBuilderServicesBuilder().build();
}
----
====

The configurable services are the `conversion-service`, `expression-parser`, and `view-factory-creator` elements (in XML) and the `ConversionService`, `ExpressionParser`, and `ViewFactoryCreator` interfaces (in Java).
These services are configured by referencing custom beans that you must define.

The following example shows how to define the configurable services in XML:

====
[source,xml]
----
<webflow:flow-builder-services id="flowBuilderServices"
    conversion-service="conversionService"
    expression-parser="expressionParser"
    view-factory-creator="viewFactoryCreator" />

<bean id="conversionService" class="..." />
<bean id="expressionParser" class="..." />
<bean id="viewFactoryCreator" class="..." />
----
====

The following example shows how to define the configurable services in Java:

====
[source,java]
----
@Bean
public FlowBuilderServices flowBuilderServices() {
    return getFlowBuilderServicesBuilder()
            .setConversionService(conversionService())
            .setExpressionParser(expressionParser)
            .setViewFactoryCreator(mvcViewFactoryCreator())
            .build();
}

@Bean
public ConversionService conversionService() {
    // ...
}

@Bean
public ExpressionParser expressionParser() {
    // ...
}

@Bean
public ViewFactoryCreator viewFactoryCreator() {
    // ...
}
----
====

[[_builder_service_conversion]]
===== Using the Conversion Service

You can use the `conversion-service` attribute (in XML) or the `ConversionService` interface (in Java) to customize the `ConversionService` used by the Web Flow system.
Type conversion is used to convert from one type to another when required during flow execution, such as when processing request parameters, invoking actions, and so on.
Many common object types (such as numbers, classes, and enums) are supported.
However, you probably need to provide your own type conversion and formatting logic for custom data types.
See <<_view_type_conversion>> for important information on how to provide custom type conversion logic.

[[_builder_service_expression_parser]]
===== Using the Expression Parser

You can use the `expression-parser` attribute (in XML) or the `ExpressionParser` interface (in Java) to customize the `ExpressionParser` used by the Web Flow system.
The default `ExpressionParser` uses the Unified Expression Language if available on the classpath.
Otherwise, it uses the Spring Expression Language.

[[_builder_service_view_factory_creator]]
===== Using the View Factory Creator

You can use the `view-factory-creator` attribute (in XML) or the `ViewFactoryCreator` interface (in Java) to customize the `ViewFactoryCreator` used by the Web Flow system.
The default `ViewFactoryCreator` produces Spring MVC view factories capable of rendering JSP, Velocity, and Freemarker views.

The configurable settings are `development`.
These settings are global configuration attributes that you can apply during the flow construction process.

[[_builder_development]]
===== Enabling Development Mode

When you create a flow builder services object, you can turn on development mode.
Development mode switches on hot-reloading of flow definition changes, including changes to dependent flow resources such as message bundles.

To turn on development mode in XML, set the `development` attribute on the `flow-builder-services` element to `true`.
To turn on development mode in Java, use `setDevelopment(true)` on the `FlowBuilderServices` object.

[[_flow_executor]]
=== Setting Flow Executor options

This section explores Flow Executor configuration options.

[[_flow_executor_execution_listeners]]
==== Attaching Flow Execution Listeners

You can use the `flow-execution-listeners` element (in XML) or the `addFlowExecutionListener` method (in Java) to register listeners that observe the lifecycle of flow executions.

The following example shows how to create flow execution listeners in XML:

====
[source,xml]
----
<webflow:flow-execution-listeners>
    <webflow:listener ref="securityListener"/>
    <webflow:listener ref="persistenceListener"/>
</webflow:flow-execution-listeners>
----
====

The folloiwng example shows how to create flow execution listeners in Java:

====
[source,java]
----
@Bean
public FlowExecutor flowExecutor() {
    return getFlowExecutorBuilder(flowRegistry())
            .addFlowExecutionListener(securityListener())
            .addFlowExecutionListener(persistenceListener())
            .build();
}
----
====

You can also configure a listener to observe only certain flows.

The following example shows how to configure a listener to monitor only two flows in XML:

====
[source,xml]
----
<webflow:listener ref="securityListener" criteria="securedFlow1,securedFlow2"/>
----
====

The following example shows how to configure a listener to monitor only two flows in Java:

====
[source,java]
----
@Bean
public FlowExecutor flowExecutor() {
    return getFlowExecutorBuilder(flowRegistry())
            .addFlowExecutionListener(securityListener(), "securedFlow1,securedFlow2")
            .build();
}
----
====

[[_tuning_flow_execution_repository]]
==== Tuning Flow Execution Persistence

You can use the `flow-execution-repository` element (in XML) or the `FlowExecutor` interface (in Java) to tune flow execution persistence settings.

The following example tunes flow execution in XML:

====
[source,xml]
----
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
    <webflow:flow-execution-repository max-executions="5" max-execution-snapshots="30" />
</webflow:flow-executor>
----
====

The following example tunes flow execution in Java:

====
[source,java]
----
@Bean
public FlowExecutor flowExecutor() {
    return getFlowExecutorBuilder(flowRegistry())
            .setMaxFlowExecutions(5)
            .setMaxFlowExecutionSnapshots(30)
            .build();
}
----
====

[[_repository_max_executions]]
===== Tuning `max-executions`

You can tune the `max-executions` attribute (in XML) to place a cap on the number of flow executions that can be created per user session.
When the maximum number of executions is exceeded, the oldest execution is removed.

NOTE: The `max-executions` attribute is per user session.
That is, it works across instances of any flow definition.

[[_repository_max_snapshots]]
===== Tuning `max-execution-snapshots`

You can tune the `max-execution-snapshots` attribute to place a cap on the number of history snapshots that can be taken per flow execution.
To disable snapshotting, set this value to 0.
To enable an unlimited number of snapshots, set this value to -1.

NOTE: History snapshots enable browser back button support.
When snapshotting is disabled, pressing the browser back button does not work.
Doing so results in using an execution key that points to a snapshot that has not been recorded.
