DispatcherServlet responsible for constructing this data for Handler? - java

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

Related

How the Spring MVC #Controller's handler methods' parameters are automatically resolved during run-time?

How does the DispatcherServlet (or any other bean, supporting Spring MVC infrastructure), dynamically, resolve the signature of the handler method of the #Component instance, and how does it know, what parameters/types are expected, in which order, in that method?
If I have a "#RequestMapping-ed" handler method, in my #Controller instance, defining any version of its signature:
public String f() {...}
public String f(Model model) {...}
public String f(HttpServletRequest, Model model) {...}
public String f(Model model, HttpServletRequest) {...}
public String f(SomeEntity se, Model model, HttpServletRequest, AnotherModel am) {...}
//so on..
would work fine, disregarding of parameter number, types, and order, which, eventually, are supplied with corresponding arguments, again - disregarding of their number, order and types.
There should be quite a work going underneath, to correctly instantiate expected arguments, pass them in a proper order, maybe even do some type-casting, if needed.. an so on, but I don't grasp the fundamentals of this.
I looked up the corresponding sources from spring-webmvc module, and sources of the DispatcherServlet; however, haven't got a firm grasp of the underlying mechanism.
I can guess, that some BeanPostProcessors could be involved.. doing reflective accesses, and so on.. but even in this case, as I'm not certain on what's happening, I would very much appreciate any valuable input.
In Spring MVC there are three implementations of HandlerMapping: BeanNameUrlHandlerMapping, SimpleUrlHandlerMapping and ControllerClassNameHandlerMapping.
You can read more about this subject here:
https://www.baeldung.com/spring-handler-mappings
I've not used Spring in years, but this post gives a pretty good step-by-step outline of the spring mvc request lifecycle
When the DispatcherServlet receives a request, it iterates over this list until it finds a matching handler object for the request in question. For simplicity, let's consider only RequestMappingHandlerMapping.
A bean of this type stores a mapping of #RequestMapping annotated methods (the actual Method object retrieved with reflection) stored as a HandlerMethod instances and wrapped in RequestMappingInfo objects that hold mapping data for matching the request, ie. URL, headers, and request parameters.
The DispatcherServlet retrieves the best matching HandlerMethod from these and any corresponding HandlerInterceptor instances which you may have registered. It retrieves these as a HandlerExecutionChain object. It will first apply any pre-handling by HandlerInterceptors. It will then try to invoke your HandlerMethod. This will typically (but not always) be a #RequestMapping annotated method inside a #Controller annotated class. This produces what Spring calls a dispatch result. The DispatcherServlet then applies post-handling by the HandlerInterceptors.

How does Spring container gives reference to interface or class type we pass as an arguments to method

I have been studying spring and spring mvc framework, and I am curious to know that how the spring container gives us the reference to whatever Interface or Class type we pass as an argument to our methods.
For instance, when we create a Servlet in a web application it extends HttpServlet so when we override the doGet or doPost method the web container instantiates the servlet and pass a reference to HttpServletRequest and HttpServletResponse objects to doGet or doPost methods as:
public class DemoServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//container gives reference to request and response object
}
}
The question that comes to my mind is how the spring container knows what object reference it need to instantiate i.e how does it scans the methods as our class does not override any Class or Interface method so that it can know that it needs to provide the reference to that object. As these class or interface types are not declared as beans in application context file. For instance:
#Controller
#RequestMapping("/")
public class ContactController {
#RequestMapping(value="savecontact", method=RequestMethod.POST)
public String saveContact(#ModelAttribute("contact") Contact contact, BindingResult errors, HttpServletRequest request, HttpServletResponse response) {
...
}
}
How does Spring provide reference to BindingResult, HttpServletRequest, HttpServletResponse objects and any other Spring or Servlet class or interface type that we pass to method as arguments? Does it have a list of default objects that it instantiates on the application start up or does it scans the methods?
When you annotate a controller method with the #RequestMapping, the parameters of the method will be a subject of the argument resolving process. An interface HandlerMethodArgumentResolver and its implementations are at the core of this mechanism. The interface holds two methods supports, and resolveArguments
In simple terms, all listed arguments are passed through a list of the default resolvers registered with RequestMappingHandlerAdapter (check the getDefaultArgumentResolvers method), if the resolver supports the type, a resolveArgument method is called and an instance is injected as an argument.
For the four types you've declared, the respective resolvers are
ServletModelAttributeMethodProcessor
ErrorsMethodArgumentResolver
ServletRequestMethodArgumentResolver
ServletResponseMethodArgumentResolver
all registered by default
Based on argument resolving mechanism, its also quite easy to add a custom resolver, that will instantiate and inject any custom type as well
As a follow-on to Master Slave's answer...about #ModelAttribute arguments
An #ModelAttribute on a method argument indicates the argument should be retrieved from the model. If not present in the model,
the argument should be instantiated first and then added to the model.
Once present in the model, the argument’s fields should be
populated from all request parameters that have matching names. This
is known as data binding in Spring MVC
"where" does spring find a #ModelAttribute method arg:
It may already be in the model
due to use of #SessionAttributes
due to an #ModelAttribute method in the same controller
It may be retrieved based on a URI template variable and type converter (explained in more detail below).
It may be instantiated using its default constructor.

