[BLOSSOM-181] Flash attributes not working with uuid redirects Created: 07/Jul/14  Updated: 08/Dec/14  Resolved: 07/Aug/14

Status: Closed
Project: Blossom
Component/s: None
Affects Version/s: None
Fix Version/s: 3.0.4

Type: Bug Priority: Neutral
Reporter: Tobias Mattsson Assignee: Tobias Mattsson
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Bug DoR:
[ ]* Steps to reproduce, expected, and actual results filled
[ ]* Affected version filled

 Description   

It works fine when returning UuidRedirectView directly but with the short-hand string syntax it doesn't work.

It appears to be a shortcoming in Spring itself where the view needs to be detected as a redirect view directly after its returned from the controller. This happens in ViewNameMethodReturnValueHandler and its not exactly trivial to customize its behavior as you'd need to explicitly configure the full set of HandlerMethodReturnValueHandlers.

It is possible to fix it by subclassing RequestMappingHandlerAdapter and replace the ViewNameMethodReturnValueHandler with a custom implementation that can detect Blossom's redirect prefixes. Unfortunately this will involve repeating the logic in UuidRedirectViewResolver.



 Comments   
Comment by Tobias Mattsson [ 25/Jul/14 ]

The workaround I've found so far is customizing the RequestMappingHandlerAdapter to detect view names that will result in redirects and flag the ModelAndViewContainer as such.

import info.magnolia.module.blossom.view.UuidRedirectViewResolver;

import java.util.ArrayList;

import org.springframework.core.MethodParameter;
import org.springframework.util.PatternMatchUtils;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler;

public class CustomRequestMappingHandlerAdapter extends RequestMappingHandlerAdapter {

    @Override
    public void afterPropertiesSet() {
        super.afterPropertiesSet();

        // Spring 3
        // ArrayList<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>(super.getReturnValueHandlers().getHandlers());

        // Spring 4
        ArrayList<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>(super.getReturnValueHandlers());

        for (int i = 0; i < handlers.size(); i++) {
            HandlerMethodReturnValueHandler handler = handlers.get(i);
            if (handler instanceof ViewNameMethodReturnValueHandler) {
                handlers.set(i, new ViewNameMethodReturnValueHandler() {

                    @Override
                    protected boolean isRedirectViewName(String viewName) {
                        return super.isRedirectViewName(viewName) || CustomRequestMappingHandlerAdapter.this.isRedirectViewName(viewName);
                    }
                });
            }
            if (handler instanceof ModelAndViewMethodReturnValueHandler) {
                handlers.set(i, new ModelAndViewMethodReturnValueHandler() {

                    @Override
                    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
                        if (returnValue != null) {
                            ModelAndView mav = (ModelAndView) returnValue;
                            if (mav.isReference()) {
                                String viewName = mav.getViewName();
                                if (viewName != null && CustomRequestMappingHandlerAdapter.this.isRedirectViewName(viewName)) {
                                    mavContainer.setRedirectModelScenario(true);
                                }
                            }
                        }
                        super.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
                    }
                });
            }
        }
        super.setReturnValueHandlers(handlers);
    }

    private static final String[] REDIRECT_PATTERNS = new String[] {"website:*", UuidRedirectViewResolver.REDIRECT_MAIN_CONTENT_PLACEHOLDER};

    protected boolean isRedirectViewName(String viewName) {
        return PatternMatchUtils.simpleMatch(REDIRECT_PATTERNS, viewName);
    }
}
Comment by Tobias Mattsson [ 01/Aug/14 ]

Opened a Spring JIRA for this, https://jira.spring.io/browse/SPR-12054

Comment by Tobias Mattsson [ 07/Aug/14 ]

Will go ahead with a custom RequestMappingHandlerAdapter as outlined above. The archetype should include it preconfigured.

Comment by Tobias Mattsson [ 17/Oct/14 ]

To use the new BlossomRequestMappingHandlerAdapter it needs to be configured like this:

<bean class="info.magnolia.module.blossom.web.BlossomRequestMappingHandlerAdapter">
  <property name="customArgumentResolvers">
    <list>
      <bean class="info.magnolia.module.blossom.web.BlossomHandlerMethodArgumentResolver" />
    </list>
  </property>
  <!-- For @Valid - JSR-303 Bean Validation API -->
  <property name="webBindingInitializer">
    <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
      <property name="validator">
        <bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
      </property>
    </bean>
  </property>
  <property name="redirectPatterns">
    <list>
      <value>website:*</value>
    </list>
  </property>
</bean>
Generated at Sun Feb 11 23:30:57 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.