Announcement Announcement Module
Collapse
No announcement yet.
Spring MVC FlashMap and RedirectAttributes request mapping Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring MVC FlashMap and RedirectAttributes request mapping

    Hi all,
    Yesterday I downloaded the new Spring 3.1RC to test the just introduced support for flash scoped variables in Spring MVC. Unfortunately I could not make it working...

    I have a HTML form containing some checkboxes without spring:forms tags. Something like this:

    Code:
    <form action="/deleteaction" method="post">
    <input type="checkbox" name="itemId" value="1" />
    <input type="checkbox" name="itemId" value="2" />
    <input type="submit" name="delete" value="Delete items" />
    </form>
    Before the Flash scope support, my annotated controller looked like:

    Code:
    @RequestMapping(value = "/deleteaction", method = RequestMethod.POST, params={"delete"})
    public String deleteItems(@RequestParam(value="itemId", required=false) String itemId[]) {
    Alternatively, I could have used an HttpServletRequest instead of @RequestParam:

    Code:
    @RequestMapping(value = "/deleteaction", method = RequestMethod.POST, params={"delete"})
    public String deleteItems(HttpServletRequest request) {
        String itemIds[] = request.getParameterValues("itemId");
    Both methods were working fine. If I try to add the RedirectAttributes to the method parameters, Spring will throw an exception:

    Code:
    @RequestMapping(value = "/deleteaction", method = RequestMethod.POST, params={"delete"})
    public String deleteItems(@RequestParam(value="itemId", required=false) String itemId[], RedirectAttributes redirectAttrs) {
    Log:

    Code:
    Oct 16, 2011 11:20:37 PM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/App] threw
        exception [Request processing failed; nested exception is
        java.lang.IllegalArgumentException: argument type mismatch] with root cause 
        java.lang.IllegalArgumentException: argument type mismatch
    What am I doing wrong? How is it possible to get the RedirectAttribues parameter where to add flash scoped variables?

    Thanks a lot for every hint
    Andrea

  • #2
    To use RedirectAttributes you need to be configured with RequestMappingHandlerMapping, RequestMappingHandlerAdapter, and ExceptionHandlerExceptionResolver, which are new in Spring 3.1 and replace the existing DefaultAnnotationHandlerMapping, AnnotationMethodHandlerAdapter, and AnnotationMethodHandlerExceptionResolver. The latter are still available but do not support any new features.

    Check how your DispatcherServlet is configured. Do you use <mvc:annotation-driven/> or not? The MVC namespace uses the new classes but if you don't use the namespace you'll need to replace the old infrastructure classes as mentioned above. Of if this isn't the problem, set logging for 'org.springframework.web' to DEBUG. That should provide information about the argument it fails to resolve.
    Last edited by Rossen Stoyanchev; Oct 17th, 2011, 01:28 PM.

    Comment


    • #3
      Hi Rossen, Thank you for your answer.

      In my dispatcher.xml I had both <mvc:annotation-driven/> and a DefaultAnnotationHandlerMapping, since I needed a localeChangeInterceptor.

      <bean id="annotationUrlMapping" class="org.springframework.web.servlet.mvc.annotat ion.DefaultAnnotationHandlerMapping">
      <property name="order" value="0" />
      <property name="interceptors">
      <list>
      <ref local="localeChangeInterceptor" />
      </list>
      </property>
      </bean>

      <mvc:annotation-driven />
      Now I have commented out the DefaultAnnotationHandlerMapping, the RedirectAttributes object is passed to the method. Unfortunately now the localeChangeInterceptor is missing... How can I hook an interceptor in the new handler?

      Thanks a lot for the help

      Comment


      • #4
        You can add an interceptor through the mvc namespace:

        Code:
        <mvc:interceptors>
            <ref local="localeChangeInterceptor" />
        </mvc:interceptors>
        This will apply it to all HandlerMappings, which is probably what you want with the LocalChangeInterceptor.

        Comment


        • #5
          Thanks again, I was not aware of the interceptors tag in the mvc namespace. Now everything is cleaner...

          Could you please tell me in which case the "addAttribute" method in the RedirectAttributes is used? Aren't only flash attributes "forwarded" to the redirect?

          Last but not least, in non sticky session environments, could flash messages stored somewhere else than in the session (For example in the DB)? How?

          Comment


          • #6
            Could you please tell me in which case the "addAttribute" method in the RedirectAttributes is used?
            The addAttribute methods are for use in the URL either as URI variables (e.g. "redirect:/foo/{bar}") or otherwise they get appended as query parameters.

            could flash messages stored somewhere else than in the session (For example in the DB)? How?
            Yes, on startup the DispatcherServlet looks for a FlashMapManager bean by name "flashMapManager". If it doesn't find one it uses DefaultFlashMapManager. You can extend that class and configure your implementation in your DispatcherServlet configuration.

            Comment


            • #7
              Hi!

              I noticed a problem with redirectattributes and returning a string ("redirect:<viewname>") for the view name. The flash attributes seam not to work with this approach.
              It's working for me if I return a RedirectView object but not the above string.

              Maybe a little bit off topic, but I would also like to suggest an update to the string based redirect. The RedirectView has a nice option to use relativeContext. This makes the viewnames nice and short and does not require to add the name of the dispatcher servlet in the redirect url. Unfortunately I cannot activate this when using the string version.
              Would it be possible to extent the current "redirect:" prefix (for example: "redirect[relative=true]:") or add a second one like "redirect-relative:"?

              Regards and thanks for this great solution with the flash attributes,
              Adrian.

              Comment


              • #8
                I'm surprised that redirecting with a view string doesn't work. Set the log level to DEBUG for "org.springframework.web" and look for output from DefaultFlashMapManager. Also the spring-mvc-showcase has an example in FormController.

                The RedirectView has a nice option to use relativeContext. This makes the viewnames nice and short and does not require to add the name of the dispatcher servlet in the redirect url. Unfortunately I cannot activate this when using the string version.
                That option prepends the application context. If the DispatcherServlet is mapped with "/mvc/*", you still need to have "redirect:/mvc/somePath". There is a ticket to that effect actually SPR-6698. You can also consider mapping the DispatcherServlet to "/" but I do realize that may not be as easy for an existing application.

                Regards and thanks for this great solution with the flash attributes
                Thanks!

                Comment

                Working...
                X