I would like that my Spring-based web application were able to validate its configuration during startup.
This means for example:
check if the required folders exist and are readable/writable
check if the required configuration keys are set and consistent
...
check any other constraint that is required for the correct functioning
How can you perform these checks and notify the system administrator if something is wrong?
The goal is to reduce the risk that some critical error arises when the application is actually going to need those resources that are bound to the wrong configuration.
NOTE: my approach is to use a special EnvironmentValidation bean that checks if the configuration/folder structure is ok and if not it throws an exception
If you want notifications you could set up an email notifier for example using log4j that would send any exceptions on startup to the system administrator.
if a configuration key is not present spring will not start up anyway.
check the keys are consistent with what?
checking folders exist and are readable/writable isn't something I'd really do in my webapp - this belongs in your deployment infrastructure. Saying that you could write your own custom checks as spring beans, load these first and throw an exception if some of your configuration fails validation.
During startup all errors will be logged in to server logs. Logs can be checked and system administrator can be notified.
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 am facing the problem of finding the best place to put some handling where I can check some of the properties in application.yml and fail app startup of Spring Boot app if they are invalid.
The main point is to find the first place where I can check these properties without running the entire app and fail in the end.
I tried:
#EventListener, but here I was able only to trigger events when the app was started.
Throwing an exception in #PostConstruct in one of my classes with #Configuration. I like this one, but it looks like a messy one.
Maybe there are better ways?
#EventListener, but here I was able only to trigger events when the
app was started
There are many different type of events and where you hook in to the startup process depends on the type of event that you listen for. In your case, consider listening for an ApplicationEnvironmentPreparedEvent if you want to check properties as soon as they are available.
I have an OpenLDAP deployment with uniqueness constraints on certain attributes (created with the "unique" overlay), which I have tested using ldapadd and confirmed to be working properly. But when I add a conflicting entry using the "bind" method of org.springframework.ldap.core.LdapTemplate, the entry is saved without being validated.
Is this supposed to happen, or is there something buggy about one of my environments? And if it is supposed to happen, how do I get spring-ldap to stop sneaking past the uniqueness constraint?
This could possibly be due to a known issue with OpenLDAP, if spring isn't explicitly adding the RDN attribute when it adds the entry:
http://www.openldap.org/lists/openldap-bugs/201210/msg00065.html
Spring LDAP uses JNDI for communication with the LDAP Server. By default JNDI sends ManageDsaIT control. If set the OpenLDAP Server ignores the unique overlay.
You can disable this behaviour by setting the following environment variable:
java.naming.referral=throw
When using a spring boot service you can set:
spring.ldap.base-environment:
java.naming.referral: "throw"
According to Spring documentation, it's possible to configure an embedded ApacheDS server, which makes testing easy.
Any reason why not use ApacheDS embedded with spring in deployment? is there some kind of limitation for that?
Also I noticed it's writing to temp directory /tmp/apacheds-spring-security. Is there a way to configure it?
I already participated in a project where embedded ApacheDS server was used in development and deployment (for test server). There was two minor problems:
If you stop your app incorrectly (for example via Terminate in debug mode or via kill -9) then you need to clean up /tmp/apacheds-spring-security directory manually. If you leave temporary files then an runtime exception will be thrown during next loading of your app.
We did not find how to change the default temporary directory (/tmp/apacheds-spring-security).
Hope this helps.
EDIT.
For the first problem I ended up with a servlet-api listener. It was declared before Spring context listener (to ensure execution before Spring and ApacheDS). This listener was responsible for checking and cleaning up /tmp/apacheds-spring-security. Maybe it is not the most elegant solution but it works. It will be better to have a param for this case in ApacheDS, something like -DapacheDSCleanUpWorkDirAtStutup=true.
In our tomcat application, we catch a CommunicationsException. There are various config parameters which can lead to this, including the database config being set wrong, but also the tomcat config have TOMCAT5_SECURITY=yes
When we catch the exception we want to give a helpful error message to the user. So we want to ask tomcat whether TOMCAT5_SECURITY is set, but we can't work out where in the API this is available.
So what tomcat API call will tell us whether TOMCAT5_SECURITY is enabled?
(The full exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure).
The only TOMCAT5_SECURITY flag I know of is the one supplied in the Ubuntu package file /etc/default/tomcat5(.5). This is Ubuntu-specific, so I wouldn't expect it to be part of the Tomcat API. Note that the flag sets whether a security manager is used or not, so maybe you should be looking at that.
How about calling some method that must throw a SecurityException when security is enabled? You could cache the result, assuming the setting doesn't change at runtime.