How to wait until a different servlet is initialized in Spring - java

I have a Spring MessageListenerContainer added to a legacy application that initializes all it's services via a servlet (ie upon startup). The problem is that I need this servlet to be fully initialized (and thus have created a series of services modeled as singletons), however in my listener I get a NullPointerException. My approach is to set the load-on-startup of the first servlet to a lower number than the spring servlet, which should ensure that the former has been initialized. Then in my listener I have a an init method decorated with #PostConstruct which gets the references to my services, so something like:
this.userService = LegacyContext.getInstance().getManager().getUserService()
where the userService has been created in the servlets init() method. Problem is it doesn't seem to be initialized (it's null). What I've tried:
in the messageListener add an #Autowired WebApplicationContext, the idea being that the messageListener should only be created once the WebApplicationContext has been created (and thus the legacy servlet been created)
created another bean which has an autowired WebApplicationContext, and add that as a dependency to the messageListener, a variation of the approach above.
created a reference to the service beans in applicationContext.xml and added depends-on to the bean above
I eventually do get a reference to the service after everything is loaded, but I don't understand why it's not available in the messageListener? The first servlet should have been initialized by the time it gets to the listener, because of the dependency.

Related

Do multiple thread request share same singleton beans in Spring?

I have been trying to understand spring beans. As per my understanding, by default all beans are singleton and a singleton bean with lazy-init property set to true is created when it is first requested and singleton bean with lazy-init property set to false is created when the application context is created.
So, in an application, when a user request comes in ( where each request is a separate thread), do all these threads share the same singleton beans when requested within the program/class?
Yes, if the bean is created with default scope, the bean is shared across threads. However, another scope can be used to achieve the behaviour you mentioned.
See: https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch04s04.html?
Yes, by default (scope == 'singleton'), all threads will share the same singleton bean. There are two other bean scopes, session and request, that may be what you're looking for. The request scope creates a bean instance for a single HTTP request while session scope maintains a unique bean for each HTTP Session.
For a list and description of all of the Spring bean scopes, check out: Spring bean scopes
The best way to understand this is to understand how #Autowired annotation works.
Or in other words to understand "Spring Dependency Injection".
You said, "
by default all beans are singleton
We use #Autowired when injecting one layer into another between two layers.
If exemplify: Suppose, I want to inject UserService UserController. UserService is a Singleton bean. Creates an instance from UserService and Stores its cache. When we want to inject this service with #Autowired annotation. This annotation brings the UserService stored in the cache.
In this way, Even if we do this inject operation in many classes.#Autowired inject an instance of UserService with singleton bean instead of dealing with one UserService at each time. It saves us a big burden.
This is the fundamental working logic of Spring Singleton Bean.
Also, Spring Ioc Container manages this whole process.

Spring bean creation lifecycle : Why having multiple interaction points?

