How can we start the webflow based on some condition? - spring

I am using spring webflow version 2.2.1.RELEASE. and below is my action state, when i type the url as //hostAddress:8080/app/order the flow starts by executing the below action state. My question is there any way to pass parameter to this action state? or can we call the below action state when clicked on some button by passing one parameter. because the flow starts from below action state.
<action-state id="placeInitialize">
<evaluate expression="orderActions.setupPlacePage"></evaluate>
<transition on="error" to="home" />
<transition on="success" to="estimate" />
</action-state>

you can do something like this inside your flow (it will be your entry point):
<input name="param1" type="string" />
<decision-state id="isParamSet">
<if test="param1 == null" then="estimate" else="error" />
</decision-state>
and then just call you flow with //hostAddress:8080/app/order?param1=something

Related

how to store value returned by a business service in a variable in spring web flow?

Situation : I am developing a spring mvc web flow app , in that i have two tables customer and customerAdress and two corresponding models : customerModel and customerAdressModel , now following is my flow.xml :
<var name="customer" class="com.model.Customer"/>
<var name="customerAdress" class="com.model.CustomerAdress"/>
<var name="id">
<view-state id="customer" view="customerView.jsp" model="customer">
<transition on="next" to="customerAdress"/>
</view-state>
<view-state id="customerAdress" view="customerAdressView.jsp" model="customerAdress">
<transition on="next" to="insertCustomer"/>
</view-state>
<action-state id="insertCustomer">
<evaluate expression="Buisness.insertCustomer(customer)"/>
<evaluate expression="Buisness.fetchCustomerId(customer)" result="id"/>
<evaluate expression="Buisness.insertCustomerAdress(id,cutomerAdress)"/>
</action-state>
Now insertCustomer inserts customer , fetchCustomerId fetches customer's id and insertCusotomerAdress inserts adresses of customer by id
Problem : My problem is this code is not working , specifically insertCustomerAdress is not working , i think i have done some mistake in decalring id or assigning buisness service's value to id , can somebody please tell me proper syntax ?
By default action state executes only first action. To execute a chain of actions use Named actions.
<action-state id="insertCustomer">
<evaluate expression="Buisness.insertCustomer(customer)">
<attribute name="name" value="insertCustomer" />
</evaluate>
<evaluate expression="Buisness.fetchCustomerId(customer)" result="id">
<attribute name="name" value="fetchCustomerId" />
</evaluate>
<evaluate expression="Buisness.insertCustomerAdress(id,cutomerAdress)">
<attribute name="name" value="insertCustomerAdress" />
</evaluate>
<transition on="insertCustomerAdress.success" to="[state id to transit]" />
</action-state>

Spring webflow start flow and event from a external link (p.e. confirmation email)

App send a confirmation email when an user register a new account. That email contain a link which must start a specific eventId for a flow which got several events. Link redirect properly to flow but I don't get this flow start on confirmation eventId, always it starts on first eventId called login.
url: ....aio/spring/login?_eventId=confirmation&code=cmFmYWVscnVpenRhYmFyZXNAZ21haWwuY29t
I have read possible solutions using externalRedirect and others commands written on flow rules but I don't need that way.
Login flow
<view-state id="login" view="login.xhtml">
<transition on="entry" to="connect"/>
<transition on="recoveryPass" to="recovery" />
</view-state>
<action-state id="connect">
<evaluate expression="login.connect()" />
<transition on="yes" to="finish" />
<transition on="no" to="login" />
</action-state>
<view-state id="recovery" view="recovery.xhtml" model="loginFields">
<transition on="return" to="login" />
<transition on="sendPass" to="recoveryPass" />
</view-state>
<action-state id="recoveryPass">
<evaluate expression="login.recoveryPass()" />
<transition on="yes" to="login" />
<transition on="error" to="error" />
</action-state>
<action-state id="confirmation">
<on-entry>
<set name="confirmationCode" value="requestParameters.code" type="string" />
</on-entry>
<evaluate expression="login.confirmation(confirmationCode)" />
<transition on="yes" to="confirmationOk" />
<transition on="no" to="noUserFound" />
<transition on="error" to="error" />
</action-state>
<view-state id="confirmationOk" view="confirmation.xhtml">
<!--<set name="viewScope.code" value="found" /> -->
</view-state>
<view-state id="noUserFound" view="confirmation.xhtml">
<!--<set name="viewScope.code" value="notFound" />-->
</view-state>
<end-state id="finish" />
<subflow-state id="error" subflow="error">
</subflow-state>
eventId is not same as state id - eventId is required for transitioning in a current state(action/view) of an ongoing flow and not for launching a new flow. The reason why you are landing on login could be that login-flow xml might be mapped to /login mapping and view-state with id login is the start state(by default first state in flow definition file will be start state) of login flow. You need to have a decision state as on start state to redirect to a state based on some conditional parameter whether you need to go to login state or confirmation state.
EDIT:
For example, if code parameter is present only when request is from email, then your flow definition could be like:
<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">
<input name="code" type="java.lang.String">
<decision-state id="checkFlowStart">
<if test="code == null" then="login" else="confirmation"/>
</decision-state>
<view-state id="login" view="login.xhtml">
<transition on="entry" to="connect"/>
<transition on="recoveryPass" to="recovery" />
</view-state>
....
Have you considered make a particular state (implementation in that state) as a different flow. When using in the main flow it can be used as sub-flow and whereas it gives you a freedom to be launched as a separate flow as well.
The parameter from the main flow can be passed as inputs to the sub-flow. Below is an example I am trying to explain myself
Main Flow
<view-state></view-state>
<action-state></action-state>
<!-- This is the re-usable flow which can be used within this flow and can be
launched independently -->
<sub-flow>
<input/>
</sub-flow>
Another spring flow - can be plugged in from another flow or used independently
<input/>
<action-state></action-state>
<end-state></end-state>

