【问题标题】:Spring LDAP PoolingContextSource via annotationSpring LDAP PoolingContextSource 通过注释
【发布时间】:2015-05-18 17:28:43
【问题描述】:

我试图将 Spring LDAP PoolingContextSource XML 配置转换为使用注释。我可以通过提到here 来让 LdapContextSource 工作,但我无法让 PoolingContextSource 工作。当我运行代码时,我得到了 NullPointerException。下面列出了 XML、注解和异常 sn-p。

XML配置sn-p,

<ldap:context-source
        id="ldapContextSource"
        username="${ldap.username}"
        password="${ldap.password}"
        url="${ldap.url}"
        base="${ldap.base}">
    <ldap:pooling
            test-on-borrow="true"
            test-while-idle="true"/>
</ldap:context-source>

<ldap:ldap-template id="ldapTemplate" context-source-ref="ldapContextSource"/>

注解配置sn-p,

@Bean
public ContextSource ldapContextSource() {
    LdapContextSource contextSource = new LdapContextSource();
    contextSource.setUrl(ldapUrl);
    contextSource.setBase(ldapBase);
    contextSource.setUserDn(ldapUsername);
    contextSource.setPassword(ldapPassword);

    PoolingContextSource poolingContextSource = new PoolingContextSource();
    poolingContextSource.setDirContextValidator(new DefaultDirContextValidator());
    poolingContextSource.setContextSource(contextSource);
    poolingContextSource.setTestOnBorrow(true);
    poolingContextSource.setTestWhileIdle(true);

    TransactionAwareContextSourceProxy proxy = new TransactionAwareContextSourceProxy(poolingContextSource);

    return proxy;
}

@Bean
public LdapTemplate ldapTemplate() {
    return new LdapTemplate(ldapContextSource());
}

我得到了例外,

Exception in thread "main" org.springframework.dao.DataAccessResourceFailureException: Failed to borrow DirContext from pool.; nested exception is java.lang.NullPointerException
at org.springframework.ldap.pool.factory.PoolingContextSource.getContext(PoolingContextSource.java:446)
at org.springframework.ldap.pool.factory.PoolingContextSource.getReadWriteContext(PoolingContextSource.java:429)
at org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy.getReadWriteContext(TransactionAwareContextSourceProxy.java:88)
at org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy.getReadOnlyContext(TransactionAwareContextSourceProxy.java:61)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:357)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:309)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:642)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:578)
at org.springframework.ldap.core.LdapTemplate.find(LdapTemplate.java:1836)
at org.springframework.ldap.core.LdapTemplate.find(LdapTemplate.java:1857)
at org.springframework.ldap.core.LdapTemplate.findOne(LdapTemplate.java:1865)
at org.example.playground.ldap.spring.PersonDaoImpl.getByAccountId(PersonDaoImpl.java:23)
at org.example.playground.ldap.spring.Main.main(Main.java:19)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

Caused by: java.lang.NullPointerException
at org.springframework.ldap.core.support.AbstractContextSource.getReadWriteContext(AbstractContextSource.java:175)
at org.springframework.ldap.pool.factory.DirContextPoolableObjectFactory.makeObject(DirContextPoolableObjectFactory.java:149)
at org.apache.commons.pool.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:1220)
at org.springframework.ldap.pool.factory.PoolingContextSource.getContext(PoolingContextSource.java:443)
... 17 more

