[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> |