Spring MVC #PreDestroy method not working - spring-mvc

I am using #controller in my controller class which internally creates bean. For this controller I need to use #postConstruct and #preDestroy methods, #postConstruct is working fine but #preDestroy is not working. It means Bean is not destroying. So how can I destroy bean in spring MVC(annotation based)(I am not using ApplicationContext).
Correct me if my assumption was wrong.

WHen you say you dont use application context, do you mean to say that you are not using xml based configuration and are using java annotation config?
With spring mvc controllers, #PreDestroy annotated method will be called on session expiry (unless it's prototype scoped)
Here is a post #PreDestroy on Session-scoped Spring MVC Controllers
Here is a good explantation on spring bean life cycle http://www.journaldev.com/2637/spring-bean-life-cycle-methods-initializingbean-disposablebean-postconstruct-predestroy-aware-interfaces

I found out that if I set the bean scope to singleton, I can get PreDestroy called but not if I set it to prototype.

Related

how to log the request information using logback for very method annotated with #RequestMapping in a spring mvc controller?

Right now I am using logback for logging in one spring mvc project. And I need to log every request against the controller. There are quite a lot of methods in the controller and they are annotated with the #RequestMapping. I am thinking if there is a way to make the log automatically with Aspectj or something which is already built-in in SpringMVC framework. Someone who knows it?
#RequestMapping(value = "accounts/", method = RequestMethod.GET)
public Collection<DTOWithAccountInfo> getAccounts(final HttpServletRequest request) {
//todo:log the request info for
}
so I want to log the request info like URI for example for very #RequestMapping annotated method in spring mvc, maybe AOP is a good point to start with?

spring MVC errors : Could not instantiate bean class [org.springframework.data.domain.Pageable]: Specified class is an interface

I want to pagination in Spring MVC but getting error :
Could not instantiate bean class [org.springframework.data.domain.Pageable]: Specified class is an interface . Anyone can help? thanks!
To resolve Pageable parameters, Spring MVC uses a component called a HandlerMethodArgumentResolver(reference here). Specifically for Pageable as parameter, HandlerMethodArgumentResolver used is org.springframework.data.web.PageableHandlerMethodArgumentResolver, this can be registered using Java Configuration by just adding the #EnableSpringDataWebSupport annotation.
More options are available here: http://docs.spring.io/spring-data/data-commons/docs/current/reference/html/#core.web

How does the web container manage the lifecycle of a spring controller

If i write a simple servlet application, in my servlet class i extend the http servlet. This lets the container know that my class is a servlet and it will manage the 'lifecycle' of the servlet. init, doget(), destroy() etc.
But the Spring MVC framweork controller class does not extend any servlet class. it is jsut a POJO with it s own custom methods. Now I can call those methods individually using Requestmapping.
But will this spring controller class be 'mananged' by the container in a same way a servlet lifecyle is managed?
But will this spring controller class be 'mananged' by the container
in a same way a servlet lifecyle is managed?
Not directly. Then entry point of a Spring MVC application is typically a DispatcherServlet*. This class extends (not directly, but through inheritance) HttpServlet. You declare it as you would any other Servlet, typically in web.xml.
However you don't declare it by itself. You provide a Spring ApplicationContext from which the DispatcherServlet can go and get the #Controller annotated classes it will use to handle requests.
The DispatcherServlet handler stack is pretty big. There are many components involved. The official Spring MVC is an excellent document. You should read it.
*I say typically because Spring provides other handlers, HttpRequestHandler for example.
Additional Reading:
Spring MVC and Servlets 3.0 - Do you still need web.xml?
What happens behind the scenes of deploying a Spring MVC application to tomcat outside of eclipse?
What's the difference between #Component, #Repository & #Service annotations in Spring?
Spring MVC: difference between <context:component-scan> and <annotation-driven /> tags?
Difference between <context:annotation-config> vs <context:component-scan>
ContextLoadListener and DispatcherServlet

When, exactly, #Inject annotation initiates injection of SessionScoped bean in Servlet?

I need to modify a user session object (SessionScoped bean - CDI) in a Servlet, so I have to obtain that bean somehow. I used injection in the following way:
#Inject
private UserSession user;
where UserSession is the SessionScoped CDI bean. user methods are called from either doPost or doGet servlet methods.
This works perfectly; every time the #Inject annotation injects the appropriate UserSession bean, but I don't understand how this behavior is achieved.
I assumed that the beans, annotated with #Inject, are injected only once (when the object - Servlet instance in this case - is created), but it is obviously a wrong presumption.
So, when are these beans injected into the servlet? Per request? And how does this approach avoids conflicts (one servlet instance - multiple threads to deal with it) when there are multiple UserSession objects?
The CDI uses the proxy pattern. The injected instance is actually not the real instance, but a proxy which locates the real instance depending on the current context and delegates all methods to it (like as how EJBs work). The autogenerated class of your UserSession bean looks roughly like this:
public UserSessionCDIProxy extends UserSession implements Serializable {
public String getSomeProperty() {
UserSession instance = CDI.resolveItSomehow();
return instance.getSomeProperty();
}
public void setSomeProperty(String someProperty) {
UserSession instance = CDI.resolveItSomehow();
instance.setSomeProperty(someProperty);
}
}
This mechanism allows you to inject instances of a narrower scope in instances of a broader scope and allows you to still get the expected instance in the current context. The standard JSF #ManagedProperty annotation doesn't support it, simply because it does not use a proxy, but injects the desired instance directly. That's why it's not possible to inject something of a narrower scope by #ManagedProperty.
See also:
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Get JSF managed bean by name in any Servlet related class
When using #EJB, does each managed bean get its own #EJB instance?
How to choose the right bean scope?
Your answer lies in the C of CDI, which stands for Contexts.
What happens is that not the actual bean is injected, but a proxy. This proxy is contextual and resolves to the actual session scoped bean depending on the context of the caller on who's behalf the proxy is executed.

How do I get Web.xml context-param values in controller action method?

This feels like a basic question, but I haven't had much luck Googling.
My app connects to an SMTP server and sends mail through it. I need this SMTP server to be configurable based on which environment the app is deployed to.
How can I specify the specify the SMTP server name in my web.xml config file and access it from my Spring MVC 3.0 controller?
The controller does not extend or implement anything. It is completely annotation driven with #Controller and #RequestMapping. From what I have seen online, people access context-params via the servlet API. Being annotation driven, I do not have access to the servlet object.
I solved this.
Make your controller implement ServletContextAware, which requires a method called
setServletContext(ServletContext servletContext)
Spring MVC will inject the servlet context into this method if your controller is ServletContextAware.
Create a private variable on your controller to store the servletController that is injected into the above method. You can now use servletContext just as you would if you were using a regular servlet.
hth.
Adding an instance of Servletcontext and autowiring it worked for me
#Controller
public MyController {
// other instances relevant to your requirement
#Autowired
private ServletContext sCtx;
//other methods relevant to your requirement
}
I suppose following also should work:
void action(final HttpServletRequest request) {
final paramValue = request.getSession().getServletContext().getInitParameter("paramName");
...
}

Resources