【问题讨论】:

    标签: annotations spring-ldap


    【解决方案1】:

    解决方案 1 - 基于来自 here 的回答

    @Bean
    public ContextSource ldapContextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        contextSource.setUrl(ldapUrl);
        contextSource.setBase(ldapBase);
        contextSource.setUserDn(ldapUsername);
        contextSource.setPassword(ldapPassword);
        contextSource.afterPropertiesSet(); // *** need this ***
    
        PoolingContextSource poolingContextSource = new PoolingContextSource();
        poolingContextSource.setDirContextValidator(new DefaultDirContextValidator());
        poolingContextSource.setContextSource(contextSource);
        poolingContextSource.setTestOnBorrow(true);
        poolingContextSource.setTestWhileIdle(true);
    
        TransactionAwareContextSourceProxy proxy = new TransactionAwareContextSourceProxy(poolingContextSource);
    
        return proxy;
    }
    

    解决方案2 - 将LdapContextSource和PoolingContextSource的创建分开,spring容器会负责bean的生命周期(即afterPropertiesSet())

    @Bean
    public LdapContextSource ldapContextSource() {
        LdapContextSource contextSource = new LdapContextSource();
        contextSource.setUrl(ldapUrl);
        contextSource.setBase(ldapBase);
        contextSource.setUserDn(ldapUsername);
        contextSource.setPassword(ldapPassword);
        return contextSource;
    }
    
    @Bean
    public ContextSource poolingLdapContextSource() {
        PoolingContextSource poolingContextSource = new PoolingContextSource();
        poolingContextSource.setDirContextValidator(new DefaultDirContextValidator());
        poolingContextSource.setContextSource(ldapContextSource());
        poolingContextSource.setTestOnBorrow(true);
        poolingContextSource.setTestWhileIdle(true);
    
        TransactionAwareContextSourceProxy proxy = new TransactionAwareContextSourceProxy(poolingContextSource);
        return proxy;
    }
    

    【讨论】:

      【解决方案2】:

      可以使用以下代码,在 a 中激活 Pooling (https://docs.spring.io/spring-ldap/docs/1.3.2.RELEASE/reference/html/pooling.html)

      • SpringBoot 应用程序
      • 使用 Spring Data 与 Ldap 服务器通信

      上面缺少的重要部分 - 是将PoolingContextSource 传递给LdapTemplate

      new LdapTemplate(poolingLdapContextSource());

      @PropertySource("ldap-${spring.profiles.active}.properties")
      @Configuration
      public class LdapConfiguration {
      
        private static Logger LOG = LoggerFactory.getLogger(LdapConfiguration.class);
      
        @Autowired
        private Environment env;
      
      
        @Bean
        public LdapContextSource contextSource() {
          LdapContextSource contextSource = new LdapContextSource();
          contextSource.setUrl(env.getRequiredProperty("ldap.url"));
          contextSource.setBase(env.getRequiredProperty("ldap.base"));
          contextSource.setUserDn(env.getRequiredProperty("ldap.user"));
          contextSource.setPassword(env.getRequiredProperty("ldap.password"));
          contextSource.setPooled(false); // Robert improved the performance by 100x for PARALLEL requests by enabling that
      
          Map<String, Object> environment = new HashMap<>();
      
          // DEBUGGING
          environment.put("com.sun.jndi.ldap.connect.pool.debug", "fine");    // many debug infos
          contextSource.setBaseEnvironmentProperties(environment);
      
          return contextSource;
        }
      
          /**
           * Configure the LDAP connection pool to
           * validate connections https://docs.spring.io/spring-ldap/docs/1.3.2.RELEASE/reference/html/pooling.html
           *
           * so that the connections do not expire in pool
           *
           * @return
           */
          @Bean
          public ContextSource poolingLdapContextSource() {
              PoolingContextSource poolingContextSource = new PoolingContextSource();
              poolingContextSource.setDirContextValidator(new DefaultDirContextValidator());
              poolingContextSource.setContextSource(contextSource());
              poolingContextSource.setTestOnBorrow(true);
              poolingContextSource.setTestWhileIdle(true);
              poolingContextSource.setTimeBetweenEvictionRunsMillis(60000);
              poolingContextSource.setNumTestsPerEvictionRun(3);
      
              TransactionAwareContextSourceProxy proxy = new TransactionAwareContextSourceProxy(poolingContextSource);
              return proxy;
          }
      
        @Bean
        public LdapTemplate ldapTemplate() {
          LdapTemplate ldapTemplate = new LdapTemplate(poolingLdapContextSource());
          ldapTemplate.setIgnoreNameNotFoundException(true);
          return ldapTemplate;
        }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-14
        • 2015-09-11
        相关资源
        最近更新 更多