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).
Related
I read the servlet-3.0 specification and have got one question about the ServletRequest object. Currenctly I have a filter chain
public class MyFilter implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
//do filter
}
}
after doing filters the javax.servlet.Servlet's
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
comes into play. Is it reliable that both in the filter's method and the service method operate on the same object reference? The servlet specification said this:
Each request object is valid only within the scope of a servlet’s
service method, or within the scope of a filter ’s doFilter
method, unless the asynchronous processing is enabled for the
component and the startA sync method is invoked on the request object
But it;s not obvious to me that the ServletRequest object is a singleton per one request handling.
Upd: To be more specific, I need to return the HttpSession instance within Filter's doFilter method and Servlet's do_HttpMethod_ method. Is it always the same? I mean httpServletRequest.getSession()
A container uses a single request object for a given request. However any filter can wrapper the request object so your filter or servlet may be getting a wrapper depending on what other filters do. Usually as an app developer you would know if this is the case. If no wrappers are used the filter and servlets get the same request object.
For info on request wrappers see:
http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequestWrapper.html
So when you call getSession() you may get the container implementation of the method or that provided by a wrapper. However note that an HttpServletRequestWrapper object provides a getRequest() method which returns the request object it wraps so you can recurse through wrappers until you get the original and then call it. Lots of examples how to do this on the web.
ServletRequest is an interface and the same is used in doFilter method as well as service method. So both are going to return the same session object (if you call getSession()).
Servlet as well as Filter uses same interface so it's going to behave same way. I am not sure why you are curious to know if it's singleton ? May be you can check servlet specification to know more about it.
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.
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 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!.
I will need to implement my own version of HttpSession in Java. I have found very little information which explains how achieve such a feat.
I guess my problem is - how do I override the existing HttpSession no matter the application server's implementation?
I did run across a quality but rather old read which helps me achieve my goal - http://java.sun.com/developer/technicalArticles/Servlets/ServletControl/
Are there any other approaches?
Its two ways.
"Wrapping" the original HttpSession in your own HttpServletRequestWrapper implementation.
I made this a short time ago for clustering distributed sessions with Hazelcast and Spring Session.
Here is explained pretty well.
First, implement your own HttpServletRequestWrapper
public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
public SessionRepositoryRequestWrapper(HttpServletRequest original) {
super(original);
}
public HttpSession getSession() {
return getSession(true);
}
public HttpSession getSession(boolean createNew) {
// create an HttpSession implementation from Spring Session
}
// ... other methods delegate to the original HttpServletRequest ...
}
After, from your own Filter, wraps the original HttpSession, and put it inside the FilterChain provided by your Servlet Container.
public class SessionRepositoryFilter implements Filter {
public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
SessionRepositoryRequestWrapper customRequest =
new SessionRepositoryRequestWrapper(httpRequest);
chain.doFilter(customRequest, response, chain);
}
// ...
}
Finally, set your Filter at the beginning in the web.xml to ensure it performs before any other.
The second manner to achieve it is providing to your Servlet Container your custom SessionManager.
For example, in Tomcat 7.
Create a new class, and implement HttpSession:
public class MyHttpSession implements javax.servlet.http.HttpSession {
// and implement all the methods
}
Disclaimer: I have not tested this myself:
Then write a filter with a url-pattern of /* and extend HttpServletRequestWrapper. Your wrapper should return your custom HttpSession class in getSession(boolean).
In the filter, use your own HttpServletRequestWrapper.
It doesn't seem like it's easily doable in a portable fashion that would work among different containers, since the HttpSession implementation is provided by the J2EE container.
However, to achieve a similar result, you can implement a javax.servlet.Filter and javax.servlet.HttpSessionListener and in your filter, wrap the ServletRequest and ServletResponse, such as described in Spring Boot with Hazelcast and Tomcat.