So I have a Spring app running on Tomcat. While deploying initialization I sometimes may run into some errors (i.e. that some JDNI value is not found or that the app is not able to connect to some service). So when this happen I throw and exception and catch it in the #Configuration file. In the catch block I try to close the app with a System.exit(-1). But it doesn't seem to be the right way to do it. Cause Intellij is no capable or turning off the server, I even have seen that resources are not released till server is OFF.
I have also tried:
#Autowired
public ApplicationContext application context
#Bean
public IServerDataCache serverDataCache() {
try {
return new ServerDataCache(args);
} catch(InitializationError initializationError) {
log.error("Unable to load configuration for Server Data Cache. Closing application.");
System.exit(1); OR SpringApplication.exit(applicationContext)
}
return null;
}
Both System.exit(1); OR SpringApplication.exit(applicationContext) seem to have the same effect. Any idea of a better way to enforce application finalization.
BTW it is a spring boot application.
Just let your #Bean method throw the exception. It will be caught by the container and it'll then take care of tidying things up.
Although Andy Wilkinson's answer is correct, I'd just like to add that, since you're running your application on Tomcat (and not an embedded Tomcat), the Tomcat server doesn't shutdown when the application fails to start.
This happens by design, since Tomcat is, like all JavaEE containers, meant to run several applications at once.
If you want the whole process to stop when the application fails, you need to switch to using an embedded container.
Related
In our project, we have several Spring-based modules which are deployed on WAS as web applications. We need to skip deployment, or stop a module if its Spring context initialization fails (i.e. ContextLoaderListener#contextInitialized or DispatcherServlet#init throws an exception). Now, if such happens, app is got deployed and starts, but returns HTTP 500 for any request.
Websphere 8.5.5
Related question: https://stackoverflow.com/a/272747/3459206
This APAR seems to be relevant:
https://www-01.ibm.com/support/docview.wss?uid=swg1PI58875
From the APAR text:
Listener exceptions typically should not stop the application
from starting up for service. However, some applications depend
on their listeners to do the necessary setup before the
application is started for service. Such applications prefer to
stop the application from starting up when there is any
exception in their listeners.
Problem conclusion
The WebContainer Container code was modified to provide an
option to stop the application when there is any listener
exception during the application starting up process.
A new WebContainer custom property needs to be set to enable the
behavior provided by this APAR:
For Full Profiles
com.ibm.ws.webcontainer.stopappstartuponlistenerexception = true
(default is false)
For Liberty Profile
stopappstartuponlistenerexception=true
The fix for this APAR is currently targeted for inclusion in
WebSphere Application Server fix packs 8.5.5.11 and 9.0.0.2,
and Liberty 16.0.0.3
See the APAR link for additional information.
You can use jenkins + maven.
Add the part you need to check under your test like junit.
Then if this module do not pass test, jenkins would not deploy it.
But I prefer fix bugs before deployment
Had a very similar issue.
The thing is - webfear - sorry could not resist ;-) does not initialize everything on startup.
To trigger a controlled request, I added a ScheduledEJB to the startup of the application. This bean itself triggered a http-request to a defined URL, which itself triggered:
any filters to get initialized in the chain
any contexts which are needed are initialized
And this itself ensured that my application (EAR or WAR) got very quickly tested after deployment. This works well with some small amout of requests per minute
If you work with high load, means tons of requests per second, you need to choose a different approach.
In this case I added a polling mechanism into the #Startup of the application, which polled every second or 250ms (depends on the load of the application).
This firing to the server ensured, that my #Startup bean was the very first which triggered the possible init issues in the application. If this happened I initialized a filter which always reported a 500 (or better fitting error) to the requestor.
Of course stop your firing bean, as soon as you get the 500, else your admins may like to kill you. (happend to me, since I produced tons or monitoring issues ;-) )
And of course on the regular operation, after your application started properly, you should also disable the polling
Look for a try-catch in the top level of your application code that is catching the Spring exception and allowing the application to continue running.
If the Spring exceptions being thrown are permitted to propagate to the top of the stack, the JVM will stop and there's no way it can keep running, far as I know.
I need to hot-deploy and -undeploy resources in a Jersey ServletContainer.
There seems to be no way to 'unregister' resources on a ResourceConfig, so the route I'm following is to replace all resources with a new set.
Although the documentation says registerResources on ResourceConfig replaces all resources, browsing through the source code seems to contradict this.
The solution I found was to reload the ServletContainer with an entirely new ResourceConfig.
Set<Class<?>> classes = ...
ResourceConfig config = new ResourceConfig(classes);
container.reload(config);
This works fine until I deploy a resource that results in a ModelValidationException. After that I cannot get the ServletContainer back in a proper state.
If I take a look at the source code:
public void reload(final ResourceConfig configuration) {
try {
containerListener.onShutdown(this);
webComponent = new WebComponent(webComponent.webConfig, configuration);
containerListener = webComponent.appHandler;
containerListener.onReload(this);
containerListener.onStartup(this);
} catch (final ServletException ex) {
LOGGER.log(Level.SEVERE, "Reload failed", ex);
}
}
The ModelValidationException is thrown from the WebComponent constructor.
After that any call to reload results in an exception from the onShutdown method, caused by checkState in the preDestroy method of the ServiceLocatorImpl.
I can avoid the exception by ignoring validation errors
ResourceConfig config = new ResourceConfig(classes);
config.property(ServerProperties.RESOURCE_VALIDATION_IGNORE_ERRORS,
Boolean.TRUE);
container.reload(config);
There is no way now however to find out if there were any errors but to explore the logging, which is just as bad, really.
Per heenenee's comment I tried subclassing ServletContainer, but something like this gives problems because the ResourceConfig cannot be put in two WebComponents.
I tried creating the WebComponent before shutting down, to get an early exit, but this fails the actual reload if there is no error in the resources (because the resourceconfig cannot be modified after the webcomponent has been created)
#Override
public void reload(ResourceConfig configuration) {
try {
new WebComponent(new WebServletConfig(this), configuration);
} catch (ServletException e) {
LOGGER.log(Level.SEVERE, "Reload failed", e);
List<ResourceModelIssue> resources = Collections.emptyList();
throw new ModelValidationException(e.getMessage(), resources);
}
super.reload(configuration);
}
Is there another way to hot-undeploy resources? Is there a way to reset the ServletContainer after a failed reload?
I don't think this can be achieved without the use of a servlet container that supports hot deployments. In my experience, a good way of doing this is using a container that supports OSGi. You can take a look at Eclipse Virgo or Apache Karaf.
For example, in an OSGi environment, you can create modules (called bundles) that can be dropped to a scanned folder to enable features at runtime, or removed from a folder, to disable some features. This is similar to how plugins work in Eclipse IDE, where a new plugin install/uninstall doesn't necessarily require a restart.
Jersey is not technically a servlet container, it is a REST/JaxB framework running on a servlet container.
Most embeddable servlet containers, Tomcat, Jetty, Grizzly allows you to redeploy application and servlets at runtime. But redeployment is typically not a feature you use when you embed the container in code.
Hot redeployment is most useful in production, allowing you to continuously deploy new versions.
On Tomcat you can have new and old version of an application deployed on the same server, and tomcat ensures that new sessions are started on the newest version on the application, but older versions will continue to use the application version they were started with. When an application is no loger used it is automatically undeployed.
Trying to read some values from my standalone.xml in Wildfly, I have got the following error message:
{
"outcome" => "failed",
"failure-description" => "WFLYCTL0379: System boot is in process; execution of remote management operations is not currently available"
}
In JBoss 7.1.1 it works fine, please see my java coding inside Ejb Singleton:
#Startup
#Singleton
#ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class TestBean {
#PostConstruct
private void init() throws Exception {
final ModelNode request = new ModelNode();
request.get(ClientConstants.OP).set("read-resource");
request.get("recursive").set(true);
request.get(ClientConstants.OP_ADDR).add("subsystem", "security");
final ModelControllerClient client = ModelControllerClient.Factory.create(InetAddress.getByName("127.0.0.1"),
9029);
final ModelNode response = client.execute(new OperationBuilder(request).build());
}
}
This error comes at the moment when the client.execute() tries to get ModelNode.
I'd appreciate any help!
Don't know what El Lord Code was trying to accomplish, but in my project, for example, we are using the pattern of Startup Singleton to initialize the application. Now, during that thing, we need to do some programatic login - logout to Wildfly and the logout does some credential cache flushing which depends on acccessing the security domain. The problem is that this whole remote management is not accessible during startup and shutdown (it starts after and ends before the application is started / stopped).
I have posted a similar question here: https://developer.jboss.org/message/944842#944842
The Error is stating that Wildfly is still deploying some WAR/application
In this period the management is still not accessible.
Try to start the Wildfly without any applications in deployment folder and then try to read the standalone config for what ever needs.
I am using Play framework 1.2.5 and Hibernate 3.25 for developing my web application. I am facing problems with the application startup, it is very slow :(
For any Java EE servlet-driven application, we use the ServletContextListener for initializing the session factories (which is really a time consuming job). Once the application is deployed, the session factories will be initialized and all this have to be completed before the application is ready to use for the end user. In this way, when the user triggers the first request, the response time for the first is faster.
But, for Play framework does not follow any servlet architecture. Hence not sure how to implement something similar to the ServletContextListener which will be create all the session factories before the application is ready to use to the end user.
Without this, for the first time the application is really very slow for the first request.
I am sure there might be something in Play Framework also which will do the same but I am not aware of it.
Please let me know about this.
You can use a Job to initialise you application.
For example you could have a bootstrap job annotated with #OnApplicationStart which would take care of loading your static data or initialising you cache or factories.
#OnApplicationStart
public class Bootstrap extends Job {
public void doJob() {
//Load static data
//Initialise cache
//Initialise factories
...
// ready to serve application
}
}
You're probably running the application in development mode, where everything is compiled and initialized lazily, on the first request. The production mode compiles everything before actually starting the server. See http://www.playframework.org/documentation/1.2.5/production
JB should be correct. In short you can start the server with --%prod option:
play run --%prod
or
play start --%prod
My webapp is part of a larger EAR that is deployed into a websphere server. The server hosts number of other apps on the same virtual server. My webapp has some initialisation/health checks in a servletContextListener->contextInitialized method. I want to make the webapp unavailable if initialisation/health checks fail. What is a realiable way of doing this? Will throwing a RuntimeException from within contextInitialized suffice? Is the rest of the EAR still expected to be available? Thank you.
I'd recommend throwing a RuntimeException from ServletContextListener.contextInitialized.
Servlet 2.3 wasn't very clear on this, but Servlet 2.4 added the following detail:
Some exceptions do not occur under the
call stack of another component in the
application. An example of this is a
… ServletContextListener that
throws an unhandled exception during a
notification of servlet context
initialization…. In this case,
the Developer has no opportunity to
handle the exception. The container
may respond to all subsequent requests
to the Web application with an HTTP
status code 500 to indicate an
application error.
Since it says that the servlet engine "may" disable access to application, you might find a server that does something else. However, Tomcat and WebLogic both disable the application, and the only other reasonable thing I can think of would be to ignore the exception. I can't see a container that did that being very popular—so you'd better test it in WebSphere yourself.
Throwing a RuntimeException will probably make only that servlet unavailable. A safer way might be to implement something like a Spring interceptor that will forward to an error page or something if the checks didn't pan out. That way, you don't need to prevent the app from loading, but can handle it more gracefully at run time.