From spring
Build stateful multi-step web conversations with Spring Web Flow definitions, conversation-scoped state, transitions, validation, subflows, and flow execution tests. Use this skill when building stateful multi-step web conversations with Spring Web Flow, including flow definitions, conversation-scoped state, transitions, validation, subflows, and flow execution tests.
npx claudepluginhub ririnto/sinon --plugin springThis skill uses the workspace's default tool permissions.
Use this skill when building stateful multi-step web conversations with Spring Web Flow, including flow definitions, conversation-scoped state, transitions, validation, subflows, and flow execution tests.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Use this skill when building stateful multi-step web conversations with Spring Web Flow, including flow definitions, conversation-scoped state, transitions, validation, subflows, and flow execution tests.
Use spring-web-flow for guided browser conversations such as checkouts, onboarding wizards, and review-confirm-submit journeys that need explicit state transitions.
The ordinary Spring Web Flow job is:
SKILL.md for the ordinary wizard path: flow definition structure, flow registry and executor setup, view-state model binding, simple validation, decision states, subflows, and basic flow execution tests.Use the core Web Flow module for ordinary MVC-integrated flows.
Spring Web Flow 4.0.0 is the current released line and targets Java 17+, Spring Framework 7.0, and Servlet 6.1.
<dependencies>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
@Bean
FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder()
.setBasePath("/WEB-INF/flows")
.addFlowLocationPattern("/**/*-flow.xml")
.build();
}
@Bean
FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry()).build();
}
@Bean
FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping mapping = new FlowHandlerMapping();
mapping.setOrder(-1);
mapping.setFlowRegistry(flowRegistry());
return mapping;
}
@Bean
FlowHandlerAdapter flowHandlerAdapter() {
FlowHandlerAdapter adapter = new FlowHandlerAdapter();
adapter.setFlowExecutor(flowExecutor());
return adapter;
}
Keep the flow id aligned with the URL mapping strategy. A flow registered as booking-flow should be reachable through the MVC flow handler path you standardize on.
Start with one registry path and one executor. Add custom execution listeners or repositories only when the application really needs them.
model binding and validation in view states instead of duplicating form parsing in actions.viewScope, conversationScope, or scope lifetime rules become the design constraint.<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow https://www.springframework.org/schema/webflow/spring-webflow.xsd">
<var name="booking" class="com.example.Booking"/>
<view-state id="enterDetails" model="booking">
<transition on="next" to="confirm" validate="true"/>
</view-state>
<view-state id="confirm" model="booking">
<transition on="confirm" to="saveBooking"/>
<transition on="back" to="enterDetails"/>
</view-state>
<action-state id="saveBooking">
<evaluate expression="bookingService.save(booking)"/>
<transition on="success" to="finished"/>
</action-state>
<end-state id="finished" view="booking/complete"/>
</flow>
@Configuration
class WebFlowConfig extends AbstractFlowConfiguration {
@Bean
FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder()
.setBasePath("/WEB-INF/flows")
.addFlowLocationPattern("/**/*-flow.xml")
.build();
}
@Bean
FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry()).build();
}
@Bean
FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping mapping = new FlowHandlerMapping();
mapping.setOrder(-1);
mapping.setFlowRegistry(flowRegistry());
return mapping;
}
@Bean
FlowHandlerAdapter flowHandlerAdapter() {
FlowHandlerAdapter adapter = new FlowHandlerAdapter();
adapter.setFlowExecutor(flowExecutor());
return adapter;
}
}
<decision-state id="checkEligibility">
<if test="booking.vipCustomer" then="vipReview" else="standardReview"/>
</decision-state>
<subflow-state id="collectPayment" subflow="payment-flow">
<input name="bookingId" value="booking.id"/>
<transition on="paid" to="finished"/>
</subflow-state>
Return these implementation artifacts for the ordinary path:
*-flow.xml definition with explicit states and transitionsWebFlowConfig or equivalent configuration class that registers the flow and executor*FlowExecutionTests class that proves startup, one forward transition, and one negative or backtracking pathenterDetails
confirm
saveBooking
finished
<transition on="next" to="confirm"/>
<var name="booking" class="com.example.Booking"/>