I'm learning spring and I'm stuck with the bean lifecycle !
When creating a bean, spring gives us several maners to interact with it. We can use one or all of :
BeanFactoryPostProcessor
BeanPostProcessor#postProcessBeforeInitialization
#PostConstruct
InitializingBean#afterPropertiesSet
#Bean#initMethod
BeanPostProcessor#postProcessAfterInitialization
Spring calls them in the order above
My question is : why all these points of interaction ? and when to use each of them (the use case) ?
A BeanFactoryPostProcessor and a BeanPostProcessor are quite different beast and also apply to different things.
A BeanFactoryPostProcessor will operate on the metadata for a bean (I like to call it the recipe) and will post process that. A well know example is the PropertySourcesPlaceholderConfigurer which will inject/replace all #Value in configuration with the value. A BeanFactoryPostProcessor operates on the metadata and thus before any bean has been created.
The BeanPostProcessor can be applied to a bean and can even replace a bean. Spring AOP uses this quite a lot. An example is the PersistenceExceptionTranslationPostProcessor, when a bean has been created it will pass through this BeanPostProcessor and when it is annotated with #Persistence the bean will be replaced by a proxy. This proxy adds exception translation (i.e. it will convert JpaException and SQLException to the Spring DataAccessException). This is done in a BeanPostProcessor. And can be be done before the init-callbacks are called (the postProcessBeforeInitializationor after they have been called thepostProcessAfterInitialization). The PersistenceExceptionTranslationPostProcessorwill run in thepostProcessAfterInitialization` as it needs to be certain the bean has been initialized.
The ServletContextAwareProcessor will run right after the object has been created to inject the ServletContext as early as possible as the initializing of a bean might depend on it.
The 3 callbacks for initializing a bean are more or less the same but are called in sequence because they have been included in later versions. It starter with only an interface InitializingBean and init-method in xml (later also added to #Bean and the annotation support was added when annotations became a thing.
You need init methods to initialize a bean, you might want to check if all properties have been set (like a required datasource) or you might want to start something. A DataSource (especially a connection pool) is a good example to initialize. After all dependencies have been injected you want to start the pool so it will open the connections. Now as you probably cannot modify the code you want to use the init-method if you control the code you probably want to add #PostConstruct. If you are writing an framework that depends on Spring I would use the InitializingBean.
Next to those 3 init methods you also have the destruction counter-parts. The DisposableBean interface (and destroy-method) and the #PreDestroy annotation. Again when you stop your application you also want to close the connections in your connection pool and you want to probably call the close method on the DataSource. A perfect sample of a destruction callback.

spring-boot - Which piece of code actually register dispatcher servlet for springMVC?

I am trying to find out in spring-boot, which implementation of WebApplicationInitializer actually register the dispatcher servlet.
I didn't found any piece code from SpringBootServletInitializer or its parent types did that.
Instead, AbstractDispatcherServletInitializer does the job, but it's abstract, I can't find any of its concrete implementation with help of Eclipse.
So, which piece of code from which class is actually invoked to register the dispatcher servlet for springMVC?
This is a subsequent question of: How does spring-boot able to serve specific url?
Below is the description of Spring Boot initialization steps that eventually register DispatcherServlet.
Example Code
#EnableAutoConfiguration
public class TestSpring {
public static void main(String[] args) throws Exception {
SpringApplication.run(TestSpring.class, args);
}
}
Spring Boot Initialization Steps
Here are the steps:
SpringApplication.run() creates EmbeddedWebApplicationContext application context;
Calls its refresh() method;
Refresh process reads annotations of the starting class TestSpring. It looks for import annotations. EnableAutoConfiguration is one of them. For an import annotation the refresh process gets the corresponding class from the annotation value and invokes its selectImports() method;
In case of #EnableAutoConfiguration the corresponding class is EnableAutoConfigurationImportSelector whose selectImports() loads tons of other import selectors from the META-INF/spring.factories;
This process continues recursively. Also, all bean definitions, that are inside these import selectors, are read. I.e. it includes beans defined by a method with the #Bean annotation, i.e. beans that require the Spring context to call the corresponding method automatically to instantiate them;
The resfresh() continues and reaches onRefresh(), the createEmbeddedServletContainer() method is called inside;
Among read bean defitions at the previous step, beans implementing ServletContextInitializer are searched for and instantiated. One of them is the bean, defined by the DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration#dispatcherServletRegistration() method of ServletRegistrationBean type that extends ServletContextInitializer. As you can guess from the name of the class, such initializers add a given servlet (in this case DispatcherServlet) to a given ServletContext, when their onStartup() method is invoked;
A tomcat embedded server is created (not started completely yet). All found ServletContextInitializers at the previous step are passed to this tomcat initialization - this is where the onStartup() methods of those ServletContextInitializers are called and DispatcherServlet gets created and registered as servlet;
End of onRefresh() of application context;
The finishRefresh() is called where tomcat is finally started by TomcatEmbeddedServletContainer.start();
End of refresh() of application context and other final initialization steps;
The app is running.
When you look for something Spring Boot does during auto-configuration, you should look in the *AutoConfiguration classes. In this case, DispatcherServletAutoConfiguration.
If you want to deploy the Spring Boot application as a traditional WAR, then the Servlet 3.0 specification details how service providers can set it up so that the 3.0 compliant servlet container will automatically bootstrap any web assets (Servlet, Filter, ServletContextInitializer's) into the servlet container. The "magic" is accomplished in the spring-web dependency. If you un'jar it, you'll find file "spring-web/META-INF/services/javax.servlet.ServletContainerInitializer". Open the file and you'll see single line "org.springframework.web.SpringServletContainerInitializer". This class delegates to all classes that implement WebApplicationInitializer, more specifically their onStartup(ServletContext servletContext) method. There's one such concrete class I'm aware of in Spring Boot, namely SpringBootServletInitializer.

Looking up SessionContext in JBoss 7.2

For various reasons I need to perform a manual lookup of SessionContext. In JBoss5, the solution
InitialContext initialContext = new InitialContext();
SessionContext sessionContext = (SessionContext) initialContext.lookup("java:comp/EJBContext");
has served med well, but from JBoss 7 I instead get a
javax.naming.NameNotFoundException: EJBContext -- service jboss.naming.context.java.global.EJBContext
Has something changed in how context is looked up in JBoss 7.2, or is my deployment lacking anything vital? For reference, standard injection works fine, this is the only lookup that fails. Or am I doing something terribly wrong (besides performing a manual lookup of SessionContext)?
According to specification of Java EJB (this one is for EJB 3.2. but nothing changed about EJBContext from previous one, EJB 3.x), you can inject EJBContext into your components either using annotation #Resource or manually via lookup (section 11.15):
The container must make a component’s EJBContext interface available either through injection
using the Resource annotation or in JNDI under the name java:comp/EJBContext
Standard way of looking up for EJB resource is via EJBContext.lookup method but there is also JNDI way which is the only possibilities if you don't have already EJBContext:
Context initCtx = new InitialContext();
EJBContext ejbCtx = (EJBContext) initCtx.lookup("java:comp/EJBContext");
This is exactly what you did, so what is wrong? There are two things, which one I'm not sure about. First, with manually lookup it's sometime needed to assign resource to component with annotation at class level:
#Resource(name = "EJBContext", type = javax.ejb.EJBContext)
public class MyComponent {
...
}
but I'm not sure is it needed for EJBContext as well, I guess not. The second thing, more important and critical - according to specification once again:
EJBContext objects accessed through the naming environment are only valid within the bean
instance that performed the lookup.
this one is section 11.15.1, and the next one, section 11.15.2:
The Container Provider is responsible for providing an appropriate EJBContext object to the refer-
encing component. The object returned must be of the appropriate specific type for the bean requesting
injection or performing the lookup—that is, the Container Provider must return an instance of the SessionContext interface to referencing session beans and an instance of the MessageDrivenCon-
text interface to message-driven beans.
Those both mean that injection and lookup for EJBContext are only valid in Enterprise Java Beans, so those which are annotated with #MessageDriven, #Stateful, #Singleton or #Stateless (or described as EJBs in deployment descriptor file, also as EJB 2.x Specification). Maybe your component isn't valid EJB and it's why lookup isn't working? This is only suggestion of course.
There's one more possibilities to get EJBContext (more correctly SessionContext). Your component should implements SessionBean interface which has setSessionContext(SessionContext sessionContext) method. This method should be invoked by EJB container every time when component is used (injected somewhere, invoked by client or timeout, especially when it's created) and inside this method you should assign sessionContext parameter to bean's field.

Spring #Autowired and WebApplicationContext in Tomcat

#Autowired works only once.
What to do to make it wire the bean every time the Servlet is recreated?
My web-app (Tomcat6 container) consists of 2 Servlets. Every servlet has private fields.
Their setters are marked with #Autowired
In the init method I use
WebApplicationContextUtils
...
autowireBean(this);
It autowires the properties marked with #Autowired once - during the initialization of the Servlet.
Any other session will see these fields values, they will not be rewired after the previous session is destroyed.
What to do to make them rewire them each time a Servlet constructor is called?
a) Put the autowiring into the constructor?
Or better 2) get a web app context and extract a bean from there?
There seems to be some misunderstanding about how the container works. Servlets are essentially singletons, you don't get a new servlet everytime someone calls the server. Storing state in private fields on a servlet is pretty much an error.
What is the scope and life-cycle of the stateful part of your request processing? If it's just the life of the request then you can take whatever on your servlet is stateful and move it into another class. Then you can define a prototype bean for that class and use getBean at the start of the request to get a new one. If you want to start getting fancy you could write a filter that puts a new bean into a ThreadLocal at the start of each request.
If your state needs to span multiple requests, you need to start keeping state or a key that points to the state storage on the web session, or look into using a conversation framework.
Try using scope as prototype for that bean #Scope("prototype")
You may try to use #Scope("session")

Categories

Resources