47

Can anyone help explain why JNDI should be a preferred way to expose services such as a database / jms?

The posts I run into all talk about the advantage of not having to load a specific driver manager, benifiting from connection pooling etc. but thats easily achievable by specifying the driver manager in a properties file and using reflection.

Connection pooling can also be achieved by wiring in the right implementation into an application bean via spring or otherwise.

So why would using JNDI be any better?

Kailash
  • 785
  • 1
  • 8
  • 17

5 Answers5

48

JNDI really shines when you have to move an application between environments: development to integration to test to production. If you configure each app server to use the same JNDI name, you can have different databases in each environment and not have to change your code. You just pick up the WAR file and drop it in the new environment.

Here are some other assumptions that are crucial to know when judging this answer:

  • I don't have access to the servers on which the code is deployed at all, except for read-only access to logs.
  • The person who writes and packages the code is not the same person who configures and manages the server.
  • Once a WAR file starts on its journey to PROD it cannot be changed again without going back to the beginning. Any testing that's done by QA on the test server must be re-done if the WAR is altered.

Perhaps you don't see this benefit because you're a lone developer who writes code on a local desktop and deploys right to production.

duffymo
  • 305,152
  • 44
  • 369
  • 561
  • 5
    So how is that any different from having a properties file in each of those environments? After all, an administrator is managing the database connections on each server. – Kailash Oct 13 '11 at 21:45
  • 2
    Property files are usually packaged inside the WAR, so you don't get to change them. You'd have to distinguish between files by environment and pass a variable to identify where you are. If you're really sold on doing it your way, by all means do so. I'm not trying to sell anything; you don't sound like you really want to acknowledge any difference. Some people just like to have their ideas validated; perhaps you're one of those. – duffymo Oct 13 '11 at 21:47
  • 1
    I just want to really understand the difference, that's all :) If I understand you right, using JNDI you let the container manage those properties, so you don't have to manage them in your own file. I also see some posts that talk about setting the jndi configs via a properties file - http://activemq.apache.org/jndi-support.html - so is this defeating the purpose in a way? – Kailash Oct 13 '11 at 21:54
  • 2
    When I deploy in a WAR file, which I always do, my CLASSPATH consists of the JARs in the WEB-INF/lib and the packages under WEB-INF/classes - that's it. Unless I put a .properties file for every environment in the WAR, I don't get to change anything as I move towards PROD. I don't depend on CLASSPATH environment variables or script changes, because I don't have access to the server on which I deploy. – duffymo Oct 13 '11 at 22:16
  • 7
    You can easily accomplish most of what JNDI does by using Host name aliases. That is make an alias that points MYRESOURCE to 127.0.0.1 in your /etc/hosts (or wherever it is for your env). Then in your App config use MYRESOURCE (in a jdbc url for example). There you just made a way more portable smaller footprint naming directory that will work in other languages (ruby, python). – Adam Gent Aug 02 '12 at 15:29
  • @AdamGent: And how do you configure a database connection pool using host name aliases? Or store authentication keys for external services? – sleske Jan 21 '14 at 16:50
  • @sleske I use load balencers (ie pgbouncer or HAproxy), SSH/VPN tunnes and/or private network respectively. Using crypto like SSL in an internal private network is a complete waste. There is also DNS load balancing but thats for way more geographic disperse systems something which I don't think JNDI is capable of. – Adam Gent Jan 21 '14 at 19:09
  • 1
    @sleske You can also use DNS (not host files though) for config management (something JNDI does also but I use zookeeper and/or env variables) http://labs.spotify.com/2013/02/25/in-praise-of-boring-technology/ – Adam Gent Jan 21 '14 at 19:13
  • @AdamGent: Using DNS is an interesting solution. Of course, you could use the "DNS Service Provider" included in the JDK to perform the DNS queries via JNDI, thus closing the loop :-). – sleske Jan 22 '14 at 08:14
  • You can also use Puppet/Chef for configuration management and *.properties file outside of WAR for configuration of datasource. – rantoniuk Jul 14 '14 at 12:22
  • Couldn't the WAR application just reference an ENV variable and have each environment provide a JDBC connection string to the application? I don't see how JNDI is any better than that approach. – ivandov Jun 27 '18 at 14:16
  • Java EE chose to externalize with JNDI. The point was that JNDI was build into Java EE app servers. Spring Boot and .NET do not use Java EE, so JNDI matters less now. – duffymo Jun 27 '18 at 14:41
  • @duffymo: Well, you can use JNDI without the rest of JEE. As a matter of fact, Spring supports JNDI (``). – sleske Apr 17 '19 at 07:32
  • Only if you have to deploy your Spring Boot app to a Java EE server. No one has to anymore. When I deploy an executable Spring Boot JAR on cloud there's no JNDI in sight. – duffymo Apr 17 '19 at 09:34
15

I think the "preferred" mechanism is the one that's preferred by the person doing the admin and configuration. As duffymo pointed out, it's crucial that the configuration be external to your deployable artifact, but otherwise, I'd say anything goes. If your sysadmin prefers using a GUI to configure JDNI entries, cool. If he/she prefers editing properties files with cssh and vi, cool too. If you're responsible for both developing and configuring/deploying your app, then that's pretty much your call. Personally, I like to keep as much implementation as possible inside my artifact, meaning that my data source and drivers live there, too.

If you're asking about technical benefits of JNDI over the alternatives, I'm not sure there are any, but you might want to clarify your question.

Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
7

The real benefit of JNDI over property files comes when deploying to a clustered environment. Using property files leaves the possibility of some of the server instances having a different value. When using JNDI the same value is pushed out to all of the clustered servers by the domain controller, removing the need to copy the same property file to all of the servers (and probably restarting the server/app).

SensiJense
  • 71
  • 1
  • 1
6

As mentioned by others JNDI for the most part is used for service location lookup but mainly for DB like resources.

Whats most annoying is that Java's LDAP API is also the JNDI API. When working with LDAP the abstractions are very very confusing. JNDI also has the disadvantage of sometimes being a single point of failure.

You can easily accomplish most of what JNDI does by using Host name aliases. That is make an alias that points MYRESOURCE to 127.0.0.1 in your /etc/hosts (or wherever it is for your env). Then in your App config use MYRESOURCE as the host name (in a jdbc url for example).

Then when you move your app to production just change the production's /etc/hosts file to point MYRESOURCE to the production resource/service (like prod database server).

The above is a way more portable smaller footprint naming directory that will work in other languages (ruby, python). It will also work with things that are not normally done with JNDI like REST services. The only annoying thing is that you will have to update your servers hosts files but this can be automated through SSH scripts.

Adam Gent
  • 47,843
  • 23
  • 153
  • 203
6

Another area where JNDI helps:

It abstracts the lookup of resources. Normally the JNDI configuration is stored in an XML file on the application server, but it need not be. The configuration might for example be stored on an LDAP server, to make it easier to maintain centrally.

If the applications you run use JNDI to lookup what they need, you can switch from configuration files to using an LDAP server without modifying the applications. If each applications expects a properties file with a hardcoded name, you are out of luck. Imagine an enterprise with dozens of applications in production - changing them all would be a significant problem.

In other words, JNDI mainly shines for complex deployment scenarios, like:

  • many application servers (possibly clustered)
  • many different applications
  • centralized configuration
  • different server stages (test, production)

So it might seem overkill at first, but is very useful in theses scenarios. Of course, some benefits apply even for small deployments, such as the standardized configuration of DB connections.

sleske
  • 81,358
  • 34
  • 189
  • 227
  • 2
    "without modifying the applications" is a great mirage. Just like when connecting to resources (databases, etc.) one has to maintain the connection information, connecting to LDAP in it's own turn requires connection information. One only saves time if he/she connects to multiple resources and puts all of the resources configuration into the same LDAP store. It's a waste of time if LDAP is used to manage connection to a single resource - becomes just another layer of indirection. – Faustas Mar 18 '16 at 13:10
  • 3
    @Faustas: LDAP also makes sense if many different apps require the same information - central point to change everything. And yes, in that case the LDAP connection information must be managed instead. That's a tradeoff - no such thing as a free lunch :-). – sleske Apr 06 '16 at 11:26