title: LDAP connection leak in this code
body: <p>Could someone explain me why this piece of code randomly "leaks" LDAP connections? I can see the amount of established TCP/IP connections rising by time and at some stage this starts causing problems. I tried fiddling with the com.sun.jndi.ldap.connect environment properties (enabling pooling, disabling it and such) but it did not seem to help. </p>
  
  <p>That means my lame piece of code has got bug(s). How should this done generally better and make sure I never "leak" LDAP connections?</p>
  
  <pre><code>import java.util.ArrayList;
  import java.util.List;
  import java.util.Properties;
  import javax.naming.Context;
  import javax.naming.InitialContext;
  import javax.naming.NamingEnumeration;
  import javax.naming.NamingException;
  import javax.naming.directory.Attributes;
  import javax.naming.directory.InitialDirContext;
  import javax.naming.directory.SearchControls;
  import javax.naming.directory.SearchResult;
  
  public class LdapUtil {
      private String ldap_context = "ou=myunit,dc=com";
      protected static String ldap_server = "ldap://ldapserver:389/";
      private String ldap_prefix = "(&amp;(uid=";
      private String ldap_postfix = ")(objectclass=inetOrgPerson))";
      private String[] ldap_attributes = {"uid","departmentNumber","cn","postOfficeBox","mail"};
      private Properties ldap_properties;
      private SearchControls ldap_searchcontrols;
          private static String ldap_principal = "uid=bind_account,cn=users,ou=myunit,dc=com";
          private static String ldap_credentials = "qwerty";
  
      private List&lt;String&gt; getUserAttributes(final String userId) {
          List&lt;String&gt; UserAttributes = new ArrayList&lt;String&gt;();
          InitialDirContext ctx = null;
          NamingEnumeration&lt;SearchResult&gt; resultsEnum = null;
          NamingEnumeration&lt;String&gt; atrEnum = null;
  
          // Connect the LDAP
          try {
          ctx = new InitialDirContext(this.ldap_properties);
          // Prepare the query string
          String query = this.ldap_prefix+ userId+ this.ldap_postfix;
          // Query!
          resultsEnum = ctx.search(this.ldap_context, query, this.ldap_searchcontrols);
  
          // Enumerate the results
          while (resultsEnum.hasMore()) {
              SearchResult sr = (SearchResult) resultsEnum.nextElement();
  
              // Get all the attributes for a hit
              Attributes atr = sr.getAttributes();
              // Enumerate the attributes
              atrEnum = atr.getIDs();
  
              while (atrEnum.hasMore()) {
                      String nextid = atrEnum.nextElement();
                      String nextattribute = atr.get(nextid).toString();
                      UserAttributes.add(nextattribute);
              }
  
          }
          } catch ( Exception eom ) {
              System.out.println("LDAP exception");
          } finally {
              try {
                  if (atrEnum!=null)
                  atrEnum.close();
                  if (resultsEnum!=null)
                  resultsEnum.close();
                  if (ctx!=null)
                  ctx.close();
              } catch (NamingException eo) {
                  // nothing
              } catch (NullPointerException eo) {
                  // Nothing
              }
          } 
          return UserAttributes;
      }
  
  
      /*
       * Parses the LDAP search results and searches for selected attribute.
       */
      private String getAttribute (final List&lt;String&gt; attributes,final String attribuutti) {
          String result = null;
          // Let's go through all attributes
          for (int i = 0; i &lt; attributes.size(); i++) {
              String attribute = attributes.get(i).toString();
              // Look for match
              if (attribute.startsWith(attribuutti)) {
                  // Return the value after the space
                  int k = attribute.indexOf(" ");
                  result = attribute.substring(k+1,attribute.length());
              }
          }
          return result;
      }
  
  
      public LdapUtil(String remoteuser) {
  
          // Pre-initialize LDAP connection related properties
          this.ldap_properties = new Properties();
          this.ldap_properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
          this.ldap_properties.put(Context.PROVIDER_URL, ldap_server) ;
          this.ldap_properties.put(Context.REFERRAL, "follow" );
          this.ldap_properties.put(Context.SECURITY_AUTHENTICATION, "simple");
          this.ldap_properties.put(Context.SECURITY_PRINCIPAL,ldap_principal);
          this.ldap_properties.put(Context.SECURITY_CREDENTIALS,ldap_credentials);
          this.ldap_properties.put("com.sun.jndi.ldap.read.timeout", "10000");
          this.ldap_properties.put("com.sun.jndi.ldap.connect.timeout", "10000");
          // Tried with both pooling and without - doesn't solve problems
          this.ldap_properties.put("com.sun.jndi.ldap.connect.pool", "false");
  
          // Pre-initialize LDAP search controls
          this.ldap_searchcontrols = new SearchControls();
          this.ldap_searchcontrols.setSearchScope(SearchControls.SUBTREE_SCOPE);
          this.ldap_searchcontrols.setReturningAttributes(this.ldap_attributes);
  
              // The List for attributes
          List&lt;String&gt; attributes = null;
  
          attributes = getUserAttributes(remoteuser);
      }
  
  }
  </code></pre>