Spring MVC: How autowiring of HttpSession works? - spring

I would like to know how autowiring of HttpSession works.
If we declare like below:
#Autowired
private HttpSession httpSession;
When exactly in the Spring workflow, httpSession variable declared above will be initialized with request.getSession(true)?

I don't understand why you want to autowire HttpSession but here is how autowiring works.
To Autowire a class you need to specify it as a bean either by using annotations (#Controller, #Service, #Repository, #Component) or by declaring #Bean in config class. Once you define a bean Spring autowires or constructs the objects when the spring context initializes (during server startup for webapp and you explicitly initialize spring context in case console/standalone app).
Since HttpSession can only be fetched from HttpServletRequest object, you cannot initialize it during application startup because there is no HttpServletRequest during startup. If you want some logic to implement before fetching the HttpSession you can create a util method like this
public getHttpSession(HttpServletRequest request) {
// put your logic here and return session object
}

Related

Spring Boot HttpServletRequest Request Scope Bean?

It would seem that HttpServletRequest is a request scope bean, but I have not yet been able to find any documentation on this.
Does anyone know where this is documented or where in the code base it is created?
The HttpServletRequest is normally created and managed by servlet container (e.g. Tomcat) but not Spring. You normally do not need to define it as a spring bean unless you are doing something special. So technically from the spring 's point of view, the HttpServletRequest does not have any scope as it is not a spring bean.
But even if you need to define a HttpServletRequest bean for some reason, by default it will be in the singleton scope. (see the scope table in this).
The relationship between HttpServletRequest and a request scope bean is that Spring will make sure whenever the servlet container process a new HttpServletRequest , it will create a new request scope bean instance in case you need to access it during processing this HttpServletRequest. And this request scope bean will be destroyed after the servlet container finish process that HttpServletRequest. Such behaviour is also mentioned in the above link as :
Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext

How #RequestMapping internally works in Spring Boot?

#RestController
#RequestMapping("/employee")
public class Employee {
#RequestMapping("/save")
public void saveEmployee() {
// saving employee
}
}
How does #RequestMapping will work internally to map the request to the saveEmployee method?
During application startup, Spring will identify all Beans by way of XML Config, Java Config, or Component Scanning and store them in the ApplicationContext.
Spring Boot autoconfigures many Beans for you, including RequestMappingHandlerMapping.
When this Bean is initialized it scans the ApplicationContext for any Beans annotated with #Controller.
Then it iterates over each Controller bean and looks for methods annotated with #RequestMapping. Finally it persists these mapping/handler pairs in the MappingRegistry
The DispatcherServlet is the central HTTP request handler for your application and it will search the ApplicationContext for any Beans that implement the HandlerMapping interface, which the RequestMappingHandlerMapping Bean does (by way of inheritance).
Then it iterates over these beans asking them to resolve the corresponding handler for this request. The RequestMappingHandlerMapping bean will resolve the handler by searching its MappingRegistry.
When a match is found, the handler method is eventually invoked.

Using session-scoped object in singleton in Spring

I have a problem with one of my beans. I have a bean, which has a singleton scope and second bean which has session scope.
I'm using java based config in my spring app, I added proxy mode to my session scope bean, but it throws exception when I'm tryign to use that (session scoped) bean:
Method threw 'org.springframework.beans.factory.BeanCreationException' exception. Cannot evaluate my-bean-full-name$$EnhanceBySpringCGLIB#ID.toString()
From what I have read here http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-other-injection-proxies
I thought that only thing which I have to do is to add
#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
to my bean class (which also has #Component annotation and it is scanned by Spring)
The thing which I was missing was this line in my web app initializer:
servletContext.addListener(new RequestContextListener());
After that, bean has been injected

#ControllerAdvice with #Autowired dependency not being injected

Anyone knows how to inject a dependency to a #ControllerAdvice?
My #ControllerAdvice extends Spring's ResponseEntityExceptionHandler and implements no interfaces.
The #ControllerAdvice gets called correctly, but the #Autowired dependency is never injected. There are no startup injection errors, the dependency is simply null.
I guess it has to do with how Spring proxies the #ControllerAdvice with cglib so that the #Autowired annotation gets lost.
I tested by implementing an interface, so that Spring could create a JDK proxy but it didn't work either. Actually with an interface, it didn't even gets called at all... even if I also annotate the interface with #ControllerAdvice.
Is there a way to specify that Spring should use JDK proxies for that particular case?
EDIT: I'm using Spring 3.2.4.RELEASE, by the way.
Sample class:
#ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {
#Autowired(required = true)
public AuditService auditService;
#ExceptionHandler(value = { RuntimeException.class })
public final ResponseEntity<Object> handleRuntimeException(Exception ex, WebRequest request) {
// auditService is null here!
}
}
In your case your bean is behind a CGLIB proxy.
It creates a subclass of your bean and as the method has final modifier it can't change the behavior of the original ResponseEntityExceptionHandler class to insert a call to the bean behind - please check my other answer about CGLIB.
CGLIB proxy is a different object that delegates the method calls to the original bean.
Please note that it would not be possible to implement much of Spring functionality only with subclassing i.e. without this separation of objects. How would it work when singleton-scoped bean references a session-scoped bean - obviously there are many session-scope beans and only one singleton-scoped bean.

Why #Resource can't work in HttpServlet?

I am tiro to Spring, and want to use auto wire with annotation #Resource in my servlet.
In service layer and dao layer, this annotation works well, when I use it in my Servlet, the exception comes:
com.fruit.action.merchant.MerAdd.service name='merAddService' is an unknown #Resource
as you see, MerAdd is a servlet extends my own BaseServlet which extends HttpServlet, service is an object of MerAddServie, in MerAdd servlet:
#Resource(name="merAddService")
private MerAddBusiness service;
public MerAddBusiness getService() {
return service;
}
public void setService(MerAddBusiness service) {
this.service = service;
}
Is there anything I should do to fix this problem, mybe I misunderstand #Resource, can you help me , thanks ahead~
Unfortunately You cannot autowire using #Resource annotaion in Servlet.
Same Question is discussed in this spring forum link
Problem:-"The problem here is that some J2EE components have dependencies injected into them by the web container. Which means that #Resource() annotations won't work -- the container will try to resolve those dependencies to JNDI (or somewhere else)."
Possible Workaround:-
As you can use #Autowired annotation in your servlet
So You can delegate request processing to the dedicated bean which will have #Resource Bean autowired in it , i.e. make your servlet to be just an entry point that conforms to the API supported by servlet container. Hence, you can configure that actual business logic holder bean as necessary via spring and just retrieve it from IoC container and call necessary method from the servlet

Resources