Why refreshing the ApplicationContext immediately after its creation in WebApplicationInitializer? - spring-mvc

In https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html 11.1 there is an example:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletCxt) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
ac.register(AppConfig.class);
ac.refresh();
...
Then in chapter 11.4 there is another example but without the ac.refresh();
What benefit could refreshing the context immediately after its creation possibly have?

After calling refresh() it would be possible to get all configured contents from the ApplicationContext (beans, listeners, resources, etc.).
For instance, without refreshing the context any call to ac.getBean("myBean") would throw
java.lang.IllegalStateException:
BeanFactory not initialized or already closed - call 'refresh'
before accessing beans via the ApplicationContext
Usually in WebApplicationInitializer there is no need to get beans or other configured items, because its purpose is configuration of servlets and filters for the web application. That's why calling refresh is not necessary here.

Related

How to Inject a Agroal Datasource into servlet in Quarkus?

I have a Quarkus app which runs a servlet and I'm trying to inject an Agroal datasource as there is a Thread which runs within the servlet where I need to do some database transactions. However, I've tried the below implementation inside the Thread class as well and another static class which is utilized inside the thread, but in both classes the datasource returns null.
I've added the datasource properties in the application.properties file as well. Also the servlet is set to load on startup, Hence as soon as the application is run, the thread starts as well. This thread starts after the servlet is initialized.
class LoopThread extends Thread {
#Inject
#Named("db")
AgroalDataSource datasource;
public LoopThread() {
super();
    }
#Override
public void run() {
try {
DbUtil.userErrorLogged = false;
DbUtil.initDataSource(datasource);
LogUtil.debug("Thread started.");  
catch (Exception ex) {
LogUtil.error(ex);
}
}
}
I have tried to inject the datasource in the Thread class and also in the static Util class but both did not return the datasource. I'm thinking whether it is due to the thread which is started as the servlet is initialized. Any help on this would be great

Run a code when the war is deployed [duplicate]

I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.
I can see two ways to setup my application:
Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.
Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?
None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).
CDI/EJB unavailable? Use ServletContextListener
#WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
If you're not on Servlet 3.0 yet and can't upgrade (it would be about time because Servlet 3.0 was introduced more than a decade ago), and thus can't use #WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().
Here's an example which lets the listener store itself in the application scope:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
and then obtain it in a servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
It's also available in JSP EL by ${config}. So you could make it a simple bean as well.
CDI available? Use #Observes on ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped
#ApplicationScoped
public class Config {
public void init(#Observes #Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(#Observes #Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #Inject. Make it if necessary also #Named so it's available via #{config} in EL as well.
Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.
In case you're curious how to install CDI on a non-JEE server such as Tomcat, head to: How to install and use CDI on Tomcat?
EJB available? Consider #Startup#Singleton
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #EJB. The difference with other approaches is that it's by default transactional and in case of #Singleton also read/write locked. So if you would ever need to inject a random EJB (e.g. #Stateless) into a #WebListener or an #ApplicationScoped then you could basically as good merge both into a single #Startup #Singleton.
See also:
How to run a background task in a servlet based web application?
ServletContainerInitializer vs ServletContextListener
How do I force an application-scoped bean to instantiate at application startup?

Which method is called just before the session gets invalidated in spring-mvc life cycle?

I'm trying to timeout an HttpSession in Spring-mvc.
When the session gets timed out I have to release the resources that were used.
For that I need to call some other methods in the application.
myService.releaseResources(id,name);
myService is an autowired object for the service class.
When the session gets timed out the sessionDestroyed method is called.
But in this method myService method value is null.
I want to know where should I call the above code.
Thanks in advance.
You need to implement HttpSessionListener.
public class SessionListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent sessionEvent) {
// TODO Auto-generated method stub
}
#Override
public void sessionDestroyed(HttpSessionEvent sessionEvent) {
// TODO Auto-generated method stub
}
}
Add its entry to web.xml
<listener>
<listener-class>
yourpacakage.SessionListener
</listener-class>
</listener>
Then call your desired code inside sessionDestroyed method.And as far as service is concerned you can get the service object by accessing current applicationContext.
ServletContext ctx = event.getSession().getServletContext();
WebApplicationContext springContext=WebApplicationContextUtils.getWebApplicationContext(ctx);
springContext.getBean("yourService");
If you want to handle things local to a particular session bean, you can use #Predestroy to annotate your releaseResources method. That will inform Spring that you want that method to be invoked when the session ends.
Note that your MyService bean will have to be annotated to be session scoped.