how handler mapping works in spring mvc

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.

Spring JSR303-like validation with HttpServletRequest awareness

I am willing to incorporate JSR303-like validation, which would be aware of related HttpServletRequest.
For example, Re-Captcha requires to send IP of user who is solving the CAPTCHa alongside with challenge and response and for that i need something like HttpServltRequest.getRemoteAddr(), so for validating form, containing ReCAPTCHa with annotations/corresponding validators transparently for the controller (like, annotating POJO with something like #ReCaptcha) i need such instance in validation layer.
Ideally, i want to inject my validation logic between
[Http Servlet Request] -> [Jackson or similar data bind of request parts to POJO]
and
#RequestMapping("somewhere")
#ResponseBody
public Object login(#Valid #RequestBody LoginData loginData) {
...
}
call.
Which Spring facilities exists for implementing such validation?
I've found HandlerInterceptor concept which acts a bit before i wanted it to, right after forming HttpServletRequest, before binding of request data to objects seems to be happening.
Looks like i've found something usable:
In controller' class, add
#InitBinder
public void initBinder(WebDataBinder binder, HttpServletRequest request) {
binder.addValidators(new ReCaptchaValidator(request));
}
This #InitBinder-annotated method would be called before each controller #RequestMapping-methods. You could refine this selection by providing as annotation value a list of model attributes name to trigger on.
And ReCaptchaValidator is a mere implementation of org.springframework.validation.Validator interface.
Arguments, which could be used in this #InitBinder-method are, as documentation says, similar to #RequestMapping controller methods:
* <p>Such init-binder methods support all arguments that {#link RequestMapping}
* supports, except for command/form objects and corresponding validation result
* objects. Init-binder methods must not have a return value; they are usually
* declared as {#code void}.
*
* <p>Typical arguments are {#link org.springframework.web.bind.WebDataBinder}
* in combination with {#link org.springframework.web.context.request.WebRequest}
* or {#link java.util.Locale}, allowing to register context-specific editors.

How is used #RequestAttribute and #ModelAttribute annotation in this Spring MVC showcase example?

I am pretty new in Spring MVC.
In this period I am studying the Spring MVC showcase example downlodable from STS dashboard.
I am having some problems understanding how Custom Resolvable Web Arguments are handled in this example.
In practice I have the following situation:
In my home.jsp view I have the following link:
<a id="customArg" class="textLink" href="<c:url value="/data/custom" />">Custom</a>
This link generate an HTTP Request towards the URL: "/data/custom"
The controller class that contains the method that handles this request has the following code:
#Controller
public class CustomArgumentController {
#ModelAttribute
void beforeInvokingHandlerMethod(HttpServletRequest request) {
request.setAttribute("foo", "bar");
}
#RequestMapping(value="/data/custom", method=RequestMethod.GET)
public #ResponseBody String custom(#RequestAttribute("foo") String foo) {
return "Got 'foo' request attribute value '" + foo + "'";
}
}
The method that handles this HTTP Request is custom()
So when the previous link is clicked the HTTP Request is handled by the custom method...
I am having problems understanding what the #RequestAttribute annotation.
I think that, in this case, it binds the request attribute named foo to a new String foo variable.
But... where is this attribute taken from? Is this variable taken by Spring?
Ok...my idea is that this request attribute is taken from a HttpServletRequest object...
I think this because, in this class, I have also have the beforeInvokingHandlerMethod() method that have a speacking name...so it seems that this method seta an attribute, that have name=foo and value=bar, inside an HttpServletRequest object...and then so the custom() method can use this value...
In fact my output is:
Got 'foo' request attribute value 'bar'
Why is the beforeInvokingHandlerMethod() called before the custom() method?
And why is the beforeInvokingHandlerMethod() annoted by #ModelAttribute annotation? What does this case mean?
You are correct in assumption of #RequestAttribute, it need not be set in beforeInvokingHandlerMethod. Assume you have a method mapped to /data/init which forwards request to /data/custom. In this case request attribute can be set in init method also.
Why the beforeInvokingHandlerMethod() is called before the custom() method?
And why the beforeInvokingHandlerMethod() is annoted by #ModelAttribute annotation? what means in this case?
you will get the reason here
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-methods
An #ModelAttribute on a method indicates the purpose of that method is to add one or more model attributes. Such methods support the same argument types as #RequestMapping methods but cannot be mapped directly to requests. Instead #ModelAttribute methods in a controller are invoked before #RequestMapping methods, within the same controller.

Categories