Does CloudBees allow you to define custom error pages beyond what you can to with a traditional Java web app (via web.xml)?
For instance, if a CloudBees app-cell instance goes down due to infrastructure issues, is there a type of exception it will throw that can be caught and handled by the application backend? Or a special exception/error page that can be defined if the app runs out of memory/PermGen? Thanks in advance!
error page in web.xml are used to render application errors, and suppose the application server is up-and-running. Container errors / maintenance / shutdown can't benefit from application resources by nature.
If an app-cell instance goes down, your application has no chance to throw any exception as it will have been killed with the app-cell. An OOM error will automatically trigger an application restart. Generally speaking, the platform will ensure you always have one instance running.
Related
I was trying to understand how the Web Services work and I came across this tutorial.
Now, I've seen Spring being used in enterprise applications and always wondered where the main method was and how everything worked? And whenever I would go to a Spring tutorial they'll start with beanFactory and Contexts and what not, all in a main Java method and from there just keep getting beans as required. This is totally different from what I see in the applications.
How exactly does Spring work in this case? What is the sequence of calls? I guess there will be some hidden main method somewhere, but I am not sure of that.
Normally if I were to run a simple Java project from command line, I'd do java mainClass. Now how would it happen in this case?
There is still a main method. It's just not written by the developer of the application, but by the developer of the container.
You can still see the main method being called by using the debugger like this:
Put a breakpoint in some initialization method, such as the init method of some servlet Servlet.init()
When the breakpoint hits, scroll down the call trace and the main method should be at the bottom.
This is an example with Jetty:
To see this we need to put the breakpoint in an initialization method so that we get the main thread of the application.
Putting the breakpoint in the processing of a request instead of an initialization method would show Thread.run() at the bottom of the stack trace and not main().
Thread.run() is the equivalent of the main method for threads other than the main thread.
So the main method still exists. It's just being handled at the level of the container.
Web applications don't have a main; the 'program' that is running is actually the web container (Apache Tomcat, Glassfish, JBoss, Weblogic, whatever) and that program will service the web application(s) you deploy into it. You might want to read the JEE tutorial to learn and understand what a Java web environment is.
https://docs.oracle.com/javaee/7/tutorial/
You don't see any explicit main method just because it is a Web project. This project is built into a web application archive (WAR) file which is deployed into a web server / servlet container, e.g., Tomcat in this tutorial.
Web applications do not have to contain main methods. This is because you don't need to explicitly start any Java process from within your web application. Somewhere in its depths, Tomcat calls a main method of the code it has been built from. This happens at server startup time.
Then, it will bind your code to incoming HTTP calls, but it will not start new processes for that. It will rather start new threads.
Web applications are not stand-alone applications. They run on some applications what we call a servletContainer in a Java context so there aren't any "main method or Java process (OS)" for any web application. They are just deployed on those containers that have a main method and Java process in OS runtime.
If you've created a basic program in Java then you must know that every Java program has a main() method, which is the starting point of the program. So, how come servlets don't have a main()? That is because servlets are served using Web containers.
A Web container will perform all the underlying work on behalf of the servlet so the programmer can focus on the business logic. When a client requests a servlet, the server hands requests to a Web container where the servlet is deployed.
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'm trying to verify some conditions on application startup, such as the presence of critical files in the system.
To do this, I'm using a SerlvetContextListener, which tests for a bunch of conditions on startup.
How can I make so that the application rejects the deployment in Tomcat, if any of these conditions is not met? I could throw an exception, and catch that in the logs, but I'd like the application not to start at all.
Even failing Tomcat service startup would be a solution.
What's the simplest way? Should I try connecting to the Tomcat manager and undeploy the app?
Well...
According to your original question, you'd like the application to "not start at all" if certain files aren't there (or other conditions aren't met). Logically, it follows that the checking of the conditions can't possibly be a part of the application (if the checking is to be done as a part of the application - say, upon startup - then the application must be started for those checks to take place).
So:
If you don't want the application to start at all unless certain conditions are met, then your solution must be external to the application. For example, you could write your own Tomcat startup script that will check for your conditions first, and only then start Tomcat up.
If you don't mind the application starting and performing the checks, then the ServletContextListener is precisely what you should take advantage of. Throwing an exception from within contextInitialized() will result in the application being "unavailable" for serving requests. Alternatively, you could communicate with Tomcat's MBeans to stop the application if checks don't pass.
I have two web applications running in same Servlet container (Tomcat), A and B. These two connect to each other using Spring Remoting. On startup, B needs to call A to open a connection automatically, it's basically a really simple authentication call.
However since B is (in my case) loaded before A, B's application context blocks until the entire application is started up. What this means is that the B application will be stuck until timeouts etc. occur and only then A is allowed to start, however at this point B is now incapable of connecting to A and the required connection between two web applications won't be created.
So, how do I work around this? I'm currently hooking the connection command using InitializingBean and the application context is initialized using a listener.
Two options come to my mind:
Run two instances of Tomcat, on different ports.
perform the authentication in a new thread (preferably using an ExecutorService). Thus the "main" thread won't block and the deployment will continue.
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.