Testing with autowired dependency like session in Validator

I have few custom annotations defined on fields of an object like:
public class Person{
#Accountname
String email;
}
Implementation class of #Accountname:
#Autowired ValidationService service;
#Autowired ClientSession clientSession;
#Override
public boolean isValid(final String email, final ConstraintValidatorContext ctx) {
if(!service.isAccountValid(email, clientSession)){
return false;
}
}
I am trying to write junits for these annotations.
#Test
public void validEmailTest()
{
person.setEmail("abc#xyz.com");
Set<ConstraintViolation<Person>> violations = validatorInstance.getValidator().validateProperty(person, "email");
Assert.assertEquals(1, violations.size());
}
But its throwing this error when I execute the test:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.clientSession': Scope 'session' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:343)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:34)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.getTarget(CglibAopProxy.java:663)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:614)
at org.hibernate.validator.internal.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:308)
... 45 more
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.request.SessionScope.get(SessionScope.java:90)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:329)
... 54 more
Any idea on how to write junits if a validator class has a dependency on services like session etc.?
This should be tested separately (units).
The real logic that validates is in your ValidationService, so test it there, in AccountnameValidator test only the logic that is in there, injecting your dependencies:
#Mock ValidationService service;
#Mock ClientSession clientSession;
#InjectMocks AccountnameValidator av = new AccountnameValidator()
//initialize mocks
//example test
when(service.isAccountValid(email, clientSession)).thenReturn(true);
boolean result = av.isValid(email, ctx);
assertTrue(result);
And finally if you want you can validate presence of the annotation in Person class on email field using reflection.

Using special auto start servlet to initialize on startup and share application data

I need to get some configuration and connect to external resources/objects/systems somewhere and store it in application scope.
I can see two ways to setup my application:
Overriding the init() in the existing servlets and required code there and keeping all constructed objects inside that same servlet.
Having some kind of an initialisation servlet and using its init() to do the work. Then storing created objects in ServletContext to share it with my other servlets.
Which out of above is better approach? Is there any better way to share objects between servlets? Calling them directly from one another or so...?
None of both is the better approach. Servlets are intended to listen on HTTP events (HTTP requests), not on deployment events (startup/shutdown).
CDI/EJB unavailable? Use ServletContextListener
#WebListener
public class Config implements ServletContextListener {
public void contextInitialized(ServletContextEvent event) {
// Do stuff during webapp's startup.
}
public void contextDestroyed(ServletContextEvent event) {
// Do stuff during webapp's shutdown.
}
}
If you're not on Servlet 3.0 yet and can't upgrade (it would be about time because Servlet 3.0 was introduced more than a decade ago), and thus can't use #WebListener annotation, then you need to manually register it in /WEB-INF/web.xml like below:
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
To store and obtain objects in the application scope (so that all servlets can access them), use ServletContext#setAttribute() and #getAttribute().
Here's an example which lets the listener store itself in the application scope:
public void contextInitialized(ServletContextEvent event) {
event.getServletContext().setAttribute("config", this);
// ...
}
and then obtain it in a servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
Config config = (Config) getServletContext().getAttribute("config");
// ...
}
It's also available in JSP EL by ${config}. So you could make it a simple bean as well.
CDI available? Use #Observes on ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.ApplicationScoped
#ApplicationScoped
public class Config {
public void init(#Observes #Initialized(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's startup.
}
public void destroy(#Observes #Destroyed(ApplicationScoped.class) ServletContext context) {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #Inject. Make it if necessary also #Named so it's available via #{config} in EL as well.
Noted should be that this is new since CDI 1.1. If you're still on CDI 1.0 and can't upgrade, then pick another approach.
In case you're curious how to install CDI on a non-JEE server such as Tomcat, head to: How to install and use CDI on Tomcat?
EJB available? Consider #Startup#Singleton
#Startup
#Singleton
public class Config {
#PostConstruct
public void init() {
// Do stuff during webapp's startup.
}
#PreDestroy
public void destroy() {
// Do stuff during webapp's shutdown.
}
}
This is available in a servlet via #EJB. The difference with other approaches is that it's by default transactional and in case of #Singleton also read/write locked. So if you would ever need to inject a random EJB (e.g. #Stateless) into a #WebListener or an #ApplicationScoped then you could basically as good merge both into a single #Startup #Singleton.
See also:
How to run a background task in a servlet based web application?
ServletContainerInitializer vs ServletContextListener
How do I force an application-scoped bean to instantiate at application startup?

Resources