Spring WebFlow. Pass value from button - spring-webflow

Is it possible in Spring WebFlow to pass the value of a button to the flow...?
Something like this:
<button name="_eventId_next" type="submit" id="BTN_START" value="1" />
and then try to get it into the flow like this:
<view-state id="information" view="information">
<transition on="back" to="init" validate="false"/>
<transition on="next" to="followPage">
<set name="buttonValue" value="[button.value]" />
</transition>
</view-state>
and use it in anothor JSP page?
Thanks to everyone could help me.
// Daniele.

Related

How to use the input/output elements in webflow?

I'm trying to understand how the input and output elements are used in webflow. The documentation suggests that flow input/output mapping is similar to calling a method with a signature, but I don't understand what passes the flow the input value or what the flow returns output to. How do I use these elements?
I've been reading the documentation found here, but there are no examples of the elements in action that I can find. This is an example from the documentation.
<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.xsd">
<input name="hotelId" />
<on-start>
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)"
result="flowScope.booking" />
</on-start>
<view-state id="enterBookingDetails">
<transition on="submit" to="reviewBooking" />
</view-state>
<view-state id="reviewBooking">
<transition on="confirm" to="bookingConfirmed" />
<transition on="revise" to="enterBookingDetails" />
<transition on="cancel" to="bookingCancelled" />
</view-state>
<end-state id="bookingConfirmed" />
<end-state id="bookingCancelled" />
In this code, where does the value assigned to "hotelId" come from? Does the input come from the URL? If so, does <input/> behavior change in subflows?
In this code, hotelId will be automatically mapped from the URL if you call /myFlow?hotelId=3 (assuming your flow is called "myFlow")
but you can also set the input directly when calling the flow from another flow, i.e. using:
<subflow-state id="mySubflow" subflow="myFlow">
<input name="hotelId" value="3"/>
</subflow-state>

Spring webflow Value of second parameter is not passed to subflow

Hi, I am using spring webflow2.4.4 with spring4.1.3.
I am trying to pass values between two flows as below.
sending value from flow first xml
<action-state id="submit">
<evaluate expression="someMethod(form)" result="flowScope.saveStatus" />
<set name="flowScope.value1" value="form.value1" />
<set name="flowScope.value2" value="form.value2" />
<transition on="success" to="view" />
</action-state>
<subflow-state id="view" subflow="flow/path/view">
<input name="value1" value="value1" />
<input name="value2" value="value2" />
...
</subflow-state>
reeving data in flow second view xml
<input name="value1" type="string" />
<input name="value2" type="string" />
now in view xml I am able to receive value for "value1" what I passed from first flow but getting value for 'value2' is null.
I tried switching the position in first flow as below
<action-state id="submit">
<evaluate expression="someMethod(form)" result="flowScope.saveStatus" />
<set name="flowScope.value2" value="form.value2" />
<set name="flowScope.value1" value="form.value1" />
<transition on="success" to="view" />
</action-state>
<subflow-state id="view" subflow="flow/path/view">
<input name="value2" value="value2" />
<input name="value1" value="value1" />
...
</subflow-state>
Now I am able to see value of 'value2' but value for 'value1' receiving is null.
What is wrong here? see below debug logs for both example
1st trial
DEBUG SubflowState - Calling subflow 'flow/path/view' with input map['value1' -> 'ABCDF', 'value2' -> [null]]
2nd trial
DEBUG SubflowState - Calling subflow 'flow/path/view' with input map['value2' -> 'ABCDF', 'value1' -> [null]]
I want to pass both thew values to second flow but it second parameter is getting skipped somehow.
this is a very common mistake. the action state is transitioning when it gets a success and stops evaluating the rest of the commands.
you need to use <on-entry> to separate the two:
the commands you want to set or evaluate (value1 & value2)
the command that will be evaluated for the transition, here someMethod(form))
use this instead:
<action-state id="submit">
<on-entry>
<set name="flowScope.value2" value="form.value2" />
<set name="flowScope.value1" value="form.value1" />
</on-entry>
<evaluate expression="someMethod(form)" result="flowScope.saveStatus" />
<transition on="success" to="view" />
</action-state>
Thanks rptmat57, below code worked for me.
<action-state id="submit">
<evaluate expression="someMethod(form)" result="flowScope.saveStatus" />
<transition on="success" to="view" >
<set name="flowScope.value2" value="form.value2" />
<set name="flowScope.value1" value="form.value1" />
</transition>
</action-state>

