Search code examples
springspring-ldapspring-repositories

Multiple LDAP repositories with Spring LDAP Repository


I would like to set more than one LDAP repositories with Spring LDAP. My aim is to create or update objects in all repositories at the same time.

I use LdapRepository Spring interface and I think that isn't possible for now.

I wonder if I can create my own LdapRepository extending the Spring one but I have no idea how to start.

This my configuration :

@Configuration
@EnableLdapRepositories("com.xxx.repository.ldap")
@PropertySource("classpath:ldap.properties")
public class LdapConfiguration {

    @Autowired
    Environment ldapProperties;

    @Bean
    public LdapContextSourceCustom contextSourceTarget() {
        LdapContextSourceCustom ldapContextSource = new LdapContextSourceCustom();
        ldapContextSource.setUrl(ldapProperties.getProperty("ldap.url"));
        ldapContextSource.setBase(ldapProperties.getProperty("ldap.base"));
        ldapContextSource.setUserDn(ldapProperties.getProperty("ldap.userDn"));
        ldapContextSource.setPassword(ldapProperties.getProperty("ldap.password"));
        ldapContextSource.setKeyStoreFile(ldapProperties.getProperty("ldap.truststore"));

        return ldapContextSource;
    }

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

And to be complete, one repository:

public interface LdapUserRepository extends LdapRepository<LdapUser> {

}

Any idea how to do it ?

Thanks in advance for any help.


Solution

  • 1) It is possible specify more than one LDAP Repository configuration. Please see the following example. [Notice: This depends on spring-boot libraries]

    @Configuration
    @EnableLdapRepositories("com.xxx.repository.ldap")
    @EnableConfigurationProperties(LdapProperties.class)
    public class LdapConfiguration {
    
        @Autowired
        private Environment environment;
    
        @Bean(name="contextSource1")
        public LdapContextSource contextSourceTarget(LdapProperties ldapProperties) {
            LdapContextSource source = new LdapContextSource();
            source.setUserDn(this.properties.getUsername());
            source.setPassword(this.properties.getPassword());
            source.setBase(this.properties.getBase());
            source.setUrls(this.properties.determineUrls(this.environment));
            source.setBaseEnvironmentProperties(Collections.<String,Object>unmodifiableMap(this.properties.getBaseEnvironment()));
            return source;
        }
    
        @Bean
        public LdapTemplate ldapTemplate(@Qualifier("contextSource1") LdapContextSource contextSource){
            return new LdapTemplate(contextSource);
        }
    }
    

    You can use the spring.ldap prefix in application.properties to configure the above LdapConfiguration. You can see the available properties by checking out https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ldap/LdapProperties.java.

    @Configuration
    @EnableLdapRepositories(basePackages="com.yyy.repository.ldap", ldapTemplateRef="ldapTemplate2")
    public class LdapConfiguration2 {
    
        @Autowired
        private Environment environment;
    
        @Bean(name="ldapProperties2")
        @ConfigurationProperties(prefix="spring.ldap2")
        public LdapProperties ldapProperties() {
            return new LdapProperties();
        }
    
        @Bean(name="contextSource2")
        public LdapContextSource contextSourceTarget(@Qualifier("ldapProperties2") LdapProperties ldapProperties) {
            LdapContextSource source = new LdapContextSource();
            source.setUserDn(this.properties.getUsername());
            source.setPassword(this.properties.getPassword());
            source.setBase(this.properties.getBase());
            source.setUrls(this.properties.determineUrls(this.environment));
            source.setBaseEnvironmentProperties(Collections.<String,Object>unmodifiableMap(this.properties.getBaseEnvironment()));
            return source;
        }
    
        @Bean(name="ldapTemplate2")
        public LdapTemplate ldapTemplate(@Qualifier("contextSource2") LdapContextSource contextSource){
            return new LdapTemplate(contextSource);
        }
    }
    

    LdapConfiguration2 will be configured by the spring.ldap2 prefix in application.properties.

    2) I don't think extending the Repository is the solution. I would recommend creating a @Service method that iterated through your repositories and applied the updates. I will provide two approaches below.

    Example 1)

    @Service
    public class UpdateRepositories {
        public void updateAllRepositories(LdapUserRepository userRepository1, LdapUserRepository userRepository2) {
            // apply updates to userRepository1 and userRepository2
        }
    }
    

    Example 2)

    @Service
    public class UpdateRepositories {
        public void updateAllRepositories(ApplicationContext appContext) {
            Map<String, LdapRepository> ldapRepositories = appContext.getBeansofType(LdapRepository.class)
            // iterate through map and apply updates
        }
    }
    

    I haven't compiled this code, so let me know if something is off or if you need additional guidance.