The person controller still handles delete and search.
Example 1. PersonController
@Controller
public class PersonController {
final Logger logger = LoggerFactory.getLogger(PersonController.class);
static final String SEARCH_VIEW_PATH_KEY = "/person/search";
private static final String SEARCH_VIEW_KEY = "redirect:search.html";
private static final String SEARCH_MODEL_KEY = "persons";
@Autowired
protected PersonDao personDao = null;
/**
* <p>Deletes a person.</p>
*
* <p>Expected HTTP POST and request '/person/delete'.</p>
*/
@RequestMapping(value="/person/delete", method=RequestMethod.POST)
public String delete(Person person) {
personDao.delete(person);
return SEARCH_VIEW_KEY;
}
/**
* <p>Searches for all persons and returns them in a
* <code>Collection</code>.</p>
*
* <p>Expected HTTP GET and request '/person/search'.</p>
*/
@RequestMapping(value="/person/search", method=RequestMethod.GET)
public @ModelAttribute(SEARCH_MODEL_KEY) Collection<Person> search() {
return personDao.findPersons();
}
}
At the end of the flow and when exception occurs that the flow doesn't handle, the PersonFlowHandler redirects to the search page.
Example 2. PersonFlowHandler
@Component
public class PersonFlowHandler extends AbstractFlowHandler {
/**
* Where the flow should go when it ends.
*/
@Override
public String handleExecutionOutcome(FlowExecutionOutcome outcome,
HttpServletRequest request, HttpServletResponse response) {
return getContextRelativeUrl(PersonController.SEARCH_VIEW_PATH_KEY);
}
/**
* Where to redirect if there is an exception not handled by the flow.
*/
@Override
public String handleException(FlowException e,
HttpServletRequest request, HttpServletResponse response) {
if (e instanceof NoSuchFlowExecutionException) {
return getContextRelativeUrl(PersonController.SEARCH_VIEW_PATH_KEY);
} else {
throw e;
}
}
/**
* Gets context relative url with an '.html' extension.
*/
private String getContextRelativeUrl(String view) {
return "contextRelative:" + view + ".html";
}
}
Person Validator that is automatically called by Spring Web Flow based on bean name (${model} + 'Validator') and the method based binding in a view-state.
Example 3. PersonValidator
@Component
public class PersonValidator {
/**
* Spring Web Flow activated validation (validate + ${state}).
* Validates 'personForm' view state after binding to person.
*/
public void validatePersonForm(Person person, MessageContext context) {
if (!StringUtils.hasText(person.getFirstName())) {
context.addMessage(new MessageBuilder().error().source("firstName").code("person.form.firstName.error").build());
}
if (!StringUtils.hasText(person.getLastName())) {
context.addMessage(new MessageBuilder().error().source("lastName").code("person.form.lastName.error").build());
}
}
}
Example 4. Excerpt from Address
/**
* Validates 'addressForm' view state after binding to address.
* Spring Web Flow activated validation ('validate' + ${state}).
*/
public void validateAddressForm(MessageContext context) {
if (!StringUtils.hasText(address)) {
context.addMessage(new MessageBuilder().error().source("address").code("address.form.address.error").build());
}
if (!StringUtils.hasText(city)) {
context.addMessage(new MessageBuilder().error().source("city").code("address.form.city.error").build());
}
if (!StringUtils.hasText(state)) {
context.addMessage(new MessageBuilder().error().source("state").code("address.form.state.error").build());
}
if (!StringUtils.hasText(zipPostal)) {
context.addMessage(new MessageBuilder().error().source("zipPostal").code("address.form.zipPostal.error").build());
}
if (!StringUtils.hasText(country)) {
context.addMessage(new MessageBuilder().error().source("country").code("address.form.country.error").build());
}
}