Webflow On-Render/On-Entry Exception Still Runs On-Exit Methods

I have the following defined in my flow definition:
<view-state id="switchboard" view="switchboard2" model="reservationForm">
<on-entry>
<evaluate expression="flowController.enterSwitchboard(flowRequestContext)" />
<evaluate expression="flowController.populateActionFlags(flowRequestContext)" />
</on-entry>
<transition on="prev" to="switchboardAction" validate="false" />
<transition on="*" to="switchboardAction" />
<transition on-exception="java.lang.Exception" to="systemErrorView" />
<on-exit>
<evaluate expression="flowController.exitSwitchboard(flowRequestContext)" />
<evaluate expression="flowController.clearWebflowForms(flowRequestContext)" />
</on-exit>
</view-state>
What is happening is that an error (in this particular case, IllegalArgumentException, but could be other exceptions as well) in the populateActionFlags() method is ocurring, but the exitSwitchboard() method is still firing. After this, the clearWebflowForms() method throws an exception because the model is screwed up as a result of the previous exception. This is causing an infinite loop.
What I need is this: when an exception occurs, bypass the on-exit methods and go to an error state ("systemErrorView") defined in a section. Do not pass go, do not collect $200.
Webflow version is 2.4.1.
Can anyone assist?
Jason
try using a global transition in your flow:
<global-transitions>
<transition on-exception="java.lang.Exception" to="systemErrorView"/>
</global-transitions>
keep in mind this will be shared by all states of your flow.
If you don't want it to be shared, you might want to create a custom exception for this.
on-exit is to be executed at the end of a view state with intent. Declaring it means the same as a finally block in java.
In your case you may want to do this
<transition on="prev" to="switchboardAction" validate="false" >
<evaluate expression="flowController.exitSwitchboard(flowRequestContext)" />
<evaluate expression="flowController.clearWebflowForms(flowRequestContext)
</transition>
<transition on="*" to="switchboardAction" >
<evaluate expression="flowController.exitSwitchboard(flowRequestContext)" />
<evaluate expression="flowController.clearWebflowForms(flowRequestContext)
</transition>
This executes the evaluate statements on each transition but not on exception.

Spring Webflow : how do I pass an attribute from one flow to another during a transition?

I have an action-state that evaluates an expression and then transitions to various other states depending on the result. One of the result states is a subflow-state that hands control to another flow, example;
<action-state id="doWork">
<evaluate expression="someAction.doWork(someInput)" />
<transition on="WORKSUCCESS" to="workSuccess" />
<transition on="WORKFAIL" to="fixFail" />
</action-state>
<subflow-state id="fixFail" subflow="someOtherPlace/someOtherWorkToFixFail">
<input name="someNumber" value="1" type="java.lang.Integer" />
<transition on="finish" to="workSuccess" />
</subflow-state>
As you can see I can pass an input into the subflow via the input tag but my question is how can I specify and pass additional inputs that I want present if and only if the subflow-state is being called from the transition WORKFAIL? Assume the subflow-state "fixFail" can be called from other action-states.
I've tried things similar to the following with no effect;
<action-state id="doWork">
<evaluate expression="someAction.doWork(someInput)" />
<transition on="WORKSUCCESS" to="workSuccess" />
<transition on="WORKFAIL" to="fixFail">
<attribute name="newInput" value="3000" type="java.lang.Integer" />
</transition>
</action-state>
<subflow-state id="fixFail" subflow="someOtherPlace/someOtherWorkToFixFail">
<input name="someNumber" value="1" type="java.lang.Integer" />
<input name="someNumber2" value="flowScope.newInput" type="java.lang.Integer" />
<transition on="finish" to="workSuccess" />
</subflow-state>
There are three ways you can do this. You can do it through the conversation, session or as attributes passed in.
ConversationScope: If a field is in the conversationScope the field is visible anywhere in that specific flow as well as that flow's subflows (and their transitions)
SessionScope: (Probably not what you
want) Is visible to all flows and
their subflows
Finally you can pass the field as an attribute into the subflow state for example
<subflow-state id="fixFail" subflow="someOtherPlace/someOtherWorkToFixFail">
<input name="someNumber" value="1" type="java.lang.Integer" />
<input name="someNumber2" value="flowScope.newInput" type="java.lang.Integer" />
<transition on="finish" to="workSuccess" />
</subflow-state>
In your subflow's xml
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<input name="someNumber"/>
<input name="someNumber2"/>
...
</flow>
In this example someNumber and someNumber two are passed in as attributes to your subflow. In which you can evaluate them as ${someNumber}
Edit:
This is to address your comment question. If you wanted to set a variable in the conversation scope on a specific transition you can do:
<transition on="WORKFAIL" to="fixFail" >
<set name="conversationScope.someVariable" value="Hello World"/>
</transition>
Then in your jsp
${someVariable} <!-- This will print out 'Hello World' -->

Spring Web Flow: How do I pass values from one flow to another flow

I have a Java web application using spring web flow.
How do I pass values from one flow to another flow?
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:c="http://java.sun.com/jsp/jstl/core" 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">
<persistence-context />
<var name="editBean" class="jp.co.anicom.domain.User" />
<var name="deleteBean" class="jp.co.anicom.domain.User" />
<var name="authorityBean" class="jp.co.anicom.domain.Authority" />
<on-start>
<set name="flowScope.username" value="requestParameters.username" />
</on-start>
<action-state id="queryAll">
<evaluate expression="employeeAction.GetAuthority(flowScope.username)"
result="authorityBean" />
<transition to="editForm" />
</action-state>
<view-state id="editForm" model="editBean" view="../xhtml/framework/edit">
<transition on="editButton" to="validateAccount" />
<transition on="delete" to="getId" />
<transition on="back" to="editSuccessful" />
</view-state>
<action-state id="validateAccount">
<evaluate expression="employeeAction.GetEmployee(flowScope.username, oldPassword)"
result="editBean" />
<transition to="checkUserAccount" />
</action-state>
<action-state id="getId">
<evaluate expression="employeeAction.GetEmployee(flowScope.username)"
result="deleteBean" />
<transition to="deleteUser" />
</action-state>
<decision-state id="checkUserAccount">
<if test="editBean == null" then="queryAll"
else="confirmPassword" />
</decision-state>
<decision-state id="confirmPassword">
<if test="newPassword.equals(confirmPassword)" then="editUser1"
else="queryAll" />
</decision-state>
<action-state id="editUser1">
<set name="editBean.password" value="newPassword" />
<transition to="editUser2" />
</action-state>
<action-state id="editUser2">
<evaluate
expression="employeeAction.editEmployee(editBean, authorityBean.authority)" />
<transition to="editSuccessful" />
</action-state>
<action-state id="deleteUser">
<evaluate expression="employeeAction.deleteEmployee(deleteBean)" />
<transition to="editSuccessful" />
</action-state>
<end-state id="editSuccessful"
view="externalRedirect:contextRelative:/admin_main.do" commit="true" />
<end-state id="displayError" view="../xhtml/framework/displayError" />
<end-state id="dummy1" view="../xhtml/framework/dummy" />
<global-transitions>
<transition on-exception="java.lang.Exception" to="displayError" />
</global-transitions>
</flow>
I am having a problem with the edit functionality here. In my edit page I have username, oldpassword, newpassword and confirm password fields.
First in validateAccount state I check if the username and oldpassword exists in the database, if it it doesn't exist I forward it to queryall state.
If it exists I check if the new password and confirmpassword values are the same, if they are the same I proceed with the editing.
If not I return again to queryAll.
QueryAll state gets the authority of the user to populate it in the form upon re-displaying the page. When I leave the password fields blank and the first time I click edit button It throws a java.lang.NullPointerException.
Create your two flows as subflows and then the data in each flow should be available in the parent and the other subflows.
Mapping data to the subflow happens
before the subflow session is started.
Mapping data from the subflow back to
the parent flow is done when the
subflow completes and the parent flow
session resumes.

Resources