Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring LDAP NullPointerException

Tags:

java

spring

ldap

I am using Java Spring version 1.3.1-RELEASE. There seems to be a problem with the LdapTemplate when trying to do anything and it returns a NullPointerException. When I instantiate a LdapTemplate through xml config, it works. However, when I instantiate a new LdapTemplate instance through the Java code and populate the properties that I put in the xml config, it returns a NullPointerException.

xml congfig

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
    <property name="url" value="ldap://localhost:10389"/>
    <property name="base" value="o=channel"/>
    <property name="userDn" value="uid=admin,ou=system"/>
    <property name="password" value="secret"/>
</bean>

<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
    <constructor-arg ref="contextSource"/>
</bean>

<bean id="ldapService" class="com.webchannel.services.ldap.LDAPService" scope="prototype">
           <!-- <property name="dao" ref="dao"></property>-->
     <property name="ldapTemplate" ref="ldapTemplate"></property>
</bean>
</beans>

When I try to use the LdapTemplate to save an entry it works perfectly. However, when doing the same with instantiate a new LdapTemplate I get a NullPointerException:

public class LDAPService<T> {

private LdapTemplate ldapTemplate;
private LdapContextSource ldapContextSource;

public LDAPService(DAO dao) throws Exception {
    ldapContextSource = new LdapContextSource();
    ldapTemplate = new LdapTemplate();
    ldapContextSource.setUrl(dao.findAll(LDAPDetail.class).get(0).getUrl());
    ldapContextSource.setBase(dao.findAll(LDAPDetail.class).get(0).getBase());
    ldapContextSource.setUserDn(dao.findAll(LDAPDetail.class).get(0).getUserDn());
    ldapContextSource.setPassword(dao.findAll(LDAPDetail.class).get(0).getPassword());
    ldapTemplate = new LdapTemplate(ldapContextSource); // this does not work
    ldapTemplate.setContextSource(ldapContextSource); // this does not work
                ldapTemplate.afterPropertiesSet();
}
}

I need the second approach because I don't want to hard code the information in the xml config, I need to get the information from the database at runtime.

When using ldapTemplate to save, delete, update or find it returns a java.lang.NullPointerException.

Having compared the ldapTemplate properties of both, it seems that the LdapTemplate through xml config contains a authenticationSource populated and the instantiate through the Java code leaves the authenticationSource to null.

Any ideas?

EDIT:

 java.lang.NullPointerException
at org.springframework.ldap.core.support.AbstractContextSource.getReadWriteContext(AbstractContextSource.java:138)
at org.springframework.ldap.core.LdapTemplate.executeReadWrite(LdapTemplate.java:801)
at org.springframework.ldap.core.LdapTemplate.bind(LdapTemplate.java:996)
at org.springframework.ldap.core.LdapTemplate.bind(LdapTemplate.java:1354)
at com.webchannel.services.ldap.LDAPService.saveEntry(LDAPService.java:122)
at com.webchannel.services.ldap.LDAPServiceTest.testSaveEntry(LDAPServiceTest.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
like image 402
user1646481 Avatar asked Oct 14 '13 11:10

user1646481


2 Answers

LdapContextSource is InitializingBean. That means if you are creating the instance manually, you have to call afterPropertiesSet(). Quote from its JavaDoc:

Note: When using implementations of this class outside of a Spring Context it is necessary to call #afterPropertiesSet() when all properties are set, in order to finish up initialization.


By the way do you know that you can use property placeholders ${myproperty} to leave the configuration in an external property source (such as .properties file)? Check this blog post and the <context:property-placeholder> example in scenario 2.

I would suggest leaving context source and LDAP template inside XML.

like image 189
Pavel Horal Avatar answered Sep 20 '22 01:09

Pavel Horal


Pavel answer solved my issue, but I was confused as the both LdapContextSource and LdapTemplate are InitializingBean.

Listed below is the simplest templet creation using spring-ldap 2.2.0.

import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
    ...

    public LdapTemplate getLdapTemplate(){
        LdapContextSource contextSource = new LdapContextSource();
        contextSource.setUrl("ldap://url.company.com:389");
        contextSource.setBase("DC=company,DC=com");
        contextSource.setUserDn("CN=Admin,CN=Users,DC=company,DC=com");
        contextSource.setPassword("PASSWORD");
        contextSource.afterPropertiesSet();
        LdapTemplate ldapTemplate = new LdapTemplate(contextSource);
        try {
            ldapTemplate.afterPropertiesSet();
        } catch (Exception e) {
            System.out.print("Failed to initialize ldaptemplet "); e.printStackTrace();
            return null
        }
        return ldapTemplate;
    }

Template isn't pooled and use the simple authentication strategy

Hope this will help someone.

like image 38
Haim Raman Avatar answered Sep 21 '22 01:09

Haim Raman