title: LDAP Query Java Exception in thread "main" java.lang.NullPointerException
body: <p>i have a problem with the code:</p>
  
  <pre><code>import java.util.Hashtable;
  import javax.naming.Context;
  import javax.naming.NamingEnumeration;
  import javax.naming.NamingException;
  import javax.naming.directory.DirContext;
  import javax.naming.directory.SearchControls;
  import javax.naming.directory.SearchResult;
  import javax.naming.ldap.InitialLdapContext;
  import javax.naming.ldap.LdapContext;
  
  /**
   * Example code for retrieving a Users Primary Group
   * from Microsoft Active Directory via. its LDAP API
   * 
  
  public class LDAPTest {
  
      /**
       * @param args the command line arguments
       */
      public static void main(String[] args) throws NamingException {
  
          final String ldapAdServer = "/*Server*/";
          final String ldapSearchBase = "ou=users,ou=,dc=,dc=";
  
          final String ldapUsername = "/*Username*/";
          final String ldapPassword = "/*Passwort*/";
  
          final String ldapAccountToLookup = "/*lookupaccount*/";
  
  
          Hashtable&lt;String, Object&gt; env = new Hashtable&lt;String, Object&gt;();
          env.put(Context.SECURITY_AUTHENTICATION, "simple");
          if(ldapUsername != null) {
              env.put(Context.SECURITY_PRINCIPAL, ldapUsername);
          }
          if(ldapPassword != null) {
              env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
          }
          env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
          env.put(Context.PROVIDER_URL, ldapAdServer);
  
          //ensures that objectSID attribute values
          //will be returned as a byte[] instead of a String
          env.put("java.naming.ldap.attributes.binary", "objectSID");
  
          //the following is helpful in debugging errors
          env.put("com.sun.jndi.ldap.trace.ber", System.err);
  
          LdapContext ctx = new InitialLdapContext(env,null);
  
          LDAPTest ldap = new LDAPTest();
  
  
          //1) lookup the ldap account
          SearchResult srLdapUser = ldap.findAccountByAccountName(ctx, ldapSearchBase, ldapAccountToLookup);
  
  
  
          //2) get the SID of the users primary group
          String primaryGroupSID = ldap.getPrimaryGroupSID(srLdapUser);
  
          //3) get the users Primary Group
          String primaryGroupName = ldap.findGroupBySID(ctx, ldapSearchBase,primaryGroupSID);
  
  
      }
  
  
  
      public SearchResult findAccountByAccountName(DirContext ctx, String ldapSearchBase, String accountName) throws NamingException {
  
          String searchFilter = "(&amp;(objectClass=user)(sAMAccountName=" + accountName + "))";
  
          SearchControls searchControls = new SearchControls();
          searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
  
          NamingEnumeration&lt;SearchResult&gt; results = ctx.search(ldapSearchBase, searchFilter, searchControls);
  
          SearchResult searchResult = null ;
          if(results.hasMoreElements()) {
               searchResult = (SearchResult) results.nextElement();
  
              //make sure there is not another item available, there should be only 1 match
              if(results.hasMoreElements()) {
                  System.err.println("Matched multiple users for the accountName: " + accountName);
                  return null;
              }
          }
  
          return searchResult;
      }
  
      public String findGroupBySID(DirContext ctx, String ldapSearchBase, String sid) throws NamingException {
  
          String searchFilter = "(&amp;(objectClass=group)(objectSid=" + sid + "))";
  
          SearchControls searchControls = new SearchControls();
          searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
  
          NamingEnumeration&lt;SearchResult&gt; results = ctx.search(ldapSearchBase, searchFilter, searchControls);
  
          if(results.hasMoreElements()) {
              SearchResult searchResult = (SearchResult) results.nextElement();
  
              //make sure there is not another item available, there should be only 1 match
              if(results.hasMoreElements()) {
                  System.err.println("Matched multiple groups for the group with SID: " + sid);
                  return null;
              } else {
                  return (String)searchResult.getAttributes().get("sAMAccountName").get();
              }
          }
          return null;
      }
  
      public String getPrimaryGroupSID(SearchResult srLdapUser) throws NamingException {
          byte[] objectSID = (byte[])srLdapUser.getAttributes().get("objectSid").get();
          String strPrimaryGroupID = (String)srLdapUser.getAttributes().get("primaryGroupID").get();
  
          String strObjectSid = decodeSID(objectSID);
  
          return strObjectSid.substring(0, strObjectSid.lastIndexOf('-') + 1) + strPrimaryGroupID;
      }
  
      /**
       * The binary data is in the form:
       * byte[0] - revision level
       * byte[1] - count of sub-authorities
       * byte[2-7] - 48 bit authority (big-endian)
       * and then count x 32 bit sub authorities (little-endian)
       * 
       * The String value is: S-Revision-Authority-SubAuthority[n]...
       * 
       * Based on code from here - http://forums.oracle.com/forums/thread.jspa?threadID=1155740&amp;tstart=0
       */
      public static String decodeSID(byte[] sid) {
  
          final StringBuilder strSid = new StringBuilder("S-");
  
          // get version
          final int revision = sid[0];
          strSid.append(Integer.toString(revision));
  
          //next byte is the count of sub-authorities
          final int countSubAuths = sid[1] &amp; 0xFF;
  
          //get the authority
          long authority = 0;
          //String rid = "";
          for(int i = 2; i &lt;= 7; i++) {
             authority |= ((long)sid[i]) &lt;&lt; (8 * (5 - (i - 2)));
          }
          strSid.append("-");
          strSid.append(Long.toHexString(authority));
  
          //iterate all the sub-auths
          int offset = 8;
          int size = 4; //4 bytes for each sub auth
          for(int j = 0; j &lt; countSubAuths; j++) {
              long subAuthority = 0;
              for(int k = 0; k &lt; size; k++) {
                  subAuthority |= (long)(sid[offset + k] &amp; 0xFF) &lt;&lt; (8 * k);
              }
  
              strSid.append("-");
              strSid.append(subAuthority);
  
              offset += size;
          }
  
          return strSid.toString();    
      }
  }
  </code></pre>
  
  <p>Firstly if i run this code i become the error message : </p>
  
  <pre><code>Exception in thread "main" javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
  at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
  at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
  at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)
  at javax.naming.directory.InitialDirContext.getURLOrDefaultInitDirCtx(Unknown Source)
  at javax.naming.directory.InitialDirContext.search(Unknown Source)
  at LDAPTest.findAccountByAccountName(LDAPTest.java:74)
  at LDAPTest.main(LDAPTest.java:58)
  </code></pre>
  
  <p>As a measure i put on LdapContext ctx = new InitialLdapContext(env,null);</p>
  
  <p>and now i have the error message </p>
  
  <pre><code>Exception in thread "main" java.lang.NullPointerException
  at LDAPTest.getPrimaryGroupSID(LDAPTest.java:114)
  at LDAPTest.main(LDAPTest.java:61)
  </code></pre>
  
  <p>I do not know how to continue. Can anybody help me? Is anyone familiar with it ? ----------------------------------------------------------------</p>