Broken Exceptions
Into the View Resolver
But where? Like before I wanted to keep this piece decently modularized and Spring didn't provide much to help. After fishing through the source code for a bit the best place seemed to be to intercept the call to render() on the View interface. public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
This can be modified using a Decorative wrapper:
public class RequestContextViewDecorator implements View {
private final View innerView;
private final ApplicationContext applicationContext;
public RequestContextViewDecorator(View innerView, ApplicationContext applicationContext) {
this.innerView = innerView;
this.applicationContext = applicationContext;
}
The first issue is getting around that pesky wildcard capture "?" in the model. This is easily done by a small method to get back a known safe type:
private Map<String, Object> getTypedMap(Map<String, ?> model) {
Map%lt;String, Object> typedMap = new HashMap%lt;String, Object>();
typedMap.putAll(model);
return typedMap;
}
This could easily be refactored in to an abstract class and then use a Template abstract method which receives the typed map if you have other classes doing similar things or like to add extra classes to keep things focused. This object then inherits the same behavior covered from the first post, throwing what it needs in the model and then delegating to the wrapped View:
@Override
public void render(Map%lt;String, ?> untypedModel, HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map model = getTypedMap(untypedModel);
if (exposeSpringMacroHelpers) {
if (!model.containsKey(MODEL_KEY)) {
model.put(MODEL_KEY, new RequestContext(request, response, ((WebApplicationContext) applicationContext).getServletContext(), model));
}
}
....
innerView.render(model, request, response);
}
Now just plug in to to your view resolver (in this case the Surf(again) view resolver):
public class RequestContextPageViewResolver extends PageViewResolver {
@Override
protected View loadView(String viewName, Locale locale) throws Exception {
return new RequestContextViewDecorator(super.loadView(viewName, locale), this.getApplicationContext());
}
}
And there you have it (after you wire in your View resolver of choice in your Spring config): a nice OOP way of integrating the request context needed for Spring form binding in a modular way to a View resolver which for some reason or another does not have the functionality in its inheritance hierarchy.