Hello,
I am trying to create a <Resource ...> block inside my server.xml file
similar to a JDBC Resource, only this on is for Active Directory connections
(through LDAP port 389). I have written a simple class, created a .jar from
it and added it to $CATALINA_HOME/common/lib. I have configured
server.xmlwith a <Resource ...> container inside the <Context ...>
that I am using.
Everything is working ok except that I can only connect to the AD server 1
time after I restart Tomcat. I do not have connection pooling enabled and
do not want to enable it for AD connections if at all possible. I want to
create a new connection and disconnect each time I use this JNDI context.
<< server.xml >>
...
<Context path="/INV" docBase="INV"
debug="5" reloadable="true" crossContext="false">
<Resource name="jdbc/INV" auth="Container" type="javax.sql.DataSource"
maxActive="150" maxIdle="10" maxWait="10000"
username="XXX" password="XXX" driverClassName="
com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/Inventory?autoReconnect=true"/>
<Resource name="ldap/INV" auth="Container" type="
javax.naming.DirContext"
username="XXX" password="XXX" authMechanism="simple"
factory="resources.ldapAccess"
url="ldap://localhost:389" />
</Context>
...
<< end server.xml >>
<< ldapAccess.java >>
package com.affinity.resources;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
public class ldapAccess implements ObjectFactory {
public Object getObjectInstance(Object obj, Name nm, Context
nameCtx, Hashtable environment)
throws NamingException {
DirContext ctx = null;
Hashtable<String, String> env = new Hashtable<String,
String>(11);
Reference ref = (Reference) obj;
Enumeration addrs = ref.getAll();
env.put(Context.INITIAL_CONTEXT_FACTORY, "
com.sun.jndi.ldap.LdapCtxFactory");
while (addrs.hasMoreElements()) {
RefAddr addr = (RefAddr) addrs.nextElement();
String name = addr.getType();
String value = (String) addr.getContent();
if (name.equals("password")) {
env.put(Context.SECURITY_CREDENTIALS,
value);
}
else if (name.equals("username")) {
env.put(Context.SECURITY_PRINCIPAL, value);
}
else if (name.equals("authMechanism")) {
env.put(Context.SECURITY_AUTHENTICATION,
value);
}
else if (name.equals("url")) {
env.put(Context.PROVIDER_URL, value);
}
}
try {
ctx = new InitialDirContext(env);
} catch (NamingException ne) {
ne.printStackTrace();
throw new NamingException(ne.getMessage());
}
return ctx;
}
}
<< end ldapAccess.java >>
<< /INV/WEB-INF/web.xml >>
...
<resource-ref>
<description>Active Directory Access</description>
<res-ref-name>ldap/INV</res-ref-name>
<res-ref-type>javax.naming.DirContext</res-ref-type>
</resource-ref>
...
<< end /INV/WEB-INF/web.xml >>
Here is a test.jsp that I use this JNDI in:
<%@ page import="javax.naming.directory.*" %>
<%@ page import="javax.naming.*" %>
<%@ page import="java.util.*" %>
<%
InitialContext ic = new InitialContext();
Context envCtx = (Context)ic.lookup("java:comp/env");
DirContext ds = (DirContext)envCtx.lookup("ldap/INV");
if (ds == null) {
%>
this sucks<br />
<%
}
SearchControls searchCtls = new SearchControls();
String returnedAtts[] = {"cn","mail","department"};
HashSet dep = new HashSet();
searchCtls.setReturningAttributes(returnedAtts);
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter =
"(&(objectClass=user)(userAccountControl=512)(userPrincipalName=*))";
String searchBase = "DC=domain,DC=com";
NamingEnumeration answer = ds.search(searchBase, searchFilter,
searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult)answer.next();
Attributes attrs = sr.getAttributes();
if (attrs != null) {
try {
String department = attrs.get
("department").get().toString();
dep.add(department);
} catch (NullPointerException e) {
// null
}
}
}
ds.close();
Iterator i = dep.iterator();
while (i.hasNext()) {
%>
<%=i.next()%><br />
<%
}
%>
After I restart Tomcat, I can gather information from the AD server one
time. The next time I reload my JSPs, I get this error:
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
Best Regards,
Jason Hensley