How to send parameters SubFlow in Spring WebFlow

I have main Route flow:
<view-state id="addRoute" model="route">
...
<transition on="editBlock" to="editBlock" validate="false" bind="true">
...
</transition>
</view-state>
<subflow-state id="editBlock" subflow="block">
</subflow-state>
By clicking on editBlock button I want to go over to Block Flow and edit Block.
I want to make it as Subflow.
Block Flow:
<on-start>
<set name="flowScope.id" value="requestParameters.id"/>
<evaluate expression="new java.util.ArrayList()" result="flowScope.attributes"/>
<evaluate expression="new java.util.ArrayList()" result="flowScope.visibility"/>
<set name="flowScope.folderId" value="requestParameters.folderId"/>
<set name="flowScope.path" value="requestParameters.path"/>
<evaluate expression="folderBean.treeAsMap" result="flowScope.tree" />
</on-start>
How to send parameters from the main Flow into Subflow? I need to provide 3 params:
id, folderId and path as stated above.
in your Block FLow, you can put:
<input name="id"/>
<input name="folderId"/>
<input name="path"/>
and then in your Route Flow you can use it this way:
<subflow-state id="editBlock" subflow="block">
<input name="id" value="flowScope.id"/>
<input name="folderId" value="flowScope.folderId"/>
<input name="path" value="flowScope.path"/>
</subflow-state>
also, if you call your Block Flow with parameters id=123&folderId=456&path=path then these parameters will be automatically mapped to the inputs with the same name which are set in the flowScope. So you won't need these set elements in you <on-start> anymore.
also FYI you can use <input name="visibility" type="java.util.ArrayList"/> and <input name="tree" value="folderBean.treeAsMap"/> and get rid of your <on-start> completely.

Spring Web Flow exception handling

How to prevent exception,
if requestParameters.sortBy is passed as string (java.lang.NumberFormatException) or is missing (java.lang.NullPointerException)?
<view-state id="journeySearch" model="journeyForm">
...
<transition on="sort">
<set name="journeyCriteria.sortBy" value="requestParameters.sortBy" type="int" />
<evaluate expression="bookingService.searchJourneys(journeyCriteria)" result="viewScope.journeys" />
</transition>
</view-state>
requestParameters.sortBy will be null if it doesn't exist, but it should not throw a NullPointerException
about the NumberFormatException, you could use something like that:
<global-transitions>
<transition on-exception="java.lang.NumberFormatException" to=""/>
</global-transitions>
you could also implement your own exception-handler and use it with <exception-handler bean=""/> you can use it at the flow or state level.

Need to call three webflow states in parallel

We are facing serious performance issues in our application. We need to send three different requests to our backend, when we are using webflow and we are sending them one by one and this is leading to considerable screen loading time.
Can we call three states of webflow in parallel so that we are able to send three requests to our backend in parallel? Or is there any way to load our screen and call one or two methods later?
we need to navigate from retrieveAccInsList view state to accSummary view state but in between i need to send three different Request to backenf as AccSumary screen contain 3 screen merged,so i need data from three different places.but is the required solution
<view-state id="retrieveAccInsList">
<transition on="openAccount" to="detailForAccountAction">
<set name="conversationScope.selectedAccount" value="reqSearchHandler.selectedAccIns" />
<set name="reqSearchHandler.objectToRetrieveCd" value="'RequestSearch'" />
</transition>
</view-state>
<action-state id="detailForAccountAction">
<evaluate expression="accountDetail.getDetailsForAccount(ClientDetailRq)"
result="flowScope.response">
<attribute name="name" value="detailAccountResponse" />
</evaluate>
<transition on="detailAccountResponse.success" to="searchNoteAction" />
<transition on="detailAccountResponse.error" to="retrieveAccInsList" />
</action-state>
<action-state id="searchNoteAction">
<evaluate expression="certNotesHandler.searchForNotes()"
result="flowScope.response">
<attribute name="name" value="noteResponse" />
</evaluate>
<transition on="noteResponse.success" to="searchActivityAction" />
<transition on="noteResponse.error" to="retrieveAccInsList" />
</action-state>
<action-state id="searchActivityAction">
<set name="reqSearchHandler.requestStatus" value="'O'" />
<set name="reqSearchHandler.objectToRetrieveCd" value="'RequestSearch'" />
<evaluate expression="reqSearchHandler.setparam()" />
<evaluate expression="reqSearchHandler.searchForRequest(ReqInquireRq)"
result="flowScope.response">
<attribute name="name" value="activtiyResponse" />
</evaluate>
<transition on="activtiyResponse.success" to="accSummary" />
<transition on="activtiyResponse.error" to="retrieveAccInsList" />
</action-state
Sure; use Ajax. But without further details it's tough to say--why would you need to call three webflow states "in parallel"? It's called "flow" because they're linear (at least within a single conversation; I know you can have multiple flows active at once).

Resources