4

In my Spring MVC 3.1 application, I think I can't use "<mvc:annotation-driven />". Why? Because I want to apply an interceptor to all mappings except to the "<mvc:resources" elements. So I can't use :

<mvc:annotation-driven />

<mvc:resources order="-10" mapping="/public/**" location="/public/" />
<mvc:resources order="-10" mapping="/favicon.ico" location="/public/favicon.ico" />
<mvc:resources order="-10" mapping="/robots.txt" location="/public/robots.txt" />
<mvc:resources order="-10" mapping="/humans.txt" location="/public/humans.txt" />

<mvc:interceptors>  
  <mvc:interceptor>
    <mvc:mapping path="/**"/>
    <bean class="com.my.Interceptor" />
  </mvc:interceptor>
</mvc:interceptors>

Because I don't want the interceptor to apply to the resources and there is no way (I think) to specify a path for the mapping which would apply the interceptor to everything except this and that.

So I have to add my own RequestMappingHandlerMapping to be able to specify the interceptor on it, and not globally. Because of this and this, it seems I can't simply define my own RequestMappingHandlerMapping while keeping the <mvc:annotation-driven /> element!

So... With some help, I've been able to get rid of the <mvc:annotation-driven /> element and pretty much everything works well now. I have my interceptor applied on everything but my resources. Everything works well, except the flash scope!

@RequestMapping(value="/test", method=RequestMethod.POST)
public String test(Model model, RedirectAttributes redirectAttrs) 
{
    redirectAttrs.addFlashAttribute("myKey", "my message");
    return "redirect:test2";
}

@RequestMapping(value="/test2")
public String test2(Model model, HttpServletRequest request) 
{
    Map<String, ?> map = RequestContextUtils.getInputFlashMap(request); // map is NULL
    System.out.println(model.containsAttribute("myKey")); // Prints FALSE
}

The flash map is NULL and my model doesn't contain my variable. When I try with the <mvc:annotation-driven /> element it works well! So my question is: what is missing from my context to make the flash scope work?

I also did try to set "org.springframework.web" to a DEBUG logging level, and after the redirect there is nothing logged related to a FlashMap or FlashMapManager. It seems some required bean is definitely missing.

Here are the interesting parts of my context file:

<!-- commented! -->
<!-- <mvc:annotation-driven /> -->

<bean id="baseInterceptor" class="com.my.Interceptor" />

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    <property name="order" value="0" />
    <property name="interceptors">
        <list>
            <ref bean="conversionServiceExposingInterceptor" />
            <ref bean="baseInterceptor" />
        </list>
    </property>
</bean>

<bean id="myRequestMappingHandlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
    <property name="webBindingInitializer">
        <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
            <property name="conversionService" ref="conversionService" />
            <property name="validator" ref="validator" />
        </bean> 
    </property>
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" />
            <bean class="org.springframework.http.converter.FormHttpMessageConverter" />
            <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
        </list>
    </property>
</bean>

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
<bean id="conversionServiceExposingInterceptor" class="org.springframework.web.servlet.handler.ConversionServiceExposingInterceptor">
    <constructor-arg ref="conversionService" />
</bean>

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:/messages/messages" />
    <property name="defaultEncoding" value="UTF-8" />
</bean>

<bean class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver"></bean>

<mvc:resources order="-10" mapping="/public/**" location="/public/" />
<mvc:resources order="-10" mapping="/favicon.ico" location="/public/favicon.ico" />
<mvc:resources order="-10" mapping="/robots.txt" location="/public/robots.txt" />
<mvc:resources order="-10" mapping="/humans.txt" location="/public/humans.txt" />

What is missing for the flash scope to work?

UPDATE : See my answer for the solution... Nothing was missing actually. Only the Session was not working correctly and I found a way to make it work.

Community
  • 1
  • 1
electrotype
  • 8,342
  • 11
  • 59
  • 96

2 Answers2

2

I finally found what was missing for the flash scope to work!

In the action where I access the flash variables (on the page the redirect leads to), I have to use this:

public String test2(Model model, HttpServletRequest request, HttpSession session)

instead of this :

public String test2(Model model, HttpServletRequest request)

It seems that this makes the Session to work correctly and therefore makes the flash scope to work correctly too! Why? I don't know...

electrotype
  • 8,342
  • 11
  • 59
  • 96
  • In SpringMVC 4.1.x I don't get any difficulty accessing the flash attributes directly from `Model`, as Spring doc indicated: "after the redirect attributes from the "input" FlashMap are automatically added to the Model of the controller serving the target URL", it's true that SpringMVC leverages session to store flash attributes. – Evi Song Mar 23 '15 at 06:53
0

It looks like all you need to do is to register a flash map manager with a bean name of flashMapManager and it should get automatically initialized and used by your Dispatcher Servlet:

<bean name="flashMapManager" class="org.springframework.web.servlet.support.DefaultFlashMapManager/>
Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125