Question

Using Spring MVC, is there any way to factorize the org.springframework.ui.Model, in order to not to have to specify it in the method parameters within any controller?

In other words, I'm currently doing it like this:

public abstract class AbstractController {

    @Autowired
    protected MultipartHttpServletRequest request;

}

@Controller
public class SigninController extends AbstractController {

    @RequestMapping(value = "/signin", method = RequestMethod.GET)
    public String signin(@ModelAttribute User user, Model model) {
        // do stuff with user (parameter)
        // do stuff with model (parameter) <--
        // do stuff with request (attribute)
        return "/signin/index";
    }

}

And I would like to do like that:

public abstract class AbstractController {

    @Autowired
    protected MultipartHttpServletRequest request;

    @Autowired
    protected Model model;

}

@Controller
public class SigninController extends AbstractController {

    @RequestMapping(value = "/signin", method = RequestMethod.GET)
    public String signin(@ModelAttribute User user) {
        // do stuff with user (parameter)
        // do stuff with model (attribute) <--
        // do stuff with request (attribute)
        return "/signin/index";
    }

}

But when calling the URL, an exception is thrown:

...Could not autowire field: protected org.springframework.ui.Model...
...No matching bean of type [org.springframework.ui.Model] found for dependency...

I got the same error when using org.springframework.ui.ModelMap.

Any solution of genious?

Thanks for helping :)

Was it helpful?

Solution

I finally found a solution. I'm not sure the game is worth it, but it works :)

First, add those stuff in your AbstractController:

public abstract class AbstractController {

    @Autowired
    protected MultipartHttpServletRequest request;

    protected ModelMap model;

    public void setModel(ModelMap model) {
        this.model = model;
    }

    public ModelMap getModel() {
        return model;
    }

}

Then, create an interceptor implementing org.springframework.web.servlet.HandlerInterceptor like this one:

public class UserContextInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {
        if (handler instanceof AbstractController) {
            AbstractController controller = (AbstractController) handler;
            controller.setModel(new ModelMap());
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        if (handler instanceof AbstractController && modelAndView != null) {
            AbstractController controller = (AbstractController) handler;
            modelAndView.addAllObjects(controller.getModel());
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }

}

Finally, add these lines in your applicationContext.xml:

<mvc:interceptors>
    <bean class="path.to.my.just.created.UserContextInterceptor" />
</mvc:interceptors>

And of course, make your controllers implementing your AbstractController.

Here it is! You need to specify neither your request nor your model within your controllers methods parameters anymore :) I'm not really convinced of the usefulness of that trick though, but yeah. If it can make maniacal developers happier :)

Still open to easier solutions though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top