I have a web application which I'm trying to shut down by executing the close() method on the context:
((ConfigurableApplicationContext) appContext).close();
After executing this the application appears to be continuing running, health page produces the following exception:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
Is there a way to shudown the whole thing via Spring or should I resort to System.exit()?
Any help would be kindly appreciated!
PLease have a look at these questions. They are on the same line as yours:
How to manage Tomcat via Java,
Start / stop a web application from itself?
As #chrylis suggested, I think the easiest way of shutting down the server(if it's not running in embedded mode) is to use Runtime class.
Related
I have been working with Spring for 8 years now, and very often I run into this exception.
BeanCreationException: Error creating bean with name
For example, I am working on a service right now that fails to start because a Bean requires a connection to Azure (on AMQP port) to be successful. The stack trace says nothing about the cause of the error though. Enabling com.azure.core or org.apache.http logging DEBUG also not helping.
Is it possible to intercept the Bean instantiation to reveal more information about the cause of the error? Is there a Spring coding pattern for this kind of thing?
Would love to solve this once and for all so that users of services I create are never confused about a Bean loading exception.
This page elaborates on the issue: https://www.baeldung.com/spring-beancreationexception but never tells you what to do when dealing with Beans being loaded from a 3rd party lib rather than your own code.
I am studying for the Spring Core certification and I have some dount about on this question finded into the provided study material:
What is the preferred way to close an application context?
I know that if I have something like this:
ConfigurableApplicationContext context = …
// Destroy the application
context.close();
by the use of the close() method on the context objet the ApplicationContext is closed and the application is destroyed.
But I think that this is not the best way that I have to do it.
Reading the official documentation I find that I can also do something like this:
context.registerShutdownHook();
that register a Shutdown Hook with the JVM so it is the JVM that will trigger Spring's close phase before JVM exits. So on JVM exit, Spring's close phase will execute.
On the documentation I can read that: usually not possible to call context.close() because many applications (web applications) run indefinitely But what exactly means this last assertion? why web application run indefinitely?
So my questions are:
Can I use this second way to close an application context also with not web application?
Is it prefered respect the context.close()?
Tnx
As you are aware that ContextLoaderListener is the one that takes care of initializing and destroying your ApplicationContext, when you shutdown your server, that ContextLoaderListener's contextDestroyed method is invoked.
public void contextDestroyed(ServletContextEvent event){
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
In that closeWebApplicationContext, they actually call the close method on ApplicationContext like this
if ((this.context instanceof ConfigurableWebApplicationContext)) {
((ConfigurableWebApplicationContext)this.context).close();
}
This is straight from spring-web-4.1.5.jar. As it is evident from here, they use close to destroy ApplicationContext in web applications.
But registerShutdownHook is used to explicitly shut down IoC container in non-web applications something like a standalone desktop application, specially when you're creating the ApplicationContext manually from ClassPathXmlApplicationContext (or) FileSystemXmlApplicationContext (or) some other types.
This is done to release all resources used by your spring application and to call destroy method on your spring beans if any.
On the documentation I can read that: usually not possible to call context.close() because many applications (web applications) run indefinitely But what exactly means this last assertion? why web application run indefinitely?
A web application will run as long as the application server that deploys it runs. It is up to the application server (and not to you) to correctly start and stop your application. This means that when the application server is stopped, the servlet context is destroyed. In a Spring application, the ContextLoaderListener class registered in web.xml listens to this event (context destroyed) to properly close the Spring context.
When using Spring outside of an application server (like a standalone application), it is up to you to correctly stop the Spring context. As you said, this can be done by explicitly calling context.close() or registering a shutdown hook (context.registerShutdownHook()) that makes this call for you.
From https://stackoverflow.com/a/42018369:
The ApplicationContext class doesn't define either of these methods as a part of its interface, but the ConfigurableApplicationContext does define both of these.
From the JavaDoc:
close() -- Close this application context, destroying all beans in its bean factory.
registerShutdownHook() -- Register a shutdown hook with the JVM runtime, closing this context on JVM shutdown unless it has already been closed at that time.
Basically, AbstractApplicationContext#close() will close, or shutdown, the ApplicationContext at the time it is invoked, while AbstractApplicationContext#registerShutdownHook() will close, or shutdown, the ApplicationContext at a later time when the JVM is shutting down for whatever reason. This will be achieved by utilizing the JVM shutdown hook functionality.
In either case, the actual closing is done by the doClose() method.
If you are curious about why your outputs look so similar, it is because they are effectively doing the same thing, whether you call close() or registerShutdownHook() at line 3 of you example. close() will shutdown right away, and registerShutdownHook() will shutdown just before the JVM will exit, which is pretty much as soon as the method is done being invoked, because it is the last line of code!
Several people seem to have the same problem(see this and this):
If you startup a glassfish(v 4) server with an MDB(Message Driven Bean) and there are messages to be consumed, the MDB will start consuming the messages while the container is still initializing. If the message processing requires any other service from the container it will throw an exception:
Caused by: javax.ejb.EJBException: Attempt to invoke when container is in Initializing
Has anyone managed to solve this problem?
Ideally the MDB should only start consuming messages after the container is fully initialized.
Is there a way to let the MDB check for container initialization and only start accepting messages when the container is up and running?
Edit:
Maybe the following annotation helps: #DependsOn("Dependency")
You may configure the application loading sequence (startup order), put a greater value for your application, and may be put a delaying application ahead of it.
I asked this question earlier:
Jersey app-run initialization code on startup to initialize application
Is there any way to run this initialization code after the server has initialized the web app fully ? I am running into a catch-22 problem in that I need the web app fully started by Tomcat before I can run my login call once ?
There are a few considerations. First, Jersey is implemented as a servlet, and that's how it gets loaded. The simplest way to decouple servlet startup from servlet context startup is to not load it on startup. Accomplish this by omitting the load-on-startup element from the servlet descriptor in the web.xml. Setting it to a non-positive should also work.
If you must load the servlet on startup but still want to decouple it, which was my case, you'll probably have to write some custom code, which I did. I couldn't think of any other way. Use a listener of some type--a ServletContextListener or Spring ApplicationListener, depending on exactly how your app is set up--to kick off a new thread that will initialize your Jersey servlet by making an HTTP request to it. It feels a little dirty, but like I said, it's the only thing I and my team could come up with.
I want to initialize a global instance of a class before my Tomcat server completes startup and begins to offer my servlets. If this service somehow fails initialization, I'd like the entire startup sequence to fail as well (or as close to this as possible; it would be pointless for the server to be running otherwise). What's the best way I can accomplish this?
Each web application has a ServletContext associated with it. The ServletContext object is created when the application is started and is destroyed when the application is shut down. A ServletContext has a global scope and is similar to a global variable in an application.
http://www.javabeat.net/tips/178-servletcontextlistener-example.html
complete explanation here
http://onjava.com/pub/a/onjava/2001/04/12/listeners.html
One thing you can do portably is to implement a servlet that initializes everything you need in its init() method (and maybe call System.exit() if it fails, i do not know if you have permission to do this in Tomcat). Then you would load it using <load-on-startup> in your web.xml to specify initialization order.