Failing to #AutoWire a member in a #WebServlet - java

I can't seem to get my servlet's fields to #AutoWire; they end up null. I have a pure annotation-configured webapp (no XML files). My servlet looks like this:
#WebServlet("/service")
public
class
SatDBHessianServlet
extends HttpServlet
{
#Autowired protected NewsItemDAO mNewsItemDAO;
}
Other #AutoWired things seem to work fine, both #Service objects and #Repository objects. But not this one, and I can't figure out why. I even tried adding its package to the ComponentScan(basePackages) list for my other classes.
Additional Info:
I added the following to my servlet’s init() method, and everything seemed to wire up properly, but I'm confused as to why Spring can't wire it up without that.
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, inConfig.getServletContext());

Servlet are web components that are not being created by Spring container, based on that lifecycle is not managed by the container and a lot of stuff that spring provides such as autowired or aspect can not run from them.
You need to indicate to the spring container that a component was created outside of IoC container and need to be part of it.
And as the API said SpringBeanAutowiringSupport is for:
Convenient base class for self-autowiring classes that gets
constructed within a Spring-based web application
This generic servlet base class has no dependency on the Spring ApplicationContext concept.
There is another way to indicate servlets being created by spring container using an interface

Spring MVC uses the DispatcherServlet for handling all requests in a Servlet environment.
The DispatcherServlet accordingly forwards the requests to the appropriate #Controller class (if any) based on the #RequestMapping on that class and/or it's methods.
What is happening in your Servlet is that it is not managed by Spring (but by the Servlet container) and there for no injection of dependencies is occurring.

Related

Spring : Configuration of both MVC and WebSocket in one web app

I'm currently working on a Spring web application which makes use of both Spring MVC and Spring Websocket. The configuration is annotation based. I'm using the AbstractAnnotationConfigDispatcherServletInitializer class as initializer, and I am confused about the servlet mappings I should provide, and the way I should do so.
I'd like to have all my MVC controller mapped under "/webservices/" path, and my Websocket endpoint to be under "/websockets/".
Among my #Configuration classes, one is dedicated to configure Spring MVC (#EnableWebMVC) and another one is dedicated to Spring WebSocket (#EnableWebSocketMessageBroker).
I implemented my initializer as follows :
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {WebMVCConfiguration.class, WebSocketConfiguration.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/webservices/*","/websockets/*"};
}
Also please note that I imported all of my configuration classes through the use of #Import on my Root Configuration class. I'm not sure if I should import the MVC and Websocket configuration though, as I already declared them in the getServletConfigClasses() method... But I did.
Anyway, It worked fine this way until now. But I recently added the use of #PropertySource annotation to my app (To inject my app properties through the use of #Value("${}") expressions), and thanks to that I noticed that at least the WebSocket Configuration class is ... scanned (?) twice : The first time with the #Value field value properly injected, but not the second time (Which caused an error).
While troubleshooting I noticed that I don't have this "double scanning" problem when I remove the WebSocketConfiguration class from the getServletConfigClasses() method : it is scanned only once, with the property valye properly injected. What surprised me is that even without declaring the WebSocketConfiguration in getServletConfigClasses(), the "/websockets" endpoints still works ! My guess is that it is scanned thanks to the #Import on my Root config class... but then how Spring knows it should bind the WebSocketConfiguration to the "/websockets" path ?
All of this made me wonder about my understanding of when / how I should import configurations classes. So here are my questions :
Do I really need to declare two servlet mappings to keep my services and websockets paths separated as they are ?
Is it necessary to declare as much Servlet Config classes as I have Servlet Mappings ? (Seeing how removing the WebSocketConfiguration class from getServletConfigClasses() didn't alter the WebSocket functionality... Or is it just a fluke ?)
Will Spring use the same DispatcherServlet for all the Servlet Config classes ? Or will it create one for each mapping I provide ?
From what I tried it looks like Spring cannot inject properties through the use of #Value in the configuration classes provided thanks to getServletConfigClasses()... It works only when it is imported via #Import, or a standard component scanning. Does it seems logical to you ?
Thanks for your help !

Controller beanPostProcessor spring - not singleton?

I have a custom beanPostProcessor that is supposed to do some logic with spring controllers.
I found out that it behaves funny. When I sysout controller bean in my post processor it says:
...controller.MassUploadController#743479ce
but when I call sysout(this) from controller request itself it is a different instance:
...controller.MassUploadController#58469848
So any changes I perform to controller instance in beanPostProcessor are not really reflected in runtime since it is a different instance. How is that possible? It states everywhere that spring controllers are singletons!
My controllers are defined in spring with #Controller and in xml I use componentScan on controller. java package

JSF and CDI with inputFile component

I made a simple xhtml page for upload file by using <h:inputFile> component. And everything works fine. And in managed bean I used dependency injection for the Logger. I used a factory class and createLogger() method in, to enable injection for object of Logger class.
Everything is ok but, nothing works without a #Model annotation in managed bean.
Can somebody explain the meaning of the #Model annotation.
I can not find on internet proper explanation. A founded explanation of other annotation like as #Session, #Request, #Application etc.
What does the #Model annotation do?
Hej vmaric,
#Model == #RequestScoped + #Named
It exposes the Backing Bean directly to your JSF 2 or JSP and its context will be destroyed after the end of the servlet request.
So it should not be used for entities.
Here is a hint from the Weld Reference Guide:
Notice the controller bean is request-scoped and named. Since this combination is so common in web applications, there's a built-in annotation for it in CDI that we could have used as a shorthand. When the (stereotype) annotation #Model is declared on a class, it creates a request-scoped and named bean.

Spring mvc on application load event to load collection

I have to load something from the database to initialize a hashMap object that I want to add to a application wide variable that all my mvc controllers can access.
I won't be modifying this object, and I don't care if it can only be updated when the application reloads.
Does spring MVC have a place where I can do this and have spring manage the lifecycle also?
I know servlets has the WebListener annotation:
#WebListener
But not sure if spring has this also (wrapped in their iOc container).
I think the best place is to declare a bean like the following:
public class MyInitializingBean {
#PostConstruct
private void init() {
//do initialization here
}
}
Then you declare that bean in your xml file, if you don't like the annotation, there are non-annotation approaches for initializing a bean, but that gets executed when the spring context starts.

Using Spring in standalone apps

I am learning Spring and I have a question regarding how you use it in standalone applications (and also when using it for making web applications). The examples I have been coded so far has used a simple main method where I retrieve beans by calling getBean on the. Context object. However, you probably want to do this in multiple classes so do you first get a context and then call getBean or are there other cleaner alternatives? Or is this the way you do it in standalone and web apps?
If you're calling context.getBean() everywhere, you're probably missing the whole point of Spring, which is a dependency injection framework.
In a standalone app, you typically call context.getBean() only once (or at least, very rarely), in order to get a "root" bean. This bean is injected by Spring with other beans, and so on.
In a web app, it all depends on which framework you use. But typically, you register a listener in the web.xml which loads the context for you, and controllers are created and/or injected by Spring.
You're on the right lines. Your main method will initialise your application context as you've discovered. The trick then is to use that app context to create the entry point to your application. That bean, having been created with spring will have been wired for you..
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class ApplicationMain {
public static void main(String[] args) {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/META-INF/spring/applicationContext.xml");
MyApplication app = BeanFactoryUtils.beanOfType(ctx, MyApplication.class);
app.init();
}
}
One class (your main class, probably) has to be Spring-aware to create the context. All other classes can continue to be wired together via Spring and do not need to be Context-aware.
It kind of depends on the application you are writing, but you should limit getBean() invocations to minimum, preferably one. You are fetching the first bean directly from the context and put the rest of the logic in the beans themselves. Something along the lines:
Bootstrap boot = context.getBean(Bootstrap.class);
boot.start();
And all the rest of your application logic is taking place within start(). It can create threads, listen for events, etc.

Categories