Properties files vs. the JNDI
I don’t know if this is a debate at all, but it has been in my workplace.
When managing configuration for Java EE / Spring Framework applications in a Wildfly server environment, what is better: managing an application’s configurable values at the server and environment level through the JNDI, or managing them through the use of flat configuration files, also known as “properties files?”
For load-balanced spring-enabled web applications deployed and continuously delivered (using a CI tool like Jenkins) across multiple Wildfly server environments, put me hard on the side of properties files in this debate…
Pros and Cons of the JNDI
The JNDI (which stands for Java Naming and Directory Interface) came in to being, as far as I can tell, so that system administrators could custom configure the server environment in which their applications run. There is tremendous upside to this, not just freedom to choose how you want your server running is great, but also because it can promote web app security. Through the JNDI, you can put any static value into that environment, well out of reach of anyone who might get access to your code base. In other words, instead of seeing that the password to your client’s financial web service endpoint is
MiRanchito2015, a crook would see that you are referencing a variable pulled out of the web server environment itself. This means that any potential hacker, in order to get to your passwords, would have to get access to the web application server itself, which should be challenging (unless you’re Equifax).
This also has particular relevance for application databases. If you configure application
DataSource objects at the server level, you can not only save yourself a lot of code, but also reinforce the security of your database by, again, placing the connection string, the user credentials, and diagnostic procedures apart from your code. It also results in an highly atomic application architecture. The database is wholly separate from the application itself, and the application can only reference the database by depending on the server environment in which the application is deployed.
Combine that with the detachable nature of data sources in the Wildfly application server, and you’ve got something not only secure, but extraordinarily versatile. Putting a data source into the JNDI is as easy as writing a bit of XML and deploying it on the server the same as any other application. Wildfly, at least, makes it incredibly easy.
But there are drawbacks. For any non-data source JNDI value, placement and removal is painful. This is because simple, static simple JNDI values are stored in Wildfly’s central standalone or domain XML files, and these files cannot be modified without a server restart at minimum. This leaves you with two options: use the
jboss-cli.sh bash interface to change the configuration values with minimal server interruption (which can be tricky), or stop the server, alter the server configuration XML, and then restart the server. When you’re supposed to be running web applications 24/7, this constraint typically means you’re going to be doing a configuration update at 2 a.m. Well, either that, or your going to be upsetting your clients when their application goes down so that you can make a config change.
This is important because configuration updates occasionally need to happen without a complete re-deployment of the application. If your application depends on a web service, and if suddenly the endpoint or the user credentials to that service change, you need to change them immediately. Can’t do that if it’s all JNDI-based.
Pros and Cons of Properties files
By contrast, there is another way. Spring-enabled Java applications are able to derive static configuration values from flat files as well. Colloquially (well, at least to me), these are referred to as “properties” files, given that the file extension is usually
.properties and they are full of application configurable properties. This requires inclusion of several spring framework jars into the application in order to give the application visibility into the application context, but once it’s there, it’s pretty awesome. I’m going to have to leave the exact particulars of how to do this to another blog post. But, by going this route, a developer can place all the configuration he needs into key value pairs within this file and then use them to write up spring framework bean recipes. (I’m partial to Java-based spring definitions myself, but to each his own…)
Using these files basically eliminates the need to restart a server every time a configuration update is required because, in order to update a configuration, all one must do is update the flat file and refresh the java application. (In Wildfly server environments running in Linux, I use the
touch command to do this.) This has particular relevance, in my circumstance, to development environments where continuous delivery tools are used. If all that is needed to update an application’s configuration is to place a file, then placing that file and refreshing the application is a highly automatable process that one can build into CI tools, such as Jenkins, in a snap. No muss, no fuss. Just simple placement and refresh. Boom. You’re app’s up to date. Whereas, it’s virtually impossible to use such tools to painlessly update server-level configurations.
That said, properties files do not lend themselves well to configuration of data sources, which are best maintained in the JNDI. It is conceivable that one could use a CI tool like Jenkins to manage these data source connections, but they change so rarely that it’s hardly worth fretting about. Not to mention that setting up a database connection is slightly more complicated in my experience than pulling a couple properties out of a flat file. Here’s an old blog post that give a good illustration.
By using properties files, you also are able to keep configuration values out of your code, which keeps your code atomic. The drawback, however, is that if you’re using version control to keep track of these properties, all a hacker needs to do is gain access to your version control servers, and he has all your usernames and passwords. Therefore, make sure you have extra security in place guarding whatever properties files you use in production. Restrict access, require keys, apply extra passwords… whatever you’ve got to do, then do it.
When you’re trying to transition from manual to automated deployments, you need a way to manage configuration without the fuss of configuring each individual server many times over. The best, and really, the only way that I can think of to do this effectively is to use Spring Framework to manage configuration through flat files. Take the headache out of managing your server environment; get your data sources set up once at the server level, and then allow your applications to derive configurable values from a file that you can maintain in your scm solution and place using an automation tool.