LDAP Connection Pooling - JCA

I'm interested in setting up connection pooling for LDAP. Our J2EE app is running on JBoss, and the database connections are already pooled through JCA using the provided JDBC resource adapter.
So, I have investigated JCA a bit to see if that is the way to go to implement connection pooling for LDAP, but I haven't come to a conclusion yet. If I was to use JCA, it looks like I would need to create a resource adapter for LDAP, which does not seem to be a trivial task. Or is there already a resource adapter out there for the Sun Directory Server?
For what I am trying to accomplish (connection pooling) is JCA overkill? If so, what would be the best course of action to take?
Thanks,
Jeff

I guess you are talking about Context Pooling ...... The new version of JNDI ( not sure from when...) has
context pooling in-built.... all you got to do is set the env property for pooling 'on'.....
env.put("com.sun.jndi.ldap.connect.pool", "true");
for further details
http://java.sun.com/products/jndi/tutorial/ldap/connect/pool.html

Similar Messages

  • Ldap Connections Pool

    Does anyone know if <cfldap> uses a connections pool? If not, can this be achieve by setting the ldap connections pool system properties since it's Java under the cover?
    Thanks.

    This is a bug in java version "1.7.0_17".
    Fixed in Java 1.7.0.40
    Bug # 7174887: Deadlock in jndi ldap connection cleanup.
    List of bugs fixed in the latst version is listed here Java™ SE Development Kit 7 Update 40 Bug Fixes
    Hope this helps!
    Regards,
    Shanmuga Catna

  • Connection pool for ldap

    Hi
    My application is an interface to ldap directory. I have not used any ldap open source api to retrieve data from ldap. I have written connection pool that will help the application to connect to the ldap. It's working fine, but it's creating threads which are not invited.
    ConnectionPool class takes care of the connection storage and creation, while Housekeeping thread relases these connection when idle after a given time.
    Can someone please help in finding the problem in the code that creates additional threads.
    package com.ba.cdLookup.manager;
    import com.ba.cdLookup.exception.CDLookupException;
    import com.ba.cdLookup.server.CdLookupProperties;
    import java.util.Vector;
    import javax.naming.Context;
    import javax.naming.NamingException;
    public class HouseKeeperThread extends Thread {
             * Apache Logger to log erro/info/debug statements.
        protected static org.apache.commons.logging.Log log = org.apache.axis.components.logger.LogFactory
             .getLog(HouseKeeperThread.class.getName());
        private static HouseKeeperThread houseKeeperThread;
             * Close all connections existing.
             * @param connections
             *                void
        private void closeConnections(Vector connections) {
         String methodIdentifier = "closeConnections";
         int numOfConn = connections.size();
         try {
             for (int i = 0; i < numOfConn; i++) {
              Context context = (Context) connections.get(i);
              if (context != null) {
                  context.close();
                  context = null;
                  connections.remove(i);
                  numOfConn--;
                  log.info(" connection name:" + context
                       + " removed. Threadcount =" + (connections.size()));
         } catch (NamingException e) {
             String errMsg = "CDLdapBuilder connect() - failure while releasing connection "
                  + " Exception is " + e.toString();
             log.error(errMsg);
         } catch (Exception e) {
             String errMsg = "CDLdapBuilder connect() - failure while releasing connection "
                  + " Exception is " + e.toString();
             log.error(errMsg);
             * Thread run method
        public void run() {
         String methodIdentifier = "run";
         try {
             while(true){
              log.debug("house keeping :" + this + " ---sleep");
              //sleep(100000);
              log.debug("house keeping :" + this + " startd after sleep");
               sleep(CdLookupProperties.getHouseKeepConnectionTime());
              ConnectionPool connectionPool = ConnectionPool
                   .getConnectionPool();
              Vector connList = connectionPool.getAvailableConnections();
              closeConnections(connList);
         } catch (CDLookupException cde) {
             log.error(methodIdentifier + " " + cde.getStackTrace());
         } catch (InterruptedException ie) {
             log.error(methodIdentifier + " " + ie.getStackTrace());
         * @param connectionPool
         * @return
         * Thread
        public static Thread getInstance() {
         if(houseKeeperThread==null){
             houseKeeperThread = new HouseKeeperThread();
         return houseKeeperThread ;
    package com.ba.cdLookup.manager;
    import com.ba.cdLookup.exception.CDLookupException;
    import com.ba.cdLookup.server.CdLookupProperties;
    import com.ba.cdwebservice.schema.cdLookupPacket.LookupFailureReasons;
    import java.util.Properties;
    import java.util.Vector;
    import javax.naming.Context;
    import javax.naming.NamingException;
    import javax.naming.directory.DirContext;
    import javax.naming.directory.InitialDirContext;
    * ConnectionPool class manages, allocates LDAP connections. It works as a lazy
    * binder and retrieves connections only when required. It doesn't allow
    * connection greater then the maximum connection stated.
    * To retrieve a connection the singelton method getConnectionPool is to used,
    * which retruns thread safe singleton object for the connection.
    public class ConnectionPool implements Runnable {
        private int initialConnections = 0;
        private int maxConnections = 0;
        private boolean waitIfBusy = false;
        private Vector availableConnections, busyConnections;
        private boolean connectionPending = false;
        private static int threadCount = 0;
             * classIdentifier
        private final String classIdentifier = "ConnectionPool";
             * Apache Logger to log erro/info/debug statements.
        protected static org.apache.commons.logging.Log log = org.apache.axis.components.logger.LogFactory
             .getLog(CDLdapBuilder.class.getName());
             * To get the attribute a systemaccessfor out of the search result
        private String vendorContextFactoryClass = "com.sun.jndi.ldap.LdapCtxFactory";// "com.ibm.jndi.LDAPCtxFactory";
             * context factory to use
        private String ldapServerUrl = "LDAP://test.ldap.com"; // default ldap
             * server live used by default
        private String searchBase;
             * environment properties.
        private Properties env;
             * DirContext
        private javax.naming.directory.DirContext ctx;
             * default search base to be used in Corporate Directory searches
        private String defaultSearchBase = "dc=Pathway";
             * search criteria
        private String searchAttributes;
             * search filter to retrieve data from CD
        private String searchFilter;
             * CorporateDirectoryLookup Constructor
             * <p>
             * loads the setup parameters from the properties file and stores them
             * Makes a connection to the directory and sets default search base
             * @throws CDLookupException
             * @throws CDLookupException
        private ConnectionPool() throws CDLookupException {
         this.maxConnections = CdLookupProperties.getMaxConnection();// maxConnections;
         this.initialConnections = CdLookupProperties.getInitialConnection();
         this.waitIfBusy = CdLookupProperties.isWaitIfBusy();
         this.searchBase = CdLookupProperties.getDefaultSearchBase();
         //for local env testing
    //      this.maxConnections = 5;
    //      this.initialConnections = 1;
    //      this.waitIfBusy = true;
             * For keeping no of connections in the connection pool if
             * (initialConnections > maxConnections) { initialConnections =
             * maxConnections; }
         availableConnections = new Vector(maxConnections);
         busyConnections = new Vector(maxConnections);
         for (int i = 0; i < maxConnections; i++) {
             availableConnections.add(makeNewConnection());
             *  ConnectionPoolHolder provide Thread safe singleton
             *         instance of ConnectionPool class
        private static class ConnectionPoolHolder {
             * connection pool instance
         private static ConnectionPool connectionPool = null;
             * If no ConnectionPool object is present, it creates instance of
             * ConnectionPool class and initiates thread on that.
             * @return ConnectionPool Returns singleton object of ConnectionPool
             *         class.
             * @throws CDLookupException
         private static ConnectionPool getInstance() throws CDLookupException {
             if (connectionPool == null) {
              connectionPool = new ConnectionPool();
              new Thread(connectionPool).start();
              // Initiate house keeping thread.
              HouseKeeperThread.getInstance().start();
             return connectionPool;
             * Returns singleton object of ConnectionPool class.
             * @return ConnectionPool
             * @throws CDLookupException
        public static ConnectionPool getConnectionPool() throws CDLookupException {
         return ConnectionPoolHolder.getInstance();
             * getConnection retrieves connections to the corp directory. In case
             * there is no available connections in the pool then it'll try to
             * create one, if the max connection limit for the connection pool
             * reaches then this waits to retrieve one.
             * @return Context
             * @throws CDLookupException
        public synchronized Context getConnection() throws CDLookupException {
         String methodIdentifier = "getConnection";
         if (!availableConnections.isEmpty()) {
             int connectionSize = availableConnections.size() - 1;
             DirContext existingConnection = (DirContext) availableConnections
                  .get(connectionSize);
             availableConnections.remove(connectionSize);
                     * If connection on available list is closed (e.g., it timed
                     * out), then remove it from available list and repeat the
                     * process of obtaining a connection. Also wake up threads that
                     * were waiting for a connection because maxConnection limit was
                     * reached.
             if (existingConnection == null) {
              notifyAll(); // Freed up a spot for anybody waiting
              return (getConnection());
             } else {
              busyConnections.add(existingConnection);
              return (existingConnection);
         } else {
                     * Three possible cases: 1) You haven't reached maxConnections
                     * limit. So establish one in the background if there isn't
                     * already one pending, then wait for the next available
                     * connection (whether or not it was the newly established one).
                     * 2) You reached maxConnections limit and waitIfBusy flag is
                     * false. Throw SQLException in such a case. 3) You reached
                     * maxConnections limit and waitIfBusy flag is true. Then do the
                     * same thing as in second part of step 1: wait for next
                     * available connection.
             if ((totalConnections() < maxConnections) && !connectionPending) {
              makeBackgroundConnection();
             } else if (!waitIfBusy) {
              throw new CDLookupException("Connection limit reached", 0);
                     * Wait for either a new connection to be established (if you
                     * called makeBackgroundConnection) or for an existing
                     * connection to be freed up.
             try {
              wait();
             } catch (InterruptedException ie) {
              String errMsg = "Exception raised =" + ie.getStackTrace();
              log.error(errMsg);
              throw new CDLookupException(classIdentifier, methodIdentifier,
                   errMsg, ie);
             // connection freed up, so try again.
             return (getConnection());
             * You can't just make a new connection in the foreground when none are
             * available, since this can take several seconds with a slow network
             * connection. Instead, start a thread that establishes a new
             * connection, then wait. You get woken up either when the new
             * connection is established or if someone finishes with an existing
             * connection.
        private void makeBackgroundConnection() {
         connectionPending = true;
         try {
             Thread connectThread = new Thread(this);
             log.debug("background thread created");
             connectThread.start();
         } catch (OutOfMemoryError oome) {
             log.error("makeBackgroundConnection ="+ oome.getStackTrace());
             * Thread run method
        public void run() {
         String methodIdentifier = "run";
         try {
             Context connection = makeNewConnection();
             synchronized (this) {
              availableConnections.add(connection);
              connectionPending = false;
              notifyAll();
         } catch (Exception e) { // SQLException or OutOfMemory
             // Give up on new connection and wait for existing one
             // to free up.
             String errMsg = "Exception raised =" + e.getStackTrace();
             log.error(errMsg);   
             * This explicitly makes a new connection. Called in the foreground when
             * initializing the ConnectionPool, and called in the background when
             * running.
             * @return Context
             * @throws CDLookupException
        private Context makeNewConnection() throws CDLookupException {
         String methodIdentifier = "makeNewConnection";
         Context context = null;
         env = new Properties();
         log.debug("inside " + methodIdentifier);
         try {
             env.put(Context.INITIAL_CONTEXT_FACTORY,
                  getVendorContextFactoryClass());
             env.put(Context.PROVIDER_URL, getLdapServerUrl());
             env.put("com.sun.jndi.ldap.connect.pool", "true");
             context = new InitialDirContext(env);
         } catch (NamingException e) {
             String errMsg = "CDLdapBuilder connect() - failure while attempting to contact "
                  + ldapServerUrl + " Exception is " + e.toString();
             throw new CDLookupException(classIdentifier, methodIdentifier,
                  errMsg, e, LookupFailureReasons.serviceUnavailable);
         } catch (Exception e) {
             String errMsg = "CDLdapBuilder connect() - failure while attempting to contact "
                  + ldapServerUrl + " Exception is " + e.toString();
             throw new CDLookupException(classIdentifier, methodIdentifier,
                  errMsg, e, LookupFailureReasons.serviceUnavailable);
         log.info("new connection :" + (threadCount++) + " name =" + context);
         log.debug("exit " + methodIdentifier);
         return context;
             * releases connection to the free pool
             * @param context
        public synchronized void free(Context context) {
         busyConnections.remove(context);
         availableConnections.add(context);
         // Wake up threads that are waiting for a connection
         notifyAll();
             * @return int give total no of avail connections.
        public synchronized int totalConnections() {
         return (availableConnections.size() + busyConnections.size());
             * Close all the connections. Use with caution: be sure no connections
             * are in use before calling. Note that you are not <I>required</I> to
             * call this when done with a ConnectionPool, since connections are
             * guaranteed to be closed when garbage collected. But this method gives
             * more control regarding when the connections are closed.
        public synchronized void closeAllConnections() {
         closeConnections(availableConnections);
         availableConnections = new Vector();
         closeConnections(busyConnections);
         busyConnections = new Vector();
             * Close all connections existing.
             * @param connections
             *                void
        private void closeConnections(Vector connections) {
         String methodIdentifier = "closeConnections";
         try {
             for (int i = 0; i < connections.size(); i++) {
              Context context = (Context) connections.get(i);
              if (context != null) {
                  log.info(" connection name:" + context
                       + " removed. Threadcount =" + (threadCount++));
                  context.close();
                  context = null;
         } catch (NamingException e) {
             String errMsg = "CDLdapBuilder connect() - failure while attempting to contact "
                  + ldapServerUrl + " Exception is " + e.toString();
             log.error(errMsg);
        public synchronized String toString() {
         String info = "ConnectionPool(" + getLdapServerUrl() + ","
              + getVendorContextFactoryClass() + ")" + ", available="
              + availableConnections.size() + ", busy="
              + busyConnections.size() + ", max=" + maxConnections;
         return (info);
             * @return the defaultSearchBase
        public final String getDefaultSearchBase() {
         return defaultSearchBase;
             * @param defaultSearchBase
             *                the defaultSearchBase to set
        public final void setDefaultSearchBase(String defaultSearchBase) {
         this.defaultSearchBase = defaultSearchBase;
             * @return the ldapServerUrl
        public final String getLdapServerUrl() {
         return ldapServerUrl;
             * @param ldapServerUrl
             *                the ldapServerUrl to set
        public final void setLdapServerUrl(String ldapServerUrl) {
         this.ldapServerUrl = ldapServerUrl;
             * @return the vendorContextFactoryClass
        public final String getVendorContextFactoryClass() {
         return vendorContextFactoryClass;
             * @param vendorContextFactoryClass
             *                the vendorContextFactoryClass to set
        public final void setVendorContextFactoryClass(
             String vendorContextFactoryClass) {
         this.vendorContextFactoryClass = vendorContextFactoryClass;
         * @return the availableConnections
        public final Vector getAvailableConnections() {
            return availableConnections;
    }

    Hi,
    As the connection pool implmentation has the bug of not extending more than the min size, workaround I use is MIN_CONN=100 and MAX_CONN=101,and just waiting for the bug to get fixed. (using Netscape SDK for java4.0)

  • Problem with JNDI/LDAP AND connection pool

    I'm a newbie to Java but am attempting to write a servlet that retrieves info use to populate the contents of drop down menus. I'd like to only have to do this once. The servlet also retrieves other data (e.g. user profile info, etc ...). I'd like to be able to use the connection pool for all of these operations but I'm getting a compile error:
    public class WhitePages extends HttpServlet {
    ResourceBundle rb = ResourceBundle.getBundle("LocalStrings");
    public static String m_servletPath = null;
    public static String cattrs = null;
    public static String guidesearchlist[] = {};
    public static int isLocalAddr = 0;
    private int aeCtr;
    private String[] sgDNArray;
    private HashMap sgDN2DNLabel = new HashMap();
    private HashMap sgDN2SearchGuide = new HashMap();
    private String strport;
    private int ldapport;
    private String ldaphost;
    private String ldapbinddn;
    private String ldapbindpw;
    private String ldapbasedn;
    private int maxsearchcontainers;
    private int maxsearchkeys;
    private String guidesearchbases;
    private String guidecontainerclass;
    private String strlocaladdr;
    private String providerurl;
    // my init method establishes the connection
    // pool and then retrieve menu data
    public void init(ServletConfig config) throws ServletException {
    super.init(config);
    String strport = config.getInitParameter("ldapport");
    ldapport = Integer.parseInt(strport);
    String strconts = config.getInitParameter("maxsearchcontainers");
    maxsearchcontainers = Integer.parseInt(strconts);
    String strkeys = config.getInitParameter("maxsearchkeys");
    maxsearchkeys = Integer.parseInt(strkeys);
    ldaphost = config.getInitParameter("ldaphost");
    ldapbinddn = config.getInitParameter("ldapbinddn");
    ldapbindpw = config.getInitParameter("ldapbindpw");
    ldapbasedn = config.getInitParameter("ldapbasedn");
    guidesearchbases = config.getInitParameter("guidesearchbases");
    guidecontainerclass = config.getInitParameter("guidecontainerclass");
    strlocaladdr = config.getInitParameter("localaddrs");
    providerurl = "ldap://" + ldaphost + ":" + ldapport;
    /* Set up environment for creating initial context */
    Hashtable env = new Hashtable(11);
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, providerurl.toString());
    /* Enable connection pooling */
    env.put("com.sun.jndi.ldap.connect.pool", "true");
    StringTokenizer st = new StringTokenizer(guidesearchbases, ":" );
    String guidesearchlist[] = new String[st.countTokens()];
    for ( int i = 0; i < guidesearchlist.length; i++ ) {
    guidesearchlist[i] = st.nextToken();
    // Get a connection from the connection pool
    // and retrieve the searchguides
    StringBuffer asm = new StringBuffer(""); // This is the advanced search menu htmlobject buffer
    StringBuffer strtmpbuf = new StringBuffer(""); // This is the simple search menu htmlobject buffer
    try {
    StringBuffer filter = new StringBuffer("");
    filter.append("(objectclass=" + guidecontainerclass + ")");
    String[] attrList = {"dn","cn","searchguide"};
    SearchControls ctls = new SearchControls();
    ctls.setReturningAttributes(attrList);
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    String attrlabelkey;
    sgDNArray = new String[guidesearchlist.length];
    for( int i = 0; i < guidesearchlist.length; i++ ) {
    // Search each of the namingspaces where
    // searchguides exist then build
    // the dynamic menus from the result
    DirContext ctx = new InitialDirContext(env);
    NamingEnumeration results = ctx.search(guidesearchlist, filter, ctls);
    I get a compile error:
    WhitePages.java:164: cannot resolve symbol
    symbol : method search (java.lang.String,java.lang.StringBuffer,javax.naming.directory.SearchControls)
    location: interface javax.naming.directory.DirContext
    NamingEnumeration results = ctx.search(guidesearchlist[i], filter, ctls);
    ^
    WhitePages.java:225: cannot resolve symbol
    symbol : variable ctx
    location: class OpenDirectory
    ctx.close();
    ^
    Can anyone help? If there is someone out there with JNDI connection pool experience I would appreciate your assistance!

    Manish
    The issue may not be related to the number of connections or the initial
    connections. Check your heap size (ms, mx). Turn on verbosegc. Your heap may
    not be big enough to accept the 25,000 rows.
    Bernie
    "Manish Kumar Singh" <[email protected]> wrote in message
    news:3e6c34ca$[email protected]..
    We are creating the result set with 25000 rows(each row has 56 columns) bygetting the connection using data source. With the initial capacity of the
    connection pool is 5 and the max capacity as 30 and grow connection as 1,
    the server gets out of memory exception, when we issue a new request, even
    after closing the previous connections.
    Now, if we change the initial capacity to 1 and rest all the things assame, the issue gets resolved and the server works fine.
    Could you please help me out in this regard????
    thanks in advance
    manish

  • Issue with LDAP Connection becuase of Network issue

    Hello All,
    We have some network issues going on which is causing the NIC (Network interface card) to failover to another NIC. Due to this failover SUN access manager's LDAP connection pool fills up and we see errors in logs "Directory is down". We have to restart the Access manager to resolve this issue which refresh the connection pool of LDAP.
    Now we have set the setting as recommended in admin guide/tuning guide. Like
    1. Set event connection idle timeout to less that firewall or loadbalancer idle timeout value.
    2. event connection retry count and interval on perticular error code.
    Despite of above settings its not working out. Is there other way to get all the stale connections back to the LDAP pool without restarting the server?
    Or something which handles the network failover or failback?
    Regards
    Chetan Kulshrestha

    The user search name is the value you should be looking at in the LDAP attributes, that's the one that it will send to LDAP on a logon attempt. If you changed this value after mapping a group, I'm not sure but you may have to remap the group to get the change.
    So on the LDAP side verify the user search attribute = the username you expect to login with (i.e. cn, samaccountname, uid, etc)
    Regards,
    Tim

  • Threading with connection pool

    Hi
    My application is an interface to ldap directory. I have not used any ldap open source api to retrieve data from ldap. I have written connection pool that will help the application to connect to the ldap. It's working fine, but it's creating threads which are not invited.
    ConnectionPool class takes care of the connection storage and creation, while Housekeeping thread relases these connection when idle after a given time.
    Can someone please help in finding the problem in the code that creates additional threads.
    package com.ba.cdLookup.manager;
    import com.ba.cdLookup.exception.CDLookupException;
    import com.ba.cdLookup.server.CdLookupProperties;
    import java.util.Vector;
    import javax.naming.Context;
    import javax.naming.NamingException;
    public class HouseKeeperThread extends Thread {
             * Apache Logger to log erro/info/debug statements.
        protected static org.apache.commons.logging.Log log = org.apache.axis.components.logger.LogFactory
             .getLog(HouseKeeperThread.class.getName());
        private static HouseKeeperThread houseKeeperThread;
             * Close all connections existing.
             * @param connections
             *                void
        private void closeConnections(Vector connections) {
         String methodIdentifier = "closeConnections";
         int numOfConn = connections.size();
         try {
             for (int i = 0; i < numOfConn; i++) {
              Context context = (Context) connections.get(i);
              if (context != null) {
                  context.close();
                  context = null;
                  connections.remove(i);
                  numOfConn--;
                  log.info(" connection name:" + context
                       + " removed. Threadcount =" + (connections.size()));
         } catch (NamingException e) {
             String errMsg = "CDLdapBuilder connect() - failure while releasing connection "
                  + " Exception is " + e.toString();
             log.error(errMsg);
         } catch (Exception e) {
             String errMsg = "CDLdapBuilder connect() - failure while releasing connection "
                  + " Exception is " + e.toString();
             log.error(errMsg);
             * Thread run method
        public void run() {
         String methodIdentifier = "run";
         try {
             while(true){
              log.debug("house keeping :" + this + " ---sleep");
              //sleep(100000);
              log.debug("house keeping :" + this + " startd after sleep");
               sleep(CdLookupProperties.getHouseKeepConnectionTime());
              ConnectionPool connectionPool = ConnectionPool
                   .getConnectionPool();
              Vector connList = connectionPool.getAvailableConnections();
              closeConnections(connList);
         } catch (CDLookupException cde) {
             log.error(methodIdentifier + " " + cde.getStackTrace());
         } catch (InterruptedException ie) {
             log.error(methodIdentifier + " " + ie.getStackTrace());
         * @param connectionPool
         * @return
         * Thread
        public static Thread getInstance() {
         if(houseKeeperThread==null){
             houseKeeperThread = new HouseKeeperThread();
         return houseKeeperThread ;
    package com.ba.cdLookup.manager;
    import com.ba.cdLookup.exception.CDLookupException;
    import com.ba.cdLookup.server.CdLookupProperties;
    import com.ba.cdwebservice.schema.cdLookupPacket.LookupFailureReasons;
    import java.util.Properties;
    import java.util.Vector;
    import javax.naming.Context;
    import javax.naming.NamingException;
    import javax.naming.directory.DirContext;
    import javax.naming.directory.InitialDirContext;
    * ConnectionPool class manages, allocates LDAP connections. It works as a lazy
    * binder and retrieves connections only when required. It doesn't allow
    * connection greater then the maximum connection stated.
    * To retrieve a connection the singelton method getConnectionPool is to used,
    * which retruns thread safe singleton object for the connection.
    public class ConnectionPool implements Runnable {
        private int initialConnections = 0;
        private int maxConnections = 0;
        private boolean waitIfBusy = false;
        private Vector availableConnections, busyConnections;
        private boolean connectionPending = false;
        private static int threadCount = 0;
             * classIdentifier
        private final String classIdentifier = "ConnectionPool";
             * Apache Logger to log erro/info/debug statements.
        protected static org.apache.commons.logging.Log log = org.apache.axis.components.logger.LogFactory
             .getLog(CDLdapBuilder.class.getName());
             * To get the attribute a systemaccessfor out of the search result
        private String vendorContextFactoryClass = "com.sun.jndi.ldap.LdapCtxFactory";// "com.ibm.jndi.LDAPCtxFactory";
             * context factory to use
        private String ldapServerUrl = "LDAP://test.ldap.com"; // default ldap
             * server live used by default
        private String searchBase;
             * environment properties.
        private Properties env;
             * DirContext
        private javax.naming.directory.DirContext ctx;
             * default search base to be used in Corporate Directory searches
        private String defaultSearchBase = "dc=Pathway";
             * search criteria
        private String searchAttributes;
             * search filter to retrieve data from CD
        private String searchFilter;
             * CorporateDirectoryLookup Constructor
             * <p>
             * loads the setup parameters from the properties file and stores them
             * Makes a connection to the directory and sets default search base
             * @throws CDLookupException
             * @throws CDLookupException
        private ConnectionPool() throws CDLookupException {
         this.maxConnections = CdLookupProperties.getMaxConnection();// maxConnections;
         this.initialConnections = CdLookupProperties.getInitialConnection();
         this.waitIfBusy = CdLookupProperties.isWaitIfBusy();
         this.searchBase = CdLookupProperties.getDefaultSearchBase();
         //for local env testing
    //      this.maxConnections = 5;
    //      this.initialConnections = 1;
    //      this.waitIfBusy = true;
             * For keeping no of connections in the connection pool if
             * (initialConnections > maxConnections) { initialConnections =
             * maxConnections; }
         availableConnections = new Vector(maxConnections);
         busyConnections = new Vector(maxConnections);
         for (int i = 0; i < maxConnections; i++) {
             availableConnections.add(makeNewConnection());
             *  ConnectionPoolHolder provide Thread safe singleton
             *         instance of ConnectionPool class
        private static class ConnectionPoolHolder {
             * connection pool instance
         private static ConnectionPool connectionPool = null;
             * If no ConnectionPool object is present, it creates instance of
             * ConnectionPool class and initiates thread on that.
             * @return ConnectionPool Returns singleton object of ConnectionPool
             *         class.
             * @throws CDLookupException
         private static ConnectionPool getInstance() throws CDLookupException {
             if (connectionPool == null) {
              connectionPool = new ConnectionPool();
              new Thread(connectionPool).start();
              // Initiate house keeping thread.
              HouseKeeperThread.getInstance().start();
             return connectionPool;
             * Returns singleton object of ConnectionPool class.
             * @return ConnectionPool
             * @throws CDLookupException
        public static ConnectionPool getConnectionPool() throws CDLookupException {
         return ConnectionPoolHolder.getInstance();
             * getConnection retrieves connections to the corp directory. In case
             * there is no available connections in the pool then it'll try to
             * create one, if the max connection limit for the connection pool
             * reaches then this waits to retrieve one.
             * @return Context
             * @throws CDLookupException
        public synchronized Context getConnection() throws CDLookupException {
         String methodIdentifier = "getConnection";
         if (!availableConnections.isEmpty()) {
             int connectionSize = availableConnections.size() - 1;
             DirContext existingConnection = (DirContext) availableConnections
                  .get(connectionSize);
             availableConnections.remove(connectionSize);
                     * If connection on available list is closed (e.g., it timed
                     * out), then remove it from available list and repeat the
                     * process of obtaining a connection. Also wake up threads that
                     * were waiting for a connection because maxConnection limit was
                     * reached.
             if (existingConnection == null) {
              notifyAll(); // Freed up a spot for anybody waiting
              return (getConnection());
             } else {
              busyConnections.add(existingConnection);
              return (existingConnection);
         } else {
                     * Three possible cases: 1) You haven't reached maxConnections
                     * limit. So establish one in the background if there isn't
                     * already one pending, then wait for the next available
                     * connection (whether or not it was the newly established one).
                     * 2) You reached maxConnections limit and waitIfBusy flag is
                     * false. Throw SQLException in such a case. 3) You reached
                     * maxConnections limit and waitIfBusy flag is true. Then do the
                     * same thing as in second part of step 1: wait for next
                     * available connection.
             if ((totalConnections() < maxConnections) && !connectionPending) {
              makeBackgroundConnection();
             } else if (!waitIfBusy) {
              throw new CDLookupException("Connection limit reached", 0);
                     * Wait for either a new connection to be established (if you
                     * called makeBackgroundConnection) or for an existing
                     * connection to be freed up.
             try {
              wait();
             } catch (InterruptedException ie) {
              String errMsg = "Exception raised =" + ie.getStackTrace();
              log.error(errMsg);
              throw new CDLookupException(classIdentifier, methodIdentifier,
                   errMsg, ie);
             // connection freed up, so try again.
             return (getConnection());
             * You can't just make a new connection in the foreground when none are
             * available, since this can take several seconds with a slow network
             * connection. Instead, start a thread that establishes a new
             * connection, then wait. You get woken up either when the new
             * connection is established or if someone finishes with an existing
             * connection.
        private void makeBackgroundConnection() {
         connectionPending = true;
         try {
             Thread connectThread = new Thread(this);
             log.debug("background thread created");
             connectThread.start();
         } catch (OutOfMemoryError oome) {
             log.error("makeBackgroundConnection ="+ oome.getStackTrace());
             * Thread run method
        public void run() {
         String methodIdentifier = "run";
         try {
             Context connection = makeNewConnection();
             synchronized (this) {
              availableConnections.add(connection);
              connectionPending = false;
              notifyAll();
         } catch (Exception e) { // SQLException or OutOfMemory
             // Give up on new connection and wait for existing one
             // to free up.
             String errMsg = "Exception raised =" + e.getStackTrace();
             log.error(errMsg);   
             * This explicitly makes a new connection. Called in the foreground when
             * initializing the ConnectionPool, and called in the background when
             * running.
             * @return Context
             * @throws CDLookupException
        private Context makeNewConnection() throws CDLookupException {
         String methodIdentifier = "makeNewConnection";
         Context context = null;
         env = new Properties();
         log.debug("inside " + methodIdentifier);
         try {
             env.put(Context.INITIAL_CONTEXT_FACTORY,
                  getVendorContextFactoryClass());
             env.put(Context.PROVIDER_URL, getLdapServerUrl());
             env.put("com.sun.jndi.ldap.connect.pool", "true");
             context = new InitialDirContext(env);
         } catch (NamingException e) {
             String errMsg = "CDLdapBuilder connect() - failure while attempting to contact "
                  + ldapServerUrl + " Exception is " + e.toString();
             throw new CDLookupException(classIdentifier, methodIdentifier,
                  errMsg, e, LookupFailureReasons.serviceUnavailable);
         } catch (Exception e) {
             String errMsg = "CDLdapBuilder connect() - failure while attempting to contact "
                  + ldapServerUrl + " Exception is " + e.toString();
             throw new CDLookupException(classIdentifier, methodIdentifier,
                  errMsg, e, LookupFailureReasons.serviceUnavailable);
         log.info("new connection :" + (threadCount++) + " name =" + context);
         log.debug("exit " + methodIdentifier);
         return context;
             * releases connection to the free pool
             * @param context
        public synchronized void free(Context context) {
         busyConnections.remove(context);
         availableConnections.add(context);
         // Wake up threads that are waiting for a connection
         notifyAll();
             * @return int give total no of avail connections.
        public synchronized int totalConnections() {
         return (availableConnections.size() + busyConnections.size());
             * Close all the connections. Use with caution: be sure no connections
             * are in use before calling. Note that you are not <I>required</I> to
             * call this when done with a ConnectionPool, since connections are
             * guaranteed to be closed when garbage collected. But this method gives
             * more control regarding when the connections are closed.
        public synchronized void closeAllConnections() {
         closeConnections(availableConnections);
         availableConnections = new Vector();
         closeConnections(busyConnections);
         busyConnections = new Vector();
             * Close all connections existing.
             * @param connections
             *                void
        private void closeConnections(Vector connections) {
         String methodIdentifier = "closeConnections";
         try {
             for (int i = 0; i < connections.size(); i++) {
              Context context = (Context) connections.get(i);
              if (context != null) {
                  log.info(" connection name:" + context
                       + " removed. Threadcount =" + (threadCount++));
                  context.close();
                  context = null;
         } catch (NamingException e) {
             String errMsg = "CDLdapBuilder connect() - failure while attempting to contact "
                  + ldapServerUrl + " Exception is " + e.toString();
             log.error(errMsg);
        public synchronized String toString() {
         String info = "ConnectionPool(" + getLdapServerUrl() + ","
              + getVendorContextFactoryClass() + ")" + ", available="
              + availableConnections.size() + ", busy="
              + busyConnections.size() + ", max=" + maxConnections;
         return (info);
             * @return the defaultSearchBase
        public final String getDefaultSearchBase() {
         return defaultSearchBase;
             * @param defaultSearchBase
             *                the defaultSearchBase to set
        public final void setDefaultSearchBase(String defaultSearchBase) {
         this.defaultSearchBase = defaultSearchBase;
             * @return the ldapServerUrl
        public final String getLdapServerUrl() {
         return ldapServerUrl;
             * @param ldapServerUrl
             *                the ldapServerUrl to set
        public final void setLdapServerUrl(String ldapServerUrl) {
         this.ldapServerUrl = ldapServerUrl;
             * @return the vendorContextFactoryClass
        public final String getVendorContextFactoryClass() {
         return vendorContextFactoryClass;
             * @param vendorContextFactoryClass
             *                the vendorContextFactoryClass to set
        public final void setVendorContextFactoryClass(
             String vendorContextFactoryClass) {
         this.vendorContextFactoryClass = vendorContextFactoryClass;
         * @return the availableConnections
        public final Vector getAvailableConnections() {
            return availableConnections;
    }

    hi ejp
    Thx for the reply.
    // Enable connection pooling
    env.put("com.sun.jndi.ldap.connect.pool", "true");
    Is this suffice to get the connection pool working,
    Should i merely have a thread to maintain the connection with the ldap that uses sun's connection pool; or allow requestes to create new object for the connection and still this pool will hold.
    for example in the above code instead to housekeep the thread merely maintain connection with the pool
    or
    should I directly connect each object with the ldap?
    I am unable to understand how exactly sun's connection pool is working and how it should be used. I have gone thru the following example but picture is still hazy and undigestable to me.
    java.sun.com/products/jndi/tutorial/ldap/connect/pool.html
    Rgds

  • LDAP Connection exception: unable to retreive the specified realm(s).

    I am using Embedded OC4J and I have a web form based authentication (j_security _check) and configured my orion-application.xml to use LDAP connection in this way:
    <?xml version = '1.0' encoding = 'windows-1252'?>
    <orion-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-application-10_0.xsd">
    <jazn provider="LDAP" location="ldap://192.168.1.114:389"
    default-realm="cn" jaas-mode="doAsPrivileged"/>
    <jazn-loginconfig>
    <application>
    <name>ceads</name>
    <login-modules>
    <login-module>
    <class>oracle.security.jazn.login.module.LDAPLoginModule</class>
    <control-flag>required</control-flag>
    <options>
    <option>
    <name>oracle.security.jaas.ldap.connect.pool.prefsize</name>
    <value>10</value>
    </option>
    ....... other LDAp parameters ...
    When I try to log in, is always failed and I get this exception. I have no Idea what to do.
    javax.security.auth.login.LoginException: oracle.security.jazn.JAZNException: The system is unable to retreive the specified realm(s).
    at oracle.security.jazn.spi.ldap.LDAPRealmManager.searchRealms(LDAPRealmManager.java:1194)
    at oracle.security.jazn.spi.ldap.LDAPRealmManager.getRealm(LDAPRealmManager.java:238)
    at oracle.security.jazn.login.module.RealmLoginModule.getRealmFromUsername(RealmLoginModule.java:247)
    at oracle.security.jazn.login.module.RealmLoginModule.getRealm(RealmLoginModule.java:219)
    at oracle.security.jazn.login.module.RealmLoginModule.getRealmUser(RealmLoginModule.java:198)
    at oracle.security.jazn.login.module.RealmLoginModule.authenticate(RealmLoginModule.java:111)
    at oracle.security.jazn.login.module.RealmLoginModule.authenticate(RealmLoginModule.java:86)
    at oracle.security.jazn.login.module.AbstractLoginModule.login(AbstractLoginModule.java:265)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
    at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
    at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
    at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
    at oracle.security.jazn.oc4j.OC4JUtil.doJAASLogin(OC4JUtil.java:241)
    at oracle.security.jazn.oc4j.GenericUser$1.run(JAZNUserManager.java:818)
    at oracle.security.jazn.oc4j.OC4JUtil.doWithJAZNClsLdr(OC4JUtil.java:173)
    at oracle.security.jazn.oc4j.GenericUser.authenticate(JAZNUserManager.java:814)
    at oracle.security.jazn.oc4j.FilterUser.authenticate(JAZNUserManager.java:1143)
    at com.evermind.server.http.EvermindHttpServletRequest.checkAndSetRemoteUser(EvermindHttpServletRequest.java:3760)
    at com.evermind.server.http.EvermindHttpServletRequest.getUserPrincipalInternal(EvermindHttpServletRequest.java:3727)
    at com.evermind.server.http.HttpApplication.checkAuthenticationAndAuthorize(HttpApplication.java:6350)
    at com.evermind.server.http.HttpApplication.getRequestDispatcher(HttpApplication.java:3030)
    at com.evermind.server.http.HttpRequestHandler.doProcessRequest(HttpRequestHandler.java:738)
    at com.evermind.server.http.HttpRequestHandler.processRequest(HttpRequestHandler.java:453)
    at com.evermind.server.http.HttpRequestHandler.serveOneRequest(HttpRequestHandler.java:221)
    at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:122)
    at com.evermind.server.http.HttpRequestHandler.run(HttpRequestHandler.java:111)
    at oracle.oc4j.network.ServerSocketReadHandler$SafeRunnable.run(ServerSocketReadHandler.java:260)
    at oracle.oc4j.network.ServerSocketAcceptHandler.procClientSocket(ServerSocketAcceptHandler.java:234)
    at oracle.oc4j.network.ServerSocketAcceptHandler.access$700(ServerSocketAcceptHandler.java:29)
    at oracle.oc4j.network.ServerSocketAcceptHandler$AcceptHandlerHorse.run(ServerSocketAcceptHandler.java:879)
    at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:303)
    at java.lang.Thread.run(Thread.java:595)
    Caused by: java.lang.IllegalStateException: LDAP properties not properly defined. Please check your JAZN configuration.
    at oracle.security.jazn.spi.ldap.LDAPContext.getDirContext(LDAPContext.java:476)
    at oracle.security.jazn.spi.ldap.LDAPContext.getDefaultDirContext(LDAPContext.java:246)
    at oracle.security.jazn.spi.ldap.LDAPContext.getOrclRootCtxDN(LDAPContext.java:187)
    at oracle.security.jazn.spi.ldap.LDAPContext.getSiteJAZNCtxDN(LDAPContext.java:222)
    at oracle.security.jazn.spi.ldap.LDAPRealmManager.searchRealms(LDAPRealmManager.java:1087)
    ... 37 more
    Edited by: user6112181 on 15-oct-2010 19:30
    Edited by: user6112181 on 15-oct-2010 19:31

    Hi,
    Can you access the URL using a browser? Does it work with the credentials used for the RunAs account?
    Strange error message though - are the account you are running the console with, present in the SCSM CMDB?
    Regards
    //Anders
    Anders Asp | Lumagate | www.lumagate.com | Sweden | My blog: www.scsm.se

  • LDAP connection timeout exception - some times

    Hi Team,
    I'm using Ldap authentication for my web applications. Everything is working fine most of the times.
    But ones in every 15 days or 10 days, I'm getting the connection timeout. But if I restart the tomcat then everything working fine. I couldn't find any
    issues with my code. Can anyone please help me on this. below is my java code. I'm keeping all the ldap entries in tomcat's server.xml and getting them in my java code to avoid the hard
    code configurations in my java code.
    I'm closing the context and naming enumerations like below, but still getting javax.naming.CommunicationException: error.
    Can anyone please help me out on this.
    public boolean authenticateFromLdap(String username, String password)throws AuthenticationException,Exception {
        LdapContext ctx = null;
        Context newctx = new InitialContext();
        Context envCtx = (Context) newctx.lookup("java:comp/env");
        DirContext ctxDir = (DirContext)envCtx.lookup("ldap/myapp");
        NamingEnumeration<?> namingEnum = null;
        String userDN=null;
        boolean isauthenticated = false;
        try {
            Hashtable env = null;
            Control[] connCtls = null;
            env = ctxDir.getEnvironment();
            env.put(Context.REFERRAL, "follow");
            this.filter = (String)env.get("ldap.filter");
            this.base = (String)env.get("ldap.base");
            try {
                ctx = new InitialLdapContext(env, connCtls);
                ctx.setRequestControls(null);
            } catch (javax.naming.AuthenticationException ex) {
                throw new Exception("ldap.server.exception");
            } catch (Exception ex) {
                throw new Exception("ldap.server.exception");
            try {
                SearchControls searchControls = new SearchControls();
                searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
                searchControls.setTimeLimit(30000);
                String filter="("+this.filter+"="+username+")";
                ctx.setRequestControls(null);
                namingEnum = ctx.search(this.base, filter, searchControls);
                SearchResult result = (SearchResult) namingEnum.next();
                Attributes attrs = result.getAttributes();
                Attribute str1=attrs.get("userprincipalname");
                userDN=str1.get().toString();
                if(userDN==null){
                    userDN=username;
                ctx.addToEnvironment(Context.SECURITY_PRINCIPAL,userDN);
                ctx.addToEnvironment(Context.SECURITY_CREDENTIALS,password);
                ctx.reconnect(connCtls);
                isauthenticated = true;
            }catch (AuthenticationException ex) {
                throw new AuthenticationException();
            }catch (NamingException ex) {
                throw new Exception("ldap.server.exception");
            return isauthenticated;
        } finally {
            if (null != namingEnum) {
                try {
                    namingEnum.close();
                } catch (Exception e) {
                    throw new Exception("close.ldap.failure");
            if (null != ctx) {
                try {
                    ctx.close();
                } catch (Exception e) {
                    throw new Exception("close.ldap.failure");
    }Tomcat (v6.0.14) server.xml:
                    <Resource name="ldap/myapp"
                                                    auth="Container"
                                                    type="com.sun.jndi.ldap.LdapCtx"
                                                    factory="com.myapp.MyLdapFactory"
                                                    java.naming.factory.initial="com.sun.jndi.ldap.LdapCtxFactory"
                                                    com.sun.jndi.ldap.connect.pool="false"
                                                    java.naming.provider.url="ldap://ldap.com.test.net:389"
                                                    java.naming.security.authentication="simple"
                                                    java.naming.security.principal="MyAdmin"
                                                    java.naming.security.credentials="xxxxxxx"
                                                    ldap.base="DC=com,DC=test,DC=net"
                                                    ldap.filter="sAMAccountName"
                    />Below is the error log trace:
    2013-Mar-26 12:01:34,714 AppUserDetailsService - javax.naming.CommunicationException: ldap.com.test.net:389 [Root exception is java.net.ConnectException: Connection timed out: connect]Note: Once we restart the tomcat, everything is working as usual and after 2 weeks again same problem occuring.
    Ganesh
    Edited by: EJP on 27/03/2013 14:26: added {noformat}{noformat} tags. Please use them. Your code is unreadable without them.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

    1. 'filter' and 'base' need to be local variables, not instance variables, otherwise the method isn't thread-safe.
    2. It isn't clear that you are closing the search results or contexts if you get an exception, in all that spaghetti, especially the part where you just catch and rethrow exceptions, which is pointless. You need to rewrite that lot like this:
    public boolean authenticateFromLdap(String username, String password) throws AuthenticationException, NamingException
         Context newctx = new InitialContext();
         try
              Context envCtx = (Context)newctx.lookup("java:comp/env");
              try
                   DirContext ctxDir = (DirContext)envCtx.lookup("ldap/myapp");
                   try
                        String userDN = null;
                        boolean isauthenticated = false;
                        Control[] connCtls = null;
                        Hashtable env = ctxDir.getEnvironment();
                        env.put(Context.REFERRAL, "follow");
                        String     filter = (String)env.get("ldap.filter");
                        String     base = (String)env.get("ldap.base");
                        LdapContext ctx = new InitialLdapContext(env, connCtls);
                        try
                             ctx.setRequestControls(null);
                             SearchControls searchControls = new SearchControls();
                             searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
                             searchControls.setTimeLimit(30000);
                             filter = "(" + filter + "=" + username + ")";
                             ctx.setRequestControls(null);
                             NamingEnumeration<SearchResult> namingEnum = ctx.search(base, filter, searchControls);
                             try
                                  SearchResult result = namingEnum.next();
                                  Attributes attrs = result.getAttributes();
                                  Attribute str1 = attrs.get("userprincipalname");
                                  userDN = str1.get().toString();
                                  if (userDN == null)
                                       userDN = username;
                                  ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
                                  ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
                                  ctx.reconnect(connCtls);
                                  isauthenticated = true;
                                  return isauthenticated;
                             finally
                                  namingEnum.close();
                        finally
                             ctx.close();
                   finally
                        ctxDir.close();
              finally
                   envCtx.close();
         finally
              newctx.close();
    }Also, you are suppressing exceptions when you rethrow. Never do that. Always log the actual exception. But there aren't any exceptions here that need to be caught and rethrown.

  • Help needed for Connection Pooling

    I want to know about connection pooling in java.Can anyone suggest a best tutorial or link to learn this.

    http://java.sun.com/developer/onlineTraining/Programming/JDCBook/conpool.html
    http://java.sun.com/products/jndi/tutorial/ldap/connect/pool.html
    or better Google it.

  • LDAP connections not being closed

    Hi,
    I am trying to authenticate against a Netscape LDAP server and it works fine for 2 out of the 3 cases I am testing against.
    The first case is authenticating with the correct username and correct password. In this case the user is authenticated and the connection is closed.
    In the second case, I try to authenticate with the correct username and a wrong password. The authentication fails and an AuthenticationException is thrown. The connection is closed.
    In the third case, where I have the PROBLEM is if I provide a wrong username, AuthenticationException is thrown indicating that such an username does not exist. But the CONNECTION IS NOT CLOSED.
    Following is the code :
         private boolean authenticate(String userName, String password) throws Exception {
              Hashtable env = new Hashtable(11);
              env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
              env.put("com.sun.jndi.ldap.connect.pool", "false");
              env.put(Context.SECURITY_AUTHENTICATION, "simple");
              env.put(Context.SECURITY_PROTOCOL, "ssl");
              env.put(Context.SECURITY_PRINCIPAL, getSecurityPrincipal(userName));
              env.put(Context.SECURITY_CREDENTIALS, password);
              env.put(Context.PROVIDER_URL,"ldap://ldap05.nike.com:11003");
              DirContext ctx = null;
              try {
                   // Create initial context
                   ctx = new InitialDirContext(env);
                   return true;
              } catch (AuthenticationException e) {
                   log.error(e.getMessage());
              } catch (NamingException e) {
                   log.error("The user could not be validated on LDAP server due to :" + e.getMessage());
              } finally {
                   if (ctx != null) {
                        ctx.close();
              return false;
         }Any help is appreciated.
    Thanks in Advance.

    I did run the NETSTAT command and found some interesting things.
    I ran it for the three cases. The first case is running netstat immediately after authenticating the user with VALID credentials. The status of the connection is TIME_WAIT which is the desired behaviour.
    In the second case, when trying to authenticate with CORRECT username but a wrong password, an AuthenticationException is thrown. When I run the netstat command, the connection is in TIME_WAIT state which is the desired one.
    In the third case, when I provide a wrong username, an AuthenticationException is thrown. When I run the netstat command, the connection is in ESTABLISHED state, which it should not be in.
    An authenticationException is thrown for wrong username and also for wrong password. But the connection is closed for wrong password, but not for wrong username.This is what seems to me as a weird behaviour.
    I was under the impression that in the CODE I mentioned at the begining of this topic, the INITIALDIRCONTEXT had the responsibility of closing the connection when authentication fails as we don't have a handle to close it. It is doing so in the case of ERROR 49 which is wrong password, but not in the case of ERROR 32 which is wrong username. Correct me if I am wrong, but doesn't it seem to be a bug with the INITIALDIRCONTEXT class.
    Thanks.

  • Photo Directory LDAP Connection

    I keep getting "User Not Found" using the photodirectory.jsp. Are we supposed to hit the Call Manager server with LDAP queries? I've been trying to use our corporate LDAP (Active Directory) through our primary DC, but I've noticed a hard coded OU setting in the User.java that makes me suspect I should be using Call Manager in my searches.

    I have in fact done it, although my search method is pretty close to the sendRequest method by Cisco, except that I'm throwing custom exceptions back including all the info about the ldap query (I never quite could figure out what was going wrong unless you log that kind of thing) and my return values use generics so as to spare me the casting.
    One thing I added was search controls.. I'm doing server side sorting whenever possible, but you gotta be careful with that. AD supports it, OpenLDAP doesn't (I just banged me head for a while last week wondering about an error message I got back from an OpenLDAP server last week.. turns out it simply doesn't do server side sorting).. so you probably want to have a look at Collections.sort as well.
    You might also want to do some connection pooling by adding the following to the env variable:
    env.put("com.sun.jndi.ldap.connect.pool", "true");
    That way, your second and third request won't take so long to get the context initiated.. that's especially important if you do many queries to the same directory hierarchy (e.g. searching your AD users multiple times).
    But other than that, the LDAPProvider.java class is quite good.. it's the part above that that you need to change.. every directory needs a different root and base search path. When I first got started, I spent quite some time figuring out what to put as root and what as base search path.. I finally settled on accessing the directory by ldap browser, which can search for your roots, then use the most specific one, and use the path from that root down the tree until the branch that you want to search as the base search path (in Cisco's code they call it searchbase).
    Oh, and you might also want to be more flexible as to the scope.. sometimes one level is enough, sometimes it isn't (you can verify that by launching your search via ldapbrowser). Since ldapbrowser is java based, it's the ideal tool to make your tests.. it will be based on the same classes and methods you're going to be using, so if you can get it to work with ldapbrowser, you can get it to work in your code, and if ldapbrowser fails, there's no point wasting your time trying to adjust your own code.
    So my suggestion would be to make these few modifications to the cisco ldap provider, and then just worry about what you put above that (you need to process the hashmap with the results somehow).

  • Win2K, Connection pools & LDAP

    Hi -
    I'm not sure whether this is a dumb question or not, but...
    We're planning to use NT Authentication in our system to validate
    users. In addition, we want to use connection pooling for performance.
    Are these mutually exclusive? What I would like to be able to do is
    have a user log into our system, get validated through an LDAP call,
    and when he/she hits a part of the system that makes a database
    call, use a connection from a pool to get the data. So far, I think
    I've got it sussed out. The twist comes from needing to have an
    audit trail of all database changes. The current version of the system
    uses triggers to make this happen, and identifies the current user
    through their database login, and makes an appropriate entry in a
    log table.
    But it seems to me, that if I'm using connection pooling, then the
    username is always the same one (the one used to open the pool).
    Is there any way to be able to get the "real" username?
    thanks,
    andy

    More information on this issue.
    I'm using the method DriverManager.getConnection(URL) to get a connection to
    the database, passing in the name of the connection pool. This method is
    throwing the following SecurityException:
    java.lang.SecurityException: User "john" does not have Permission
    "reserve"
    based on ACL "weblogic.jdbc.connectionPool.ICOM_DEV2_A".
    When running under the LDAP realm:
    -calls to getConnection() from within a jsp fail
    -calls to getConnection() from within a Session Bean or Entity Bean work
    -calls to getConnection() from a non-EJB class fail if it is called directly
    from the jsp
    -calls to getConnection() from a non-EJB class work if it is called from a
    Session Bean
    When running under the RDBMS realm, all calls to getConnection() work,
    whether they are a jsp, non-EJB class or a Session Bean.
    Is there some security context that is only present inside the EJB
    container?

  • JCA Connection Pooling

    I have a JCA resource adapter configured for connection pooling. If a connection is not used for a period of time is there any way to say it should be closed and released from the pool?
    Thanks

    https://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/docs/library/uuid/bc9baf90-0201-0010-479a-b49b25598ebf
    Try that!

  • Connection pooling and auditing on an oracle database

    Integration of a weblogic application with an oracle backend,
    Connection pooling, and auditing ,2 conflicting requirements ?
    Problem statement :
    We are in the process of maintaining a legacy client server application where
    the client is
    written in PowerBuilder and the backend is using an Oracle database.
    Almost all business logic is implemented in stored procedures on the database.
    When working in client/server mode ,1 PowerBuilder User has a one-to-one relation
    with
    a connection(session) on the oracle database.
    It is a requirement that the database administrator must see the real user connected
    to the database
    and NOT some kind of superuser, therefore in the PowerBuilder app each user connects
    to the database
    with his own username.(Each user is configured on the database via a seperate
    powerbuilder security app).
    For the PowerBuilder app all is fine and this app can maintain conversional state(setting
    and
    reading of global variables in oracle packages).
    The management is pushing for web-based application where we will be using bea
    weblogic appserver(J2EE based).
    We have build an business app which is web-based and accessing the same oracle
    backend app as
    the PowerBuilder app is doing.
    The first version of this web-based app is using a custom build connector(based
    on JCA standard and
    derived from a template provided by the weblogic integration installation).
    This custom build connector is essentially a combination of a custom realm in
    weblogic terms
    and a degraded connection pool , where each web session(browser) has a one-to-one
    relation
    with the back end database.
    The reason that this custom connector is combining the security functionality
    and the pooling
    functionality , is because each user must be authenticated against the oracle
    database(security requirement)
    and NOT against a LDAP server, and we are using a statefull backend(oracle packages)
    which would make it
    difficult to reuse connections.
    A problem that surfaced while doing heavy loadtesting with the custom connector,
    is that sometimes connections are closed and new ones made in the midst of a transaction.
    If you imagine a scenario where a session bean creates a business entity ,and
    the session bean
    calls 1 entity bean for the header and 1 entity bean for the detail, then the
    header and detail
    must be created in the same transaction AND with the same connection(there is
    a parent-child relationship
    between header and detail enforced on the back end database via Primary and Foreing
    Keys).
    We have not yet found why weblogic is closing the connection!
    A second problem that we are experincing with the custom connector, is the use
    of CMP(container managed persistence)
    within entity beans.
    The J2EE developers state that the use of CMP decreases the develoment time and
    thus also maintenance costs.
    We have not yet found a way to integrate a custom connector with the CMP persistence
    scheme !
    In order to solve our loadtesting and CMP persistence problems i was asked to
    come up with a solution
    which should not use a custom connector,but use standard connection pools from
    weblogic.
    To resolve the authentication problem on weblogic i could make a custom realm
    which connects to the
    backend database with the username and password, and if the connection is ok ,
    i could consider this
    user as authenticated in weblogic.
    That still leaves me with the problem of auditing and pooling.
    If i were to use a standard connection pool,then all transaction made in the oracle
    database
    would be done by a pool user or super user, a solution which will be rejected
    by our local security officer,
    because you can not see which real user made a transaction in the database.
    I could still use the connection pool and in the application , advise the application
    developers
    to set an oracle package variable with the real user, then on arrival of the request
    in the database,
    the logic could use this package variable to set the transaction user.
    There are still problems with this approach :
    - The administrator of the database can still not see who is connected , he will
    only see the superuser connection.
    - This scheme can not be used when you want to use CMP persistence , since it
    is weblogic who will generate the code
    to access the database.
    I thought i had a solution when oracle provided us with a connection pool known
    as OracleOCIConnectionPool
    where there is a connection made by a superuser, but where sessions are multiplexed
    over this physical pipe with the real user.
    I can not seem to properly integrate this OCI connectionpool into weblogic.
    When using this pool , and we are coming into a bean (session or entity bean)
    weblogic is wrapping
    this pool with it's own internal Datasource and giving me back a connection of
    the superuser, but not one for the real user,
    thus setting me with my back to the wall again.
    I would appreciate if anyone had experienced the same problem to share a possible
    solution with us
    in order to satisfy all requirements(security,auditing,CMP).
    Many Thanks
    Blyau Gino
    [email protected]

    Hi Blyau,
    As Joe has already provided some technical advice,
    I'll try to say something on engineering process level.
    While migrating an application from one technology to
    other, like client-server to n-tier in you case, customers and
    stakeholders want to push into the new system as many old
    requirements as possible. This approach is AKA "we must
    have ALL of the features of the old system". Mostly it happens
    because they don't know what they want. Ad little understanding
    of abilities of the new technology, and you will get a requirement
    like the one you have in you hands.
    I think "DBA must see real user" is one of those. For this
    type of requirements it can make sense to try to drop it,
    or to understand its nature and suggest alternatives. In this
    particular case it can be a system that logs user names,
    login and logout times.
    Blind copying of old features into an incompatible new architecture
    may endanger the whole project and can result in its failure.
    Hope this helps.
    Regards,
    Slava Imeshev
    "Blyau Gino" <[email protected]> wrote in message
    news:[email protected]...
    >
    Integration of a weblogic application with an oracle backend,
    Connection pooling, and auditing ,2 conflicting requirements ?
    Problem statement :
    We are in the process of maintaining a legacy client server applicationwhere
    the client is
    written in PowerBuilder and the backend is using an Oracle database.
    Almost all business logic is implemented in stored procedures on thedatabase.
    When working in client/server mode ,1 PowerBuilder User has a one-to-onerelation
    with
    a connection(session) on the oracle database.
    It is a requirement that the database administrator must see the real userconnected
    to the database
    and NOT some kind of superuser, therefore in the PowerBuilder app eachuser connects
    to the database
    with his own username.(Each user is configured on the database via aseperate
    powerbuilder security app).
    For the PowerBuilder app all is fine and this app can maintainconversional state(setting
    and
    reading of global variables in oracle packages).
    The management is pushing for web-based application where we will be usingbea
    weblogic appserver(J2EE based).
    We have build an business app which is web-based and accessing the sameoracle
    backend app as
    the PowerBuilder app is doing.
    The first version of this web-based app is using a custom buildconnector(based
    on JCA standard and
    derived from a template provided by the weblogic integrationinstallation).
    This custom build connector is essentially a combination of a custom realmin
    weblogic terms
    and a degraded connection pool , where each web session(browser) has aone-to-one
    relation
    with the back end database.
    The reason that this custom connector is combining the securityfunctionality
    and the pooling
    functionality , is because each user must be authenticated against theoracle
    database(security requirement)
    and NOT against a LDAP server, and we are using a statefull backend(oraclepackages)
    which would make it
    difficult to reuse connections.
    A problem that surfaced while doing heavy loadtesting with the customconnector,
    >
    is that sometimes connections are closed and new ones made in the midst ofa transaction.
    If you imagine a scenario where a session bean creates a business entity,and
    the session bean
    calls 1 entity bean for the header and 1 entity bean for the detail, thenthe
    header and detail
    must be created in the same transaction AND with the same connection(thereis
    a parent-child relationship
    between header and detail enforced on the back end database via Primaryand Foreing
    Keys).
    We have not yet found why weblogic is closing the connection!
    A second problem that we are experincing with the custom connector, is theuse
    of CMP(container managed persistence)
    within entity beans.
    The J2EE developers state that the use of CMP decreases the develomenttime and
    thus also maintenance costs.
    We have not yet found a way to integrate a custom connector with the CMPpersistence
    scheme !
    In order to solve our loadtesting and CMP persistence problems i was askedto
    come up with a solution
    which should not use a custom connector,but use standard connection poolsfrom
    weblogic.
    To resolve the authentication problem on weblogic i could make a customrealm
    which connects to the
    backend database with the username and password, and if the connection isok ,
    i could consider this
    user as authenticated in weblogic.
    That still leaves me with the problem of auditing and pooling.
    If i were to use a standard connection pool,then all transaction made inthe oracle
    database
    would be done by a pool user or super user, a solution which will berejected
    by our local security officer,
    because you can not see which real user made a transaction in thedatabase.
    I could still use the connection pool and in the application , advise theapplication
    developers
    to set an oracle package variable with the real user, then on arrival ofthe request
    in the database,
    the logic could use this package variable to set the transaction user.
    There are still problems with this approach :
    - The administrator of the database can still not see who is connected ,he will
    only see the superuser connection.
    - This scheme can not be used when you want to use CMP persistence , sinceit
    is weblogic who will generate the code
    to access the database.
    I thought i had a solution when oracle provided us with a connection poolknown
    as OracleOCIConnectionPool
    where there is a connection made by a superuser, but where sessions aremultiplexed
    over this physical pipe with the real user.
    I can not seem to properly integrate this OCI connectionpool intoweblogic.
    When using this pool , and we are coming into a bean (session or entitybean)
    weblogic is wrapping
    this pool with it's own internal Datasource and giving me back aconnection of
    the superuser, but not one for the real user,
    thus setting me with my back to the wall again.
    I would appreciate if anyone had experienced the same problem to share apossible
    solution with us
    in order to satisfy all requirements(security,auditing,CMP).
    Many Thanks
    Blyau Gino
    [email protected]

  • Configuring JCo3 Connection Pool with single sign on on non SAP Java server

    Hi Everyone,
    i have configured a connection pool on JBoss as per JCo3 Documentation and is working great.
    Now I need help to configure this connection pool with single sign on so that RFc on SAP ECC systems are executed using end users credential rather than using single user name password used to configure JCo connection pool.
    On SAP Java stack I am sure its possible within Java WebDynpro    and i assume using JCA resource adapter. But what if we don't want to use SAP Java App server.
    Any help will be appreciated.
    Thanks,
    Divyakumar Jain

    Eason, 你好!
    I have exactly the same problem.  Did you find a solution to this problem?  If so, please let me know!

Maybe you are looking for