340010 (5) [Avatar] Offline
#1
I was playing around with Spring web flow example provided in the book. Rather than using FormAction, i was trying to drive the app with MultiAction implementation. It is driving me nuts that i am not able to Do simple asks like putting a form validation etc. Please see the details below and help me out.

This is my findExisting-Player-flow.xml. here i have used a var and model binding.
Now once this view (findExistingPlayerForm) is rendered, my assumption is that it should validate the form and stop the user then and there on the view itself before passing on the control to searchActions.findExistingPlayer

I tried the same thing in the GIT example of the book by adding some annotations on PlyerSearchCriteria and there also the validation does not work. please please please help me out smilie

Flow xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Source project: sip05, branch: 03 (Maven Project) -->

<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
	http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
	start-state="findExistingPlayerForm">

	[b]<var name="playerSearchForm" class="com.saurabhd.springwebflow.form.PlayerSearchForm"/>
	
	<view-state id="findExistingPlayerForm" model="playerSearchForm">
		<transition on="find" to="findExistingPlayerFormActionState">
		</transition>
	</view-state>[/b]

	<action-state id="findExistingPlayerFormActionState">
		<evaluate expression="searchActions.findExistingPlayer"></evaluate>
		<transition on="success" to="displayFindExistingPlayerResult"></transition>
	</action-state>

	<view-state id="displayFindExistingPlayerResult">
		<transition on="back" to="findExistingPlayerForm" />
		<transition on="newSearch" to="newSearchEndState" />
		<transition on="noneMatch" to="endState" />
		<transition on="existingAccountFound" to="existingAccountFoundEndState" />
	</view-state>

	<end-state id="newSearchEndState" />

	<end-state id="endState" />


	<end-state id="existingAccountFoundEndState">
		<output name="loginUsername" value="player.guardian.username" />
	</end-state>


Multi Action implementation

public class SearchWorkflowActions extends MultiAction{
	private PlayerService playerService;

	/**
	 * @param playerService the playerService to set
	 */
	public void setPlayerService(PlayerService playerService) {
		this.playerService = playerService;
	}
	
	public Event findExistingPlayer(RequestContext context){
		PlayerSearchForm form = (PlayerSearchForm) context.getFlowScope().get("playerSearchForm");
		System.out.println("Search form "+form);
		Player findExistingPlayer = playerService.findExistingPlayer(form);
		context.getFlowScope().put("player", findExistingPlayer);
		return success();
	}

}


My Search form

public class PlayerSearchForm implements Serializable{
private static final long serialVersionUID = 1L;
	
	
	private String firstName;
	
	private String lastName;
	private String homePhone;
	
	@NotEmpty
	@Size(min=10)
	public String getFirstName() {
		return firstName;
	}
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}
	@NotNull
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	@NotBlank
	public String getHomePhone() {
		return homePhone;
	}
	public void setHomePhone(String homePhone) {
		this.homePhone = homePhone;
	}
	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "PlayerSearchForm [firstName=" + firstName + ", lastName="
				+ lastName + ",  homePhone="
				+ homePhone + "]";
	}
	
	

}


Flow spring configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flow="http://www.springframework.org/schema/webflow-config"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/webflow-config
	http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd">

	<flow:flow-builder-services id="flowBuilderServices"
		development="true" 
		validator="validator"/>
	<flow:flow-executor id="flowExecutor" flow-registry="flowRegistry"></flow:flow-executor>
	<flow:flow-registry id="flowRegistry" base-path="/WEB-INF/flows">
		<flow:flow-location-pattern value="*/**/*-flow.xml" />
	</flow:flow-registry>
	<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter"
		p:flowExecutor-ref="flowExecutor" />

	<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping"
		p:flowRegistry-ref="flowRegistry" p:order="0" />
		
		<bean id="searchActions" class="com.saurabhd.springwebflow.action.SearchWorkflowActions">
		<property name="playerService" ref="playerService"></property>
	</bean>


340010 (5) [Avatar] Offline
#2
Is this forum discontinued? Where can we get help from authors? Please advise.
340010 (5) [Avatar] Offline
#3
An update - I have also tried the model binding in the view state. It also fails to invoke the JSR-303 annotation validations on my bean. smilie

What has worked so far is the custom validate${view-state-id} method. See below:

public void validateFindExistingPlayerForm(ValidationContext context){
        MessageContext messages = context.getMessageContext();
        if(StringUtils.isEmpty(firstName)){
            messages.addMessage(new MessageBuilder().error().source("firstName").
                    defaultText("Please enter the value for First Name.").build());
        }
    }

Flow.xml

<var name="playerSearchForm" class="com.saurabhd.springwebflow.form.PlayerSearchForm"/>

    <view-state id="findExistingPlayerForm" model="playerSearchForm">
        <transition on="find" to="findExistingPlayerFormActionState">
        </transition>
    </view-state>


Please tell me the best way to validate forms in Spring Webflow. Pleas help!

340010 (5) [Avatar] Offline
#4
Hi Willie,

Update - I have got the validation to work for the configuration where i specify model="formName".

Question is on the following snippet:

			
	<view-state id="findExistingPlayerForm">
	 <on-render>
	   Prepares the form object for display on a form
	   <evaluate expression="findExistingPlayerFormAction.setupForm"/>	   	   
	 </on-render> 
		<transition on="find" to="findExistingPlayerActionState">
		  <!-- 
		  Binds all incoming request parameters to the form object and 
		  then validates the form object using a registered validator. 
		  This action method will return the "success" event if there 
		  are no binding or validation errors, otherwise it will 
		  return the "error" event.
		  -->
		 <evaluate expression="findExistingPlayerFormAction.bindAndValidate"/>	  
		</transition>
	</view-state>


Here, even if we put the validations on the PlyerSearchCriteria.java fields. The validations do not execute on the call of bindAndValidate. Is it a must to pass a validator here in order to perform the validation? Why dont the annotations work?