I have just started spring, I found that somewhere we are using handlerequest() method in controller and somewhere we are using handlerequestinternal() method.
I have tried google-ing this, but did not find any specific point.
Can any one explain what is the difference between these two functions and when we should implement each of them?
As I know spring framework will call by default handlerequest() function, so we can put our service layer there itself.
I am sure handlerequestinternal() must be providing some extra feature, but not sure.
Please help me to understand this.
Both handleRequest and handleRequestInternal are used by the old Spring 2.0 controller framework.
handleRequestInternal is used when you're extending one of the pre-supplied base support classes (e.g. AbstractController, SimpleFormController, etc). These use the Template design pattern, and you supply your business logic in that method.
handleRequest is the method specified on the Controller interface itself. If you directly implement that interface, rather than extending one of the above base classes, then you need to implement handleRequest directly.
Both are obsolete, and not used in controllers written for Spring 2.5 and later.
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
this.checkAndPrepare(request, response, this instanceof LastModified);
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized(mutex) {
return this.handleRequestInternal(request, response);
}
}
}
return this.handleRequestInternal(request, response);
}
protected abstract ModelAndView handleRequestInternal(HttpServletRequest var1, HttpServletResponse var2) throws Exception;
}
if in controller template classes like AbstractController and ParameterizableViewConterollers in this it will the child classes of Controller interface so spring peoples internally override the handleRequest method and call the abstract handleRequestInternal method so whenever we are using template classes we use this method otherwise we use the handleRequest() method only this the difference i think!.
Related
The getRequestDispatcher() method of ServletRequest interface returns the object of RequestDispatcher.
I know that getRequestDispatcher() method is in the Interface ServletRequest. As it is an interface, it won't define the method.
Furthermore, this interface is again inherited in another interface HttpServletRequest. But being an interface, it won't define its methods.
Now, after carefully checking the JavaDocs, I could not find any class that implemented either of these two interfaces, and defined the getRequestDispatcher() method.
So I was wondering where did they define this method
Thanks in advance.
The class which implements is org.apache.catalina.connector.RequestFacade , in case of TOMCAT container.
The implementation is basically dependent on containers & every container has its own implementation adhering to the J2EE Specs.
Use the below code to check the implementation class :-
public class TestServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws ServletException, IOException {
System.out.println(httpServletRequest.getClass());
}
}
Output :- org.apache.catalina.connector.RequestFacade
You can see this class Offical Doc here, and can check that it has implemented the interface javax.servlet.ServletRequest and its methods like getRequestDispatcher() etc.
Each container (Tomcat, Jetty, etc.) has its own class that implements HttpServletRequest. This class implements all the methods of the interface. An instance of this class is passed by the container to your servlet.
If you're really curious about it, add
System.out.println(request.getClass());
to your servlet, and you'll know the name of the concrete class.
But really, you don't need to know about it. All you need to know is that it implements the HttpServletRequest interface and thus fulfills the contract described in the javadoc and the specifications.
For jetty v6 it is org.mortbay.jetty.servlet.ServletHandler and its return org.mortbay.jetty.servlet.Dispatcher instance.
And this is how forward from Dispatcher works there:
It took original request, replace request url with new value
Clear output stream.
Execute request-responce pair via context.handle(request, responce)
Reset original value of request url for request.
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.
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.
I have made an annotation for aop. When I use it at any method rather than controller methods it works well. However when I use it at my controller's methods my controller stops working. It starts to give 404 not found error for mappings. I found a similar question here: Spring 3 MVC #Controller with AOP interceptors? but I don' know how to do it. My method at my controller is that:
#WebAuditable // This is my annotation that works at other methods
#Override
#RequestMapping(value = "/ad", method = RequestMethod.POST, headers = "Accept=application/json")
public
#ResponseBody
Cd create(HttpServletResponse response, #RequestBody Cd cd) {
...
}
My interface that my controller implements is that:
public interface BaseController<T> {
public List<T> getAll(HttpServletResponse response);
public T getByName(HttpServletResponse response, String id);
public T create(HttpServletResponse response, T t);
public T update(HttpServletResponse response, T t);
}
Any advices?
PS: #SeanPatrickFloyd says that:
Note When using controller interfaces (e.g. for AOP proxying), make
sure to consistently put all your mapping annotations - such as
#RequestMapping and #SessionAttributes - on the controller interface
rather than on the implementation class
The thing is: controller mapping is done at runtime, and if you use AOP proxies, the proxy objects don't have annotations at runtime, only their interfaces do. I can think of two possible strategies to work around this limitation.
Either annotate the generic interface methods, or (if you don't want to advise all controllers) create a sub-interface per implementation type, explicitly annotating their methods. I know that's a lot of rewritten code and contrary to what AOP is about, but I don't know a better way when sticking with interface based proxies.
Another way would be to switch to CGLib proxies using proxy-target-class="true". That way the proxy classes should (I'm not sure about this) retain the annotations.
Update: annotating your interface should work like this (if it works)
public interface BaseController<T> {
#WebAuditable
public List<T> getAll(HttpServletResponse response);
#WebAuditable
public T getByName(HttpServletResponse response, String id);
#WebAuditable
public T create(HttpServletResponse response, T t);
#WebAuditable
public T update(HttpServletResponse response, T t);
}
Annotating a base class won't work, because JDK proxies don't expose any information that's not backed by interfaces.