1

Expectation: When i attempt booking, booking has been failed due to price change and throwing below price change exception.

Then i need to capture that errors in event and redirect the request to previous page and display the error message on top of the page.

As per my below logic i can able to redirect the request to previous page, while throwing price change exception but the issue is i can't able to display my error message (Your booking price has been changed, please choose another) on previousPage.

Anybody can help me out. Thanks in advance.

BookAction.java

public class BookAction { 
   private static final String PRICE_CHANGED_ERROR = "Your booking price has been changed, please choose another";

   public Event book(RequestContext context) {
    try {
        // Booking attempt 
        // Consider booking attempt failed and throwing price change exception

    }catch (PriceChangeException priceChangeException) {
            return handlePriceChange(context);
    }
   }

    public Event handlePriceChange(RequestContext context) {

        Errors pageErrors = getPageErrors(context);
        if (true) { // Consider if its true and returning new Event "searchPage"
            pageErrors.reject(PRICE_CHANGED_ERROR);
            return new Event(this, "searchPage");
        }
        return error();
    }

}

booking.xml

<webflow:flow>
    <webflow:action-state id="book"> 
        <webflow:evaluate expression="bookAction.book" />       
        <webflow:transition on="success" to="confirm" />
        <webflow:transition on="error" to="handleFrd" />
        <webflow:transition on="searchPage" to="searchPage" />
    </webflow:action-state>

    <webflow:end-state id="searchPage" view="externalRedirect:#{flowScope.bookState.searchResultURI}" />

</webflow:flow>
Mohan
  • 145
  • 2
  • 10

4 Answers4

1

Unfortunately, this is a poorly documented part of SWF. What you are looking for is to use the flashScope. flashScope was specifically designed for this purpose after a variable in the flashScope is read once it is automatically deleted.

But... the design problem in SWF is that the flashScope only works between a Parent flow and an embedded child flow inside of it. It will not hold save your variables if you use an "externalRedirect" and try to access the error using "flashScope.error"... because technically the first flow ended and a new flow has begun. So how to solve this problem?

I was only able to solve it with 2 ways and both are hacks.

Option 1.

if the message is simple then in the 'externalRedirect:#{flowScope.bookState.searchResultURI}' append a HTTP GET param such as

?msg=An Error Occurred.

Although this will look ugly in the url bar, it is simpliest and the least painful solution.

Option 2.

is a bit more painful but provides the most flexibility if you want complex error msgs. Basically you have to merge the flashScope of Spring Web Flow and the flashMap of Spring MVC and send your externalRedirect to a spring mvc controller first.

You will need to create and register a FlowExecutionListenerAdapter to merge (hack) the flashScope and the flashMap see the link directly below for step by step instructions (ignore the stuff about sessionMap)

Spring web flow how to add flash attribute when exiting from flow to external redirect

Then once you achieve that you can easily access your flash variable error msg using Spring MVC like so:

How to read flash attributes after redirection in Spring MVC 3.1?

Note: the variable will already be in the flashMap of spring mvc. So all you have to do is render a view in spring mvc and access the variable from the view.

My 2 cents: because of limitations like this I've personally stopped using webflow and only use Spring MVC exclusively now. I think Spring Web flow is still useful for very simple use cases (flow A -> flow B -> flow C) but if you're trying to to do something more complex or are trying to learn SWF from scratch right now... my advice to you is to just use Spring MVC... it will save you a lot of time in the long run. I think they are working on a major revision for SWF (3.0) maybe then all these limitations will get worked out

Community
  • 1
  • 1
Selwyn
  • 3,118
  • 1
  • 26
  • 33
  • I created an improvement request on their jira project. https://jira.spring.io/browse/SWF-1672 lets see what they say. – Selwyn Oct 21 '15 at 11:22
1

Indeed Spring Web Flow has a number of scopes where variables can be stored but when a flow ends all scopes end as well, unless the flow is a child flow delegating control back to the parent flow in which case you can use flash scope in addition to any parent flow scoped variables.

Spring Web Flow also knows how to interact with the Spring MVC flash scope. So when a top-level flow ends and the redirect is to a Spring MVC endpoint, there is a way to indicate that output variables should be put in Spring MVC flash scope, which would make them available after the redirect.

This is mentioned in the reference documentation http://docs.spring.io/autorepo/docs/webflow/current/reference/html/spring-mvc.html#spring-mvc-flash-output.

Rossen Stoyanchev
  • 4,910
  • 23
  • 26
0

in booking.xml, add below changes

<webflow:transition on="searchPage" to="searchPage">
     <set name="flowScope.error" value="'text u wanna show in next page'" type="string" />
</webflow:transition

And now in the redirected page try reading that text. hope it would work!

  • 1
    I don't think you will be able to read the contents of "flowScope.error" after the redirect has occurred. Because once you perform an "externalRedirect" to another page... the flow ends and thus the flowScope is wiped clean removing your "error" string. – Selwyn Oct 21 '15 at 08:58
  • Yes @Airduster. i couldn't able to read that error message. can you please give some alternative solution ? – Mohan Oct 21 '15 at 09:17
  • @Mohan see my submitted answer – Selwyn Oct 21 '15 at 10:52
0

Use flash scope:

In xml

<set name="flashScope.flashScopeAttribute" value="'f'" />

In JSP

flash scope: #{flashScopeAttribute}