I am new to spring mvc. I am debugging a mvc code as given below
#Controller
#RequestMapping("/register")
public class RegisterController extends BroadleafRegisterController {
#RequestMapping(method=RequestMethod.GET)
public String register(HttpServletRequest request, HttpServletResponse response, Model model,
#ModelAttribute("registrationForm") RegisterCustomerForm registerCustomerForm) {
return super.register(registerCustomerForm, request, response, model);
}
#RequestMapping(method=RequestMethod.POST)
public String processRegister(HttpServletRequest request, HttpServletResponse response, Model model,
#ModelAttribute("registrationForm") RegisterCustomerForm registerCustomerForm, BindingResult errors) throws ServiceException, PricingException {
return super.processRegister(registerCustomerForm, errors, request, response, model);
}
#ModelAttribute("registrationForm")
public RegisterCustomerForm initCustomerRegistrationForm() {
return super.initCustomerRegistrationForm();
}
}
above is a spring handler class. for /register request i was thinking regsister() method should called but before this method inintcustomerRegisterationForm() is called i do not know why and how this method is called. I searched this in google but not find any useful information. I think this is like a interceptor method as in struts2. Please tell us how this method is called
Thanks
The initCustomerRegistrationForm() is being called because it is the 'model' of your controller. The model is typically always need for a get and post request for a specific form and represents the data entered into the form.
If you want your form pre-populated with some data, then you would add that data to the 'model'. The 'model' is also what is submitted to the post request then submitting a form.
According to spring documentation
#ModelAttribute methods are used to populate the model with commonly needed attributes for example to fill a drop-down with states or with pet types, or to retrieve a command object like Account in order to use it to represent the data on an HTML form.
A controller can have any number of #ModelAttribute methods. All such methods are invoked before #RequestMapping methods of the same controller.
Which explains why the initCustomerRegistrationForm() method is called before request mapping methods.
Related
I am currently setting up a Spring MVC application (version 4.1.4.RELEASE) and I want the application to return a JSON string on a 404 error rather than the default html response. I am using Tomcat 8 as my server. I have what I think should be correct, however it isn't behaving in the manner that I expect. What I'm trying to do is based off of this answer.
public class SpringWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
...
#Override
protected void customizeRegistration(ServletRegistration.Dynamic registration){
registration.setInitParameter("throwExceptionIfNoHandlerFound","true");
}
}
and then I have an exception controller (which is different than the question I based my solution off of, however I don't believe that is an issue as I am under the impression that #ControllerAdvice is an acceptable way to manage this based off of the Spring Docs. It looks something like:
#ControllerAdvice
public class GlobalExceptionController{
#ResponseStatus(value=HttpStatus.NOT_FOUND)
#ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public Message handleMethodNotSupported(HttpServletRequest request){
...
}
#ResponseStatus(value=HttpStatus.NOT_FOUND)
#ExceptionHandler(NoSuchRequestHandlingMethodException.class)
public Message handleBadRequest(HttpServletRequest request){
...
}
#ResponseStatus(value=HttpStatus.NOT_FOUND)
#ExceptionHandler(NoHandlerFoundException.class)
public Message requestHandlingNoHandlerFound(HttpServletRequest request){
...
}
...
}
It continues to send back the default response. I know for a fact that it is hitting my customizeRegistration() function because breakpoints stop it, however, any breakpoints that I have in my GlobalException class are not hit. Also, the GlobalException class is within a package that is hit by a #ComponentScan() annotation, so I am fairly confident that it is also being handled by spring.
I assume I'm missing something obvious, any help would be greatly appreciated.
I don't think the return type you're trying to use is supported. Have you tried changing your return value to ResponseEntity or adding a #ResponseBody annotation?
From the docs:
A ModelAndView object (Servlet MVC or Portlet MVC).
A Model object, with the view name implicitly determined through a RequestToViewNameTranslator.
A Map object for exposing a model, with the view name implicitly determined through a RequestToViewNameTranslator.
A View object.
A String value which is interpreted as view name.
#ResponseBody annotated methods (Servlet-only) to set the response content. The return value will be converted to the response stream
using message converters.
An HttpEntity or ResponseEntity object (Servlet-only) to set response headers and content. The ResponseEntity body will be
converted and written to the response stream using message converters.
void if the method handles the response itself (by writing the response content directly, declaring an argument of type
ServletResponse / HttpServletResponse / RenderResponse for that
purpose) or if the view name is supposed to be implicitly determined
through a RequestToViewNameTranslator (not declaring a response
argument in the handler method signature; only applicable in a Servlet
environment).
I am new to Spring MVC and went thru some tutorials on net.
Came across below code in one of handler class under my project.
When form is submitted for action userHistory , call goes to my below handler method
#RequestMapping(value="/userHistory", method=RequestMethod.GET)
public #ResponseBody UserDetails getUserHistory(Model model, HttpServletRequest request, HttpServletResponse response) {
model.addAttribute("userDetail", new userDetail());
}
Does DispatcherServlet construct empty Model object and pass to handler method getUserHistory?
Similarly when i submit for action "/userDetail" from my jsp, i get method parameter "userDetail" object filled with required data.
#RequestMapping(value="/userDetail", method=RequestMethod.POST)
public String userDetail(UserDetail userDetail, HttpServletRequest request, HttpServletResponse response, Locale locale)
{}
Is DispatcherServlet doing this or some other interceptor?
UPDATE:- JSP code snippet is
<form:form id="userForm" action="path/userDetail" method="post" commandName="userDetail">
Does DispatcherServlet construct empty Model object and pass to handler method getUserHistory?
Partially yes, an empty Model gets constructed, and its passed to the method getUserHistory. But its not really done by the DispatcherServlet, rather an implementation of HandlerMethodArgumentResolver (in the particular case a ModelMethodProcessor class). When the matching of the method is done, before the method is actually called another process takes place, that is argument resolving. The signature of the matched method is inspected, and objects of certain types known to spring get automatically resolved and injected by Spring. The types are defined in the docs, http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-methods check the list under subtitle Supported method argument types. All of the listed types, have a registered HandlerMethodArgumentResolver implementation that guides the creation of these objects
Is DispatcherServlet doing this or some other interceptor?
Picking up with the first answer, you can register your custom argument resolver. This great blog article tells you all you need to know to implement one. Note that UserDetail by what you have described could also be a form-backing bean, whose values are bound to the values of the input fields of the submitted form, here's an example http://www.codejava.net/frameworks/spring/spring-mvc-form-handling-tutorial-and-example
I use ModelAndView objects as all people do:
ModelAndView result = new ModelAndView("view");
result.addObject("requests", requestsService.getListByBackoffice(filter, page, Config.RECORDS_PER_PAGE));
But I noticed that I have a couple of objects that I use always in most of the views.. So the question is - is there any solutions to create some kind of default assigned objects that are passed to view automatically?
Thank you
You can register a HandlerInterceptor with your DispatcherServlet. You then implement the postHandle() method:
public class CustomInterceptor extends HandlerInterceptorAdapter /* which implements HandlerInterceptor */ {
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
modelAndView.addObject("myObject", new Object());
// add as many as you wish
}
}
NOTE: The ModelAndView object may be null. This may occur if your handler method was writing to the response body directly, for example with #ResponseBody.
Depending on the url pattern you used when registering the Interceptor, the postHandle() will get called and populate your model with any objects you want.
You can also register a servlet Filter (in web.xml or WebApplicationInitializer). The filter simply adds the request attributes before dispatching to the servlet.
public class CustomFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setAttribute("myObject", new Object());
chain.doFilter(request, response);
}
// ... init and destroy methods
}
NOTE: At some point during the request lifecycle, Spring adds all attributes in the model to your request attributes.
The disadvantage here is that you add the attributes whether or not your #Controller worked, as the Filter is called before Spring's DispatcherServlet. Also, the Filter is managed by your servlet container (workarounds exist) and therefore it's difficult to inject Spring beans into it.
first solution:
I have not tried such but can do like creating ModelAndView object in Constructor or somewhere which you call always, set object which you always want to pass as default there only.
call setViewName() in respective methods and add respective objects which you want to set.
second solution:
write one method which is adding that default object and call that method wherever you need (nothing but what interceptor do).
Sorry about the title. I couldn't think of a better wording.
Is there any way to set the default Model that Spring will supply the page without first retrieving it as an argument in the #RequestMapping method?
I'm using aspects to take the return value of controller methods(returning the view) and insert it into the model, then rendering a different global view which then includes what I added into the model. This works fine on methods that request the Model as a parameter.
However, I also want to be able to catch all methods that don't explicitly request the model and still insert the return value into it (via #AfterReturning advice). Any ideas?
I would not use the #Autowired on HttpServletRequest as it will confuse future developers working on the code of threadsafety.
Instead you should use either a #ModelAttribute or an Interceptor.
#ModelAttribute
See:
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args
But you can do something like this and add this method to your controller:
#ModelAttribute
public preloadModel(HttpServletRequest request, ModelMap model) {
//Add stuff to model.
}
Interceptor
See: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-handlermapping-interceptor
public class PreloadModelInterceptor extends HandlerInterceptorAdapter {
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView) throws Exception {
// add model attibutes for your view to see but not your controller
}
}
Well, I found a workaround. Or maybe it's all that the underlying Spring framework is doing anyway. I just autowired in the HttpServletRequest and called setAttribute. Seems to work fine.
In Spring MVC I have a controller that listens to all requests coming to /my/app/path/controller/*.
Let's say a request comes to /my/app/path/controller/blah/blah/blah/1/2/3.
How do I get the /blah/blah/blah/1/2/3 part, i.e. the part that matches the * in the handler mapping definition.
In other words, I am looking for something similar that pathInfo does for servlets but for controllers.
In Spring 3 you can use the # PathVariable annotation to grab parts of the URL.
Here's a quick example from http://blog.springsource.com/2009/03/08/rest-in-spring-3-mvc/
#RequestMapping(value="/hotels/{hotel}/bookings/{booking}", method=RequestMethod.GET)
public String getBooking(#PathVariable("hotel") long hotelId, #PathVariable("booking") long bookingId, Model model) {
Hotel hotel = hotelService.getHotel(hotelId);
Booking booking = hotel.getBooking(bookingId);
model.addAttribute("booking", booking);
return "booking";
}
In Spring 2.5 you can override any method that takes an instance of HttpServletRequest as an argument.
org.springframework.web.servlet.mvc.AbstractController.handleRequest
In Spring 3 you can add a HttpServletRequest argument to your controller method and spring will automatically bind the request to it.
e.g.
#RequestMapping(method = RequestMethod.GET)
public ModelMap doSomething( HttpServletRequest request) { ... }
In either case, this object is the same request object you work with in a servlet, including the getPathInfo method.