How #RequestMapping internally works in Spring Boot? - spring

#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.

Related

Spring MVC: How autowiring of HttpSession works?

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
}

How to inject a Spring bean in to Camel DefultProducer

I have written a camel component by extending DefaultComponent and also have the associative classes implemetation for endpoint, consumer, producer. My producer is extending the camel DefaultProducer and I want to inject a spring bean inside this class, so that whenever a route will be executed like
<route id="myRoute"><from uri="file://inbox"/><to uri="myComp://outbox"/>
I will be able to get the file from the file system and store it into database. For storing the file into the DB I have a service class instantiated by the spring container, but whenever I inject that bean into MyProducer we are getting null.
I recongnized the problem was not about Camel, it is related to the spring and I was injecting the bean in a wrong way. I resolved the problem by implementing the ApplicationContextAware interface into my helper class and storing the spring context as static variable and with the help of this helper class I am able to get spring bean inside MyProducer class. Thanks for spring ApplicationContextAware interface.

#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

jsf2 spring managed bean calling constructor and postconstruct only on tomcatstartup

I am using JSF+Spring project my spring maanged bean is ViewScoped
my saving state is client.
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
Following is my bean i found that constructor of bean and postconstruct method got call only on tomcat startup when it is spring managed bean instead if it is JSF managed bean constructor and postconstruct got call on every page refresh.
Is it the real behavior if i want to call method on page refresh every time under spring managed bean what should id do ?
#Component
#ViewScoped
public class DataTableBean implements Serializable{
public DataTableBean() {
super();
}
#PostConstruct
private void loadDataData(){
System.out.println("Post constructing");
}
}
The #Component is a Spring specific annotation to manage beans by Spring. The #ViewScoped is a JSF specific annotation to specify the scope of a JSF managed bean #ManagedBean. JSF specific scope annotations does not work on a Spring managed bean at all. You should use the Spring specific #Scope annotation instead.
So, either just manage the bean by JSF:
#ManagedBean
#ViewScoped
Or homegrow a Spring "view" scope (this is namely not one of the default scopes available in Spring):
#Component
#Scope("view")

Resources