Question

I'm new to web flow, so I'm not sure how to do this: I have a spring mvc controller, and I have a spring webflow. One of the flow states is supposed to display a form for adding a new client. In the controller I have methods for saving the Client object (binded to the form as modelAttribute = "client") to the database. I don't know how to pass the control from the webflow to the controller and back or create a model Attribute directly in the flow for binding with the form (but as I understand later I'd still have to redirect to the controller).

Please help me, what's the best logic (solution) in this situation ?

I tried:

<view-state id="clientOptions" view="options" model="client">
    <transition on="submit" to="confirm"/>
    <transition on="back" to="viewCart"/>
</view-state>

my form is in the options view and the binding goes like this

<form:form modelAttribute="client" method="post">
Was it helpful?

Solution

Assuming you have a mapping in your web.xml as:

<servlet>
    <servlet-name>yourApp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>yourApp</servlet-name>
    <url-pattern>*.htm</url-pattern>
</servlet-mapping>

Define the following in your servlet xml file (per above web.xml definition yourApp-Servlet.xml):

    <!--Handler mapping for your controller which does some work per your requirements-->
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="order" value="1" />
        <property name="mappings">
            <props>
                <prop key="/handledByController.htm">yourController</prop>
            </props>
        </property>
    </bean>
    <!--Your controller bean definition-->
    <bean id="yourController" class="package.YourController">
        //some properties like service reference
    </bean>
    <!--Class which handles the flow related actions-->
    <bean id="classForThisFlow" class="package.ClassForThisFlow">
    </bean>

I assume you have web flow required configuration defined like below (for webflow 2.3 - for 1 configuration is little different) in webflowconfig xml:

    <!--View  resolvers-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean id="flowViewResolver" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">  
        <property name="viewResolvers" ref="internalResourceViewResolver"/>  
    </bean>  
    <!--flow xml registration - flow xmls are in flows folder-->
    <flow:registry id="flowRegistry">
        <flow:location path="/WEB-INF/flows/**/*-flow.xml" />
    </flow:registry>

    <!--Flow controller to which dispacther servlet delegates the control to manage flow execution-->
    <bean name="flowController" class="org.springframework.webflow.executor.mvc.FlowController">
        <property name="flowExecutor" ref="flowExecutor" />
    </bean>

    <flow:executor id="flowExecutor" registry-ref="flowRegistry">
        <flow:repository type="continuation" max-conversations="1" max-continuations="30" />
        <flow:execution-listeners>
            <flow:listener ref="listener"/>
        </flow:execution-listeners>     
    </flow:executor>
    <!--validator to be identified and registered for view state validations if enabled-->
    <bean name="validator" class="org.springframework.validation.localvalidation.LocalValidatorFactoryBean"/>  
    <flow:flow-builder-services id="flowBuilderServices" view-factory-creator="flowViewResolver" validator="validator"/>  

In your flow xml you have view as:

            <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.3.xsd"
start-state="prepareFlow">
<action-state id="prepareFlow">
    <evaluate expression="classForThisFlow.prepareFlowForm()" result="flowScope.client"/>
    <transition to="clientOptions" />
</action-state>
    <view-state id="clientOptions" view="options" model="client">
        <!--If you have defined validator for the action class handling this view, then validation will kick in. You can disable validation by validate="false"-->
                        <!--By default binding of form fields will happen to the model specified; you can disable it by bind="false"--> 
        <transition on="submit" to="confirm"/>
        <transition on="back" to="viewCart"/>
    </view-state>

    <action-state id="confirm">
        <!--Do some action on the form-->
        <evaluate expression="classForThisFlow.methodName(flowRequestContext,flowScope.client)"/>
        <transition to="returnToController" />
    </action-state>

    <!--This will take the control back to yourController; See mappingis specified as *.htm in web.xml-->
    <end-state id="returnToController" view="externalRedirect:handledByController.htm" /> 

You can pass client to controller through session as:

    public class ClassForThisFlow{
      public Client prepareFlowForm(){
        Client client= new Client();
    ...
    return client;
       }
       public void methodName(RequestContext context, Client client){
    HttpSession session = ((HttpServletRequest)context.getExternalContext().getNativeRequest()).getSession();
              session.setAttribute("client",client);
       }
       .....
       }

This way you can navigate through your flow and on submit "confirm", you will be taken to action class, if needed, else change both end-state id and transition on submit to to "confirm", which will direct the control to yourController. In your controller you can access session and retieve the client object for further processing.

OTHER TIPS

I use to declare my controller or handler at application-context.xml for example:

<!-- handler/controller-->
<bean name="contextHandler" class="aaaa.bbbb.ContextHandler" scope="session">
    <property name="service" ref="usuarisBO" />
    <property name="usuari" ref="usuariLDAP" />
</bean>

then in my flow i can call the id object and some method:

And if you need a transaction you aldo can do it inside an action method for example:

<action-state id="a_pas2">
    <evaluate expression="contextHandler.carreguemValorsPas2(flowRequestContext,usuari)" />
        <transition on="*" to="v_pas2" />
</action-state>



<view-state id="v_pas2" view="/WEB-INF/xhtml/crearCalendariFiscal/formulariCrear2.xhtml">
        <transition on="pas3" to="a_pas3"/>
</view-state>

I hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top