transition is not invoked on view-state in spring webflow - spring

Transition is not invoked in my view-state and when I click the fogotusername link in my login page, it again lands to the login page itself. I think the webflow session is somehow lost. Any idea? Please help.
fogotUsername link in my login.jsp is below:
<a href="login.do?_eventId=fogotUsername&page=init" > <spring:message code="label.forgetUsername" /></a>
My login flow xml is below:
<?xml version="1.0" encoding="UTF-8"?>
<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="login">
<view-state id="login" view="tiles.login">
<transition on="fogotUsername" to="viewForgotUsername">
</transition>
<transition on="fogotPassword" to="viewForgotPassword">
</transition>
</view-state>
<view-state id="viewForgotUsername" view="tiles.forgotUsername">
</view-state>
<view-state id="viewForgotPassword" model="password" view="tiles.changePassword">
<transition on="submit" to="viewForgotUsername"/>
</view-state>
<end-state id="loginend"/>
</flow>

The link doesn't contain the flow execution URL. Try replacing your link element with the below:
<spring:message code="label.forgetUsername" />

Related

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>

Invalid _eventId in spring webflow

Is there any way to handle unexisting eventIds or absence of eventId parameter in spring webflow?
e.g. for this webflow
<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">
<view-state id="welcome">
<transition on="goForward" to="nextStep"/>
</view-state>
<view-state id="nextStep">
<transition on="endFlow" to="finishStep" />
</view-state>
<end-state id="finishStep"/>
<global-transitions>
<transition on="cancel" to="finishStep"/>
</global-transitions>
</flow>
How to handle requests with param like _eventId=unexistingAction or requests with no _eventId param ?
This will normally produce a page with stack trace...
no transition found on occurence of event in state of flow...
This is how you can handle transitions that don't exist:
<global-transitions>
<transition on-exception="org.springframework.webflow.engine.NoMatchingTransitionException" to="handlingViewState">
<evaluate expression="handlingBean.handle(flowExecutionException)"></evaluate>
</transition>
</global-transitions>

Display Spring WebFlow Global Transitions

I am a new at using Spring Webflow. I am trying to use Global transitions. In my jsp I am trying to display all the transitions using
<c:forEach var="transition" items="${flowRequestContext.currentState.transitions}">
<c:out value="${transition.id}"/>
</c:forEach>
I can see all the transitions for the currentState but I cannot see the global transitions.
My understanding was the global transitions would be available in all the view-states. To get the global transitions do I need to access it in a different way?
Here is a simplified version of my flow xml
<flow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/webflow"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<view-state id="state1" view="view1.jsp" model="person">
<transition on="submit" to="state2"/>
<transition on="cancel" to="canceled"/>
</view-state>
<view-state id="state2" view="view1.jsp" model="person">
<transition on="complete" to="complete"/>
</view-state>
<view-state id="canceled" view="view1.jsp" model="person">
<transition on="resubmit" to="resubmit"/>
</view-state>
<action-state id="reassign">
<evaluate expression="CustomAction.reassign(flowRequestContext)"/>
</action-state>
<end-state id="complete"/>
<global-transitions>
<transition on="cancel" to="canceled"/>
<transition on="reassign" to="reassign"/>
</global-transitions>
</flow>
So when in state1 in the jsp how canI display all the tranistions including global?
Thanks for any help in advance
Better late than never.
There is a getGlobalTransitionSet method, but it's in the implementation org.springframework.webflow.engine.Flow class, not in the interface FlowDefinition. This method returns a TransitionSet that is not iterable by forEach, but fortunatelly it has a toArray method.
If you feel comfortable with this, you could use:
${flowRequestContext.activeFlow.globalTransitionSet.toArray()}
Tested.

Restarting Spring Web Flow with new model values

I am trying to find a way that if the user restarts the flow the values are not in it. If you look at my flow below you can see that the user enters data, previews it and then saves it.. after the save the user can go back to enter new data into the input screen but with my current setup the screen shows the pre-data. how can I clear it on restart?
<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">
<var name="customer" class="org.uftwf.domain.Customer"/>
<view-state id="helloworld" view="input.jsp" model="customer" popup="true">
<transition on="submit" to="preview" />
<transition on="cancel" to="thanks" validate="false"/>
</view-state>
<view-state id="preview" model="customer">
<transition on="cancel" to="helloworld"/>
<transition on="accept" to="save">
<evaluate expression="hellowWorldFlowActions.addCustomer(customer)"/>
</transition>
</view-state>
<view-state id="save" model="customer">
<transition on="accept" to="thanks"/>
</view-state>
<view-state id="thanks">
<transition on="restart" to="helloworld"/>
</view-state>
</flow>
One simple way is to define a reset() method on your Customer class and call that in whichever <view-state> <on-entry> (like "thanks") or <transition> ("restart") makes sense.
Have you tried:
<view-state id="helloworld" view="input.jsp" model="customer" popup="true">
<on-entry>
<set name="flowScope.costumer" value="new org.uftwf.domain.Customer()" />
</on-entry>
<transition on="submit" to="preview" />
<transition on="cancel" to="thanks" validate="false"/>
</view-state>
You can do an external redirect to do same flow. Here is an example.
<var name="customer" class="org.uftwf.domain.Customer"/>
<view-state id="thanks">
<transition on="restart" to="doRestart"/>
</view-state>
<end-state id="doRestart" view="externalRedirect:nameOfThisFlow"></end-state>

Why my spring webflow can't forward or backward?

I am using spring mvc 3.0.4 and webflow 2.2.1, I config my webflow like the following:
<view-state id="createTaskDetail" model="task" view="task/createTaskDetail">
<transition on="upload" to="uploadFile" />
<transition on="revise" to="createTaskBasic" />
<transition on="publish" to="publish" />
<transition on="cancel" to="cancel" />
</view-state>
<view-state id="uploadFile" model="task" view="task/uploadFile">
<transition on="confirm" to="createTaskConfirm" >
<evaluate expression="task.processFile()"/>
</transition>
<transition on="revise" to="createTaskDetail" />
<transition on="publish" to="publish" />
<transition on="cancel" to="cancel" />
</view-state>
<view-state id="createTaskConfirm" model="task"
view="task/createTaskConfirm">
<transition on="publish" to="publish" />
<transition on="revise" to="uploadFile" />
<transition on="cancel" to="cancel" />
</view-state>
createTaskDetail is my 2nd view, when I arrived this page I can't forward or backward(When clicking button next or return or cancel). There is no js error or java exception,here is my jsp code of 2nd view:
<button type="submit" id="upload" name="_eventId_upload">next</button>
<button type="submit" name="_eventId_revise" >return</button>
<button type="submit" name="_eventId_cancel" >cancel</button>
<button type="submit" name="_eventId_publish" >publish</button>
Anyone has an idea? Thanks.
Do you have a form tag around the buttons?
<form:form modelAttribute="task">
inputs
buttons ...
</form:form>
Maybe validation errors which are not shown?

Resources