title: How to get all LDAP users with LdapTemplate
body: <p>I'm using spring-security and wish to retrieve all users and all groups to be stored in a reference table so I can quickly look up users without having to consult the LDAP directory. I have created a <code>LdapAuthoritiesPopulator</code> implementation mirroring <code>DefaultLdapAuthoritiesPopulator</code> with the following additional method:</p>
  
  
  
  <pre class="lang-java prettyprint-override"><code>public final Collection&lt;GrantedAuthority&gt; getAllAuthorities() {
      if (groupSearchBase == null) {
          return new HashSet&lt;&gt;();
      }
      Set&lt;GrantedAuthority&gt; authorities = new HashSet&lt;&gt;();
      Set&lt;String&gt; roles = ldapTemplate.searchForSingleAttributeValues(
              groupSearchBase,
              allAuthorityFilter,
              new String[0],
              groupRoleAttribute);
      for (String role : roles) {
          if (convertToUpperCase) {
              role = role.toUpperCase();
          }
          authorities.add(new SimpleGrantedAuthority(rolePrefix + role));
      }
      return authorities;
  }
  </code></pre>
  
  <p>This now allows me to retrieve all groups, <code>allAuthorityFilter</code> is a property defaulting to <code>(&amp;(objectClass=group)(objectCategory=group))</code>.</p>
  
  <p>I am now trying to achieve the same thing with the users by creating a custom <code>LdapUserSearch</code> based of of <code>FilterBasedLdapUserSearch</code> with the following additional method:</p>
  
  <pre class="lang-java prettyprint-override"><code>public List&lt;String&gt; findAllUsers() {
      SpringSecurityLdapTemplate template
              = new SpringSecurityLdapTemplate(contextSource);
      template.setSearchControls(searchControls);
      List&lt;String&gt; r = template.search(searchBase,
                                       allUsersFilter,
                                       new AttributesMapper() {
          @Override
          public Object mapFromAttributes(Attributes atrbts)
                  throws NamingException {
              return (String) atrbts.get(userNameAttribute).get();
          }
      });
      return r;
  }
  </code></pre>
  
  <p>There are two problems I have with this:</p>
  
  <ol>
  <li>If the user-list is large I get <code>javax.naming.SizeLimitExceededException</code> which I do not know how to resolve.</li>
  <li>I want this method to return something like <code>DirContextOperations</code> similar to how <code>searchForUser(String)</code> works so that my <code>LdapUserDetailsMapper</code> implementation can be reused to return all user properties.</li>
  </ol>
  
  <p>I'm finding the documentation for <code>LdapTemplate</code> a little hairy and having trouble finding the answers I'm after, any assistance would be greatly appreciated.</p>
  
  <p><strong>UPDATE</strong>: I have solved point (2) above by </p>
  
  <pre class="lang-java prettyprint-override"><code>public List&lt;UserDetails&gt; getAllUserDetails(boolean includeAuthorities) {
      List&lt;UserDetails&gt; r = new ArrayList&lt;&gt;();
      for (DirContextOperations ctx : userSearch.findAllUserOperations()) {
          try {
              Attribute att = ctx.getAttributes().get(usernameAttribute);
              String username = (String) att.get();
              r.add(userMapper.mapUserFromContext(
                      ctx,
                      username,
                      includeAuthorities
                          ? authPop.getGrantedAuthorities(ctx, username)
                          : Collections.&lt;GrantedAuthority&gt;emptySet()));
          } catch (NamingException ex) {
              LOG.warn("Username attribute " + usernameAttribute + " not found!");
          }
      }
      return r;
  }
  </code></pre>
  
  <p>In my <code>UserSearch</code> implementation I have:</p>
  
  <pre class="lang-java prettyprint-override"><code>public List&lt;DirContextOperations&gt; findAllUserOperations() {
      SpringSecurityLdapTemplate template = new SpringSecurityLdapTemplate(contextSource);
      template.setSearchControls(searchControls);
      return template.search(searchBase,
                             allUsersFilter, new ContextMapper() {
          @Override
          public Object mapFromContext(Object o) {
              return (DirContextOperations) o;
          }
      });
  }
  </code></pre>
  
  <p>However I have not solved point #1. If I need to batch this somehow then that is fine as long as there is a way to tell <code>LdapTemplate</code> where to resume on subsequent calls.</p>