9

I have a situation where through a Java program, I create a javax.naming.ldap.LdapContext and do a search() operation on it - which makes an underlying connection. Then I put the Java app thread to sleep, during which I restart the LDAP server (OpenLDAP, just to note). When the App thread wakes up and tries to do any operation on the LdapContext created earlier, it throws "CommunicationException: Connection is closed".

What I want is to be able to re-establish the connection.

I see that LdapContext has a reconnect() method - where I pass controls as null. However, this does not have any effect. What I saw in the Sun LDAP implementation that during the time when the LDAP server was restarted, the ConnectionPool maintained by the Sun implementation marked the underlying com.sun.jndi.ldap.LdapClient instance with a "usable=false". Upon reconnect() call - it simply calls ensureOpen(), which again checks if the usable flag is false or not - if it's false; then it throws CommunicationException - so back to square one.

My question is: how does a Java app survive an external LDAP server restart? Is creation of new LdapContext again is the only way out? Appreciate any insights.

Here is the stacktrace of the exception:

javax.naming.CommunicationException: connection closed [Root exception is java.io.IOException: connection closed]; remaining name 'uid=foo,ou=People,dc=example,dc=com'
at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1979)
at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1824)
at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1749)
at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:368)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:338)
at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java:321)
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:248)
Caused by: java.io.IOException: connection closed
at com.sun.jndi.ldap.LdapClient.ensureOpen(LdapClient.java:1558)
at com.sun.jndi.ldap.LdapClient.search(LdapClient.java:504)
at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1962)
... 26 more
skaffman
  • 398,947
  • 96
  • 818
  • 769
Anand
  • 409
  • 3
  • 7
  • 15
  • I don't think problem should come after restarting server if you did not change any Bind user. – Muhammad Imran Tariq Jan 09 '12 at 13:05
  • 1
    Hi Imran, unfortunately - all operations on the LdapContext fail with the CommunicationException, after the LDAP server has been restarted. – Anand Jan 09 '12 at 16:21
  • Can you please share some code, how you are creating connection and using it to search? – Muhammad Imran Tariq Jan 10 '12 at 05:20
  • I am using Active Directory. I restarted server and search. It did not give me any exception and search completes. – Muhammad Imran Tariq Jan 10 '12 at 07:45
  • The code is something like: SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); String searchName = "test"; String baseDN = "dc=foo,dc=com"; NamingEnumeration namingEnum = ldapContext.search(baseDN, searchName, constraints); --- say I put this in a loop with some delay.. and then restart the LDAP server when the loop is sleeping. On the next wakeup; the search() operation fails throwing CommunicationException – Anand Jan 11 '12 at 10:24
  • This exception might come when ldap server is being restarted. Can you confirm that, when loop continue, ldap server was up again after restart. – Muhammad Imran Tariq Jan 12 '12 at 05:19
  • Yes, as I said, when the loop is sleeping - I restart the server. So when the loop wakes up - the server is back again - however, LdapContext.search() fails. – Anand Jan 13 '12 at 04:55
  • 1
    @Anand: I'm having same problem as yours. Since there is no activity **Jan 13**, it seems that you have already found a solution. I'll be grateful if you shared it with us. Thanks – Oueslati Bechir Dec 13 '12 at 16:50
  • @LBechir : Nope, no solution with Sun/Oracle LDAP Impl :-/. Still have to keep this as "known issue". – Anand Dec 15 '12 at 15:30

4 Answers4

2

Just enable JNDI connection pooling and it will all be taken care of for you behind the scenes. See the JNDI Guide to Features and the LDAP Provider documentation. It's controlled by just a couple of properties.

user207421
  • 305,947
  • 44
  • 307
  • 483
0

We had this problem at work. The solution we came up with (may not be the best answer). Was to create a watchdog thread that would check the connection at some fixed rate. If the connection did not work, it would re-initialize the connection with LDAP.

lordoku
  • 908
  • 8
  • 22
0

The UnboundID LDAP SDK provides a means to auto-connect wherein that auto-reconnect operation is invisible to the client.

Terry Gardner
  • 10,957
  • 2
  • 28
  • 38
-1

You should note that this is related essentially to LDAP connection pooling. As defined here:

A connection is retrieved from the pool, used, returned to the pool, and then, retrieved again from the pool for another Context instance.

Thus, the reuse of a previous connection may cause such problem:

You may test the behavior without using LDAP connection pooling by setting

com.sun.jndi.ldap.connect.pool=false

Also, another possible cause may be the timeout of reading the LDAP operations. In fact, the reading operation is not notified about the closure of the LDAP server after a specific timeout. For more information, you may take a look at this link

user207421
  • 305,947
  • 44
  • 307
  • 483
Oueslati Bechir
  • 962
  • 2
  • 10
  • 15
  • Connection pooling is off by default. I can't make much sense out of your last paragraph. If the server goes down during a read you will certainly be notified. – user207421 Aug 25 '16 at 21:24