I'm setting up an application using Spring Webflow 2, and I'm running into a problem. The app takes in a reservation on one page and then allows for payment on another page. The reservation model object works fine; I can fill out the form, submit it, and it shows the fully populated object on the following confirmation screen. When I do the same thing with the paymentInformation model object however, none of the form's contents are bound into the model object when it is processed.
Here's my flow definition. (I moved the payment flow into a subflow while I was trying to troubleshoot this problem.)
<?xml version="1.0" encoding="UTF-8"?>
<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">
<var name="paymentInfo" class="com.myapp.payments.domain.PaymentInfo" />
<input name="reservation" />
<decision-state id="paymentDecision">
<if test="reservationServiceImpl.needsPayment(reservation)"
then="enterPayment"
else="resolvePayment" />
</decision-state>
<view-state id="enterPayment" view="enterPayment" model="paymentInfo">
<on-render>
<evaluate expression="reservationMultiAction.preparePayment" />
<set name="viewScope.stepNumber" value="3" />
</on-render>
<transition on="back" to="editReservation" />
<transition on="submitPayment" to="resolvePayment" />
</view-state>
<action-state id="resolvePayment">
<evaluate expression="reservationMultiAction.submitPayment" />
<transition on="success" to="receipt" />
<transition on="failure" to="payment" />
</action-state>
<end-state id="editReservation" />
<end-state id="receipt" />
</flow>
Calling preparePayment populates the bean in the flowScope, and then correctly populates the form on the enterPayment page. But when I debug the submitPayment action method, the paymentInfo bean only has the results of preparePayment, and nothing from the submitted form.
And since I'm sure someone will ask, here's the opening form tag from the enterPayment page:
<form:form modelAttribute="paymentInfo" method="post">
It is hard to identify the error if full form html code is not included. At first sight, it could be a missing action attribute in the form tag.
<form:form action="${flowExecutionUrl}" modelAttribute="paymentInfo" method="post">
<input type="submit" id="_eventId" value="submitPayment" />
</form:form>
Related
I am creating a ShoppingCart Application in Spring mvc.Here I have two flows for now.
Registration Flow(flow id=registrationFlow)
MailSender Flow(flow id=mailFlow)
When user registration data gets entered in DB successfully a mailSender flow(Subflow) will get triggered.
My Parent Flow is RegistrationFlow.
Please find below Subflow invocation code:
<!-- other navigation rules of parent flow -->
<subflow-state id="mailSenderFlow" subflow="mailFlow">
<input name="userEmail" value="flowScope.regBean.userDTO.userMail"/>
<transition on="finishMailFlow" to="checkMailFlowResult" />
</subflow-state>
<decision-state id="checkMailFlowResult">
<if test="mailSender.mailConfirmation(currentEvent.attributes.mailFlowOutcome)"
then="regSuccess" else="regConfirm" />
</decision-state>
<end-state id="regSuccess" view="/WEB-INF/view/regSuccess.jsp" />
Based on subflow outcome I have created a decision state which will take the control to regSuccess page or back to regConfirm page.
Please find below Subflow definition file:
<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.4.xsd">
<input name="userEmail" required="true" type="java.lang.String"/>
<action-state id="mailSenderAction">
<evaluate expression="mailSender.sendEmail(userEmail)" />
<transition on="success" to="finishMailFlow" />
</action-state>
<end-state id="finishMailFlow">
<output name="mailFlowOutcome" value="mail sending done"/>
</end-state>
</flow>
Now during subflow invocation time I am getting following exception :
org.springframework.webflow.execution.FlowExecutionException: Exception thrown in state 'mailSenderFlow' of flow 'registrationFlow'
at org.springframework.webflow.engine.impl.FlowExecutionImpl.wrap(FlowExecutionImpl.java:573)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:263)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:253)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
Truncated. see log file for complete stacktrace
Caused By: org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'sending'
at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:130)
at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:60)
at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:32)
at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpression(TemplateAwareExpressionParser.java:73)
at org.springframework.binding.expression.spel.SpringELExpressionParser.parseSpelExpression(SpringELExpressionParser.java:96)
Truncated. see log file for complete stacktrace>
Can anyone figure out the issue???
try with single quote inside your value:
<output name="mailFlowOutcome" value="'mail sending done'"/>
I have added a validation in my flow and it works fine, the only problem is I am not able to execute my action class method after the validation. If I remove the validation it works fine.
Here is what my flow.xml looks like
<view-state id="myView" view="newView" model="viewModel">
<transition on="doChangeView" to="doChangeView" />
<transition on="done" to="home" validate="false" />
</view-state>
<action-state id="doChangeView">
<evaluate expression="viewAction.doChangeView" />
<transition on="done" to="home" />
</action-state>
I am guessing that I am not setting the flow correctly. Any help will be appreciated.
In my case, after looking through logs I found that there was some error in the validation method. After resolving it I was able to execute the method in my action class.
I'm using Spring(3.2.8) + CAS (4.0.0) and I'd like to redirect to the login page after logout (instead of displaying the logout confirm page).
I tried to add
cas.logout.followServiceRedirects=true in my cas.properties but nothing happens.
On the client-side when a User wants to logout, he accesses: APP_URL/j_spring_cas_security_logout
My logout-webflow.xml looks like:
<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">
<action-state id="terminateSession">
<on-entry>
<evaluate expression="cryptoServerLogoutInterceptor.terminateCryptoSession(flowRequestContext)"/>
</on-entry>
<evaluate expression="terminateSessionAction.terminate(flowRequestContext)"/>
<transition to="doLogout"/>
</action-state>
<action-state id="doLogout">
<evaluate expression="logoutAction"/>
<transition on="finish" to="finishLogout"/>
<transition on="front" to="frontLogout"/>
</action-state>
<action-state id="frontLogout">
<evaluate expression="frontChannelLogoutAction"/>
<transition on="finish" to="finishLogout"/>
<transition on="redirectApp" to="redirectToFrontApp"/>
</action-state>
<view-state id="redirectToFrontApp"
view="externalRedirect:#{currentEvent.attributes.logoutUrl}&RelayState=#{flowExecutionContext.key}">
<transition on="next" to="frontLogout"/>
</view-state>
<decision-state id="finishLogout">
<if test="flowScope.logoutRedirectUrl != null" then="redirectView" else="logoutView"/>
</decision-state>
<end-state id="redirectView" view="externalRedirect:#{flowScope.logoutRedirectUrl}"/>
<view-state id="logoutView" view="casLogoutView"/>
On the other way when a User accesses the app without being authenticated , he is redirected to:
CAS_URL/login?service=APP_URL%2Fj_spring_cas_security_check
So I will probably need to add/keep somewhere: service=APP_URL
Thx for helping.
EDIT
When I try:
<end-state id="logoutView" view="flowRedirect:login"/>
I end up to:
This webpage has a redirect loop
ERR_TOO_MANY_REDIRECTS
but it works with:
<end-state id="logoutView" view="externalRedirect:contextRelative:login"/>
As you told cas.logout.followServiceRedirects=true is not enough. Because you should define the service that it should redirect after logout:
<bean id="requestSingleLogoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg
value="${cas.server.address}/logout?service=${cas.server.address}" />
<constructor-arg>
<bean
class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
</constructor-arg>
<property name="filterProcessesUrl" value="/j_spring_cas_security_logout" />
</bean>
And you should add this filter to springSecurityFilterChain:
<sec:filter-chain pattern="/j_spring_cas_security_logout*"
filters="requestSingleLogoutFilter" />
This is a part of my web-flow:
<?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"
parent="estatGeneral" start-state="a_cargar_info">
<attribute name="caption" value="consultaDeutesHandler.filAriadna" />
<action-state id="a_cargar_info">
<evaluate expression="consultaDeutesHandler.primeraCarrega(flowRequestContext, usuari)"></evaluate>
<transition on="success" to="v_formulariDeutesInici"/>
<transition on="error" to="error"/>
</action-state>
I would like to insert text from a properties bundle or backing bean into an attribute. I tried this:
<attribute name="caption" value="consultaDeutesHandler.filAriadna" />
where consultaDeutesHandler.filAriadna is a function that returns a String. Instead of the expected value I just see "consultaDeutesHandler.filAriadna" literally.
Is there a way to set the value of an attribute from a properties bundle?
The <attribute> tag will not work since it only supports plain strings, not EL expressions.
<set> should do the trick:
<set name="flowScope.caption" value="consultaDeutesHandler.filAriadna()" />
(Substitute requestScope, conversationScope, etc. for flowScope as appropriate.)
You can refer to this value later in the flow xml, and from your views. For a JSF example,
<div>#{caption}</div>
will ultimately contain the value returned from consultaDeutesHandler.filAriadna()
My application uses CAS 3.4.11, Spring 3.1 and Hibernate 4.
My login-webflow.xml uses spring-webflow-2.0.xsd and the login flow is given below,
<var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />
<on-start>
<evaluate expression="initialFlowSetupAction" />
</on-start>
<view-state id="viewLoginForm" view="casLoginView" model="credentials">
<binder>
<binding property="username" />
<binding property="password" />
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credentials'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="realSubmit">
<evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
</transition>
</view-state>
The beans "initialFlowSetupAction" and "authenticationViaFormAction" are defined in cas-servlet.xml as,
<bean id="initialFlowSetupAction" class="org.jasig.cas.web.flow.InitialFlowSetupAction"
p:argumentExtractors-ref="argumentExtractors"
p:warnCookieGenerator-ref="warnCookieGenerator"
p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator"/>
<bean id="authenticationViaFormAction" class="org.jasig.cas.web.flow.AuthenticationViaFormAction"
p:centralAuthenticationService-ref="centralAuthenticationService"
p:warnCookieGenerator-ref="warnCookieGenerator"/>
The issue here is, the InitialFlowSetupAction is called while launch the login page. On click of "Sign In" button the bind/submit method of AuthenticationViaFormAction class should be invoked. But always the InitialFlowSetupAction is called and the form is redisplayed with out any exception. Atleast I could track if there is an exception.
Can it be a binding issue with username and password fields of the form to set its properties to UsernamePasswordCredentials?
Basically I would like to know why InitialFlowSetupAction is invoked onclick of "Sign In" button?
Probably it is because your form does not hold value of "_flowExecutionKey" field.
It should contain next input elements to be able to resume flow execution.
<form>
...
<input type="hidden" name="_eventId" value="submit" />
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}" />
</form>
http://static.springsource.org/spring-webflow/docs/2.0-m1/reference/flow-executor.html
In CAS 3.5.2 for some reason field "execution" is used instead of "_flowExecutionKey".
Try setting validate to false:
<transition on="submit" bind="true" validate="false" to="realSubmit">