2

I'm pretty sure i know the problem, I just don't know how to solve it.

I have a java EE application that do searches in ldap. I initialize the context with getEnv :

(note* : code is a bit simplified for understanding purposes)

InitialDirContext ctx = new InitialDirContext( getEnv( CONFIG_MAP ); //CONFIG_MAP contains  the host, mng_dn, mng_pw

public static Hashtable<String, String> getEnv( Map<String, String> configMap ) {

    // Hashtable for environmental information
    Hashtable<String, String> env = new Hashtable<String, String>();

    // Specify which class to use for our JNDI Provider
    env.put( Context.INITIAL_CONTEXT_FACTORY, INITCTX );

    // Specify the host and port to use for directory service
    env.put( Context.PROVIDER_URL, configMap.get( HOST ) );

    // Security Information
    env.put( Context.SECURITY_AUTHENTICATION, "simple" );
    env.put( Context.SECURITY_PRINCIPAL, configMap.get( MGR_DN ) );
    env.put( Context.SECURITY_CREDENTIALS, configMap.get( MGR_PW ) );
    env.put( "java.naming.ldap.attributes.binary", "objectSID" );

    return env;
}

I don't know if this was bad practice but to prevent the initialization from happening before every search I did an Init function that does :

if(Util.ctx == null ){
    Util.init()
}

So the problem comes from here. My application will work roughly 30 mins (not sure of the time) and then the searches won't work anymore and I'll get the connection reset error in my console. My guess is that the connection is "closed" and it's not doing the initialization again since ctx is not null. I need help to figure out what to add to my if statement in order to prevent this error from happening. Maybe something like

if(Util.ctx == null || Util.ctx.isClosed() ){
    Util.init();
}

I read on InitialDirContext and couldn't find what I need.

0

2 Answers 2

2

Don't try to keep reusing the same Context. Get a new one every time you need one. The server will close idle connections any time it feels like it, and isClosed() won't tell you when it has done so.

You can use the JNDI LDAP connection pooling feature to conserve connections.

Sign up to request clarification or add additional context in comments.

2 Comments

The problem is that I don't know where to initialize the context in my webapp without having the context reloading itself 20 times while changing pages and using some simple search functions. I use to have the init() in the constructor of my form that I use for the search. I tried putting it in the doGet() of my servlet but it doesn't seem like a better solution. It doesn't seem to slow the application much but I just think it loads the same information over and over for no reason
@trixrabbit If you use the connection pool, it doesn't matter how often you initialize the Context, as Contexts cease to be 1::1 with connections. That's the whole point.
1

What about set no timeout as follows:

// 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, "ldap://localhost:389/o=JNDITutorial");

// Specify time-out to be infinite time . make it like never expired
env.put("com.sun.jndi.ldap.connect.timeout", "-1");

// Create initial context
DirContext ctx = new InitialDirContext(env);

And you can close it later when needed as follows:

finally {

        if (obj instanceof Context) {

            Context ctx = (Context) obj;
            try {
                ctx.close();
            }
            catch (Exception e) {

            }

        }
    }

Check this out: https://docs.oracle.com/javase/tutorial/jndi/newstuff/readtimeout.html

5 Comments

This way the application server would always stay connected to my ldap server unless I restart the application server? Couldn't that cause problems in the long run?
I think you are right. But the thing is that you can close your connection and return it to the connection pool at the time you need by adding a finally try catch block. I mean you need explicitly close it at the point you need.see the updated answer. Not sure if this helps.
It does help but I just can't figure out when I would want to close it. My application is a web application for our intranet that allow people to search for other people's information (e-mail, phone, ,etc) like a directory. I do the init() when the search page loads. I've only tested this on localhost so I'm not sure how this will work with many users. I figured that the server does the init() once when a user reach the search page and then future users would skip the init().
I also thought of catching the error and calling init() there too.
Since your app is a webapp, I think you can close it when the session is time out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.