### Request Control DirContextProcessor Implementation Example Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/processing-the-dircontext.adoc Example implementation of a custom request control DirContextProcessor, demonstrating how to create a request control and process response controls. ```java package com.example.control; public class MyCoolRequestControl extends AbstractRequestControlDirContextProcessor { private static final boolean CRITICAL_CONTROL = true; private MyCoolCookie cookie; ... public MyCoolCookie getCookie() { return cookie; } public Control createRequestControl() { return new SomeCoolControl(cookie.getCookie(), CRITICAL_CONTROL); } public void postProcess(DirContext ctx) throws NamingException { LdapContext ldapContext = (LdapContext) ctx; Control[] responseControls = ldapContext.getResponseControls(); for (int i = 0; i < responseControls.length; i++) { if (responseControls[i] instanceof SomeCoolResponseControl) { SomeCoolResponseControl control = (SomeCoolResponseControl) responseControls[i]; this.cookie = new MyCoolCookie(control.getCookie()); } } } } ``` -------------------------------- ### Basic ContextSource Configuration Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/configuration.adoc Configures a ContextSource with a specific URL and an authentication source reference. This is a fundamental setup for connecting to an LDAP server. ```xml ... ... ``` -------------------------------- ### Example DN with Indexed Attributes Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/odm.adoc Demonstrates a DN structure with multiple components, each mapped by index to specific attributes. This DN corresponds to the indexed @DnAttribute annotations. ```bash uid=carla,department=engineering,dc=springframework,dc=org ``` -------------------------------- ### Example DN with String Attribute Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/odm.adoc Illustrates a DN structure where a component corresponds to a String attribute. This shows how a DN like 'uid=carla,dc=springframework,dc=org' can be parsed. ```bash uid=carla,dc=springframework,dc=org ``` -------------------------------- ### Micrometer Trace Output for LDAP Operations Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/observability.adoc Example of truncated Micrometer trace output for a `DirContext#getAttributes` operation, showing START, OPEN, CLOSE, and STOP events with observability details. ```bash 2025-01-06T19:02:00.343-07:00 INFO 2036360 --- [nio-8080-exec-1] [677c8af4f5f02980a1584d0ac0b9fba4-d38e906e55d92746] i.m.o.ObservationTextPublisher : START - name='spring.ldap.dir.context.operations', contextualName='null', error='null', lowCardinalityKeyValues=[base='dc=springframework,dc=org', operation='get.attributes', urls='[ldap://localhost:41283/]'], highCardinalityKeyValues=[attribute.ids='null', name='uid=user,ou=people'], ... duration(nanos)=243104.0 ... parentObservation={name=spring.security.authentications ... parentObservation={name=spring.security.filterchains(security filterchain before) ... parentObservation={name=http.server.requests(null) ... 2025-01-06T19:02:00.345-07:00 INFO 2036360 --- [nio-8080-exec-1] [677c8af4f5f02980a1584d0ac0b9fba4-daa1bbc981aade27] i.m.o.ObservationTextPublisher : OPEN - name='spring.ldap.dir.context.operations', ... 2025-01-06T19:02:00.363-07:00 INFO 2036360 --- [nio-8080-exec-1] [677c8af4f5f02980a1584d0ac0b9fba4-daa1bbc981aade27] i.m.o.ObservationTextPublisher : CLOSE - name='spring.ldap.dir.context.operations', ... 2025-01-06T19:02:00.364-07:00 INFO 2036360 --- [nio-8080-exec-1] [677c8af4f5f02980a1584d0ac0b9fba4-d38e906e55d92746] i.m.o.ObservationTextPublisher : STOP - name='spring.ldap.dir.context.operations', ... ``` -------------------------------- ### Update Data using Rebind Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/spring-ldap-basic-usage.adoc Illustrates how to update an existing LDAP entry by using the rebind operation, which is equivalent to an unbind followed by a bind. This example uses ldapTemplate. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { private LdapClient ldapClient; ... public void update(Person p) { Name dn = buildDn(p); ldapTemplate.bind(dn).attributes(buildAttributes(p)).replaceExisting(true).execute(); } } ``` -------------------------------- ### Publish Spring LDAP Artifacts to Maven Local Source: https://github.com/spring-projects/spring-ldap/blob/main/readme.adoc Build and install all Spring LDAP JARs into your local Maven repository using Gradle. ```bash ./gradlew publishToMavenLocal ``` -------------------------------- ### ODM Person Entity and Repository Example Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/odm.adoc Shows a complete Java entity 'Person' mapped to LDAP using @Entry, @Attribute, and @DnAttribute, along with a repository class 'OdmPersonRepo' demonstrating CRUD operations with LdapTemplate. ```java @Entry(objectClasses = { "person", "top" }, base="ou=someOu") public class Person { @Id private Name dn; @Attribute(name="cn") @DnAttribute(value="cn", index=1) private String fullName; // No @Attribute annotation means this will be bound to the LDAP attribute // with the same value private String description; @DnAttribute(value="ou", index=0) @Transient private String company; @Transient private String someUnmappedField; // ...more attributes below } public class OdmPersonRepo { @Autowired private LdapTemplate ldapTemplate; public Person create(Person person) { ldapTemplate.create(person); return person; } public Person findByUid(String uid) { return ldapTemplate.findOne(query().where("uid").is(uid), Person.class); } public void update(Person person) { ldapTemplate.update(person); } public void delete(Person person) { ldapTemplate.delete(person); } public List findAll() { return ldapTemplate.findAll(Person.class); } public List findByLastName(String lastName) { return ldapTemplate.find(query().where("sn").is(lastName), Person.class); } public Stream streamFindByLastName(String lastName) { return ldapTemplate.findStream(query().where("sn").is(lastName), Person.class); } } ``` -------------------------------- ### Search for 'Person' entries returning only 'cn' attribute Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/query-builder-advanced.adoc This example demonstrates how to request specific attributes from the search results. It searches for 'Person' entries starting at 'dc=261consulting,dc=com' and returns only the 'cn' (common name) attribute. ```java import static org.springframework.ldap.query.LdapQueryBuilder.query; ... Stream persons = ldapClient.search() .query(query().base("dc=261consulting,dc=com") .attributes("cn") .where("objectclass").is("person")), .map(new PersonAttributesMapper()).stream(); ``` -------------------------------- ### Distinguished Name Example Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/spring-ldap-basic-usage.adoc Illustrates the resulting distinguished name after using LdapNameBuilder with specific person attributes. ```text cn=Some Person, ou=Some Company, c=Sweden, dc=example, dc=com ``` -------------------------------- ### Traditional Java LDAP Person Search Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/introduction.adoc Demonstrates the traditional JNDI-based approach for searching LDAP for person names. This example includes significant boilerplate code for context creation, searching, attribute retrieval, and resource management. ```java package com.example.repository; public class TraditionalPersonRepoImpl implements PersonRepo { public List getAllPersonNames() { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, "ldap://localhost:389/dc=example,dc=com"); DirContext ctx; try { ctx = new InitialDirContext(env); } catch (NamingException e) { throw new RuntimeException(e); } List list = new LinkedList(); NamingEnumeration results = null; try { SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); results = ctx.search("", "(objectclass=person)", controls); while (results.hasMore()) { SearchResult searchResult = (SearchResult) results.next(); Attributes attributes = searchResult.getAttributes(); Attribute attr = attributes.get("cn"); String cn = attr.get().toString(); list.add(cn); } } catch (NameNotFoundException e) { // The base context was not found. // Just clean up and exit. } catch (NamingException e) { throw new RuntimeException(e); } finally { if (results != null) { try { results.close(); } catch (Exception e) { // Never mind this. } } if (ctx != null) { try { ctx.close(); } catch (Exception e) { // Never mind this. } } } return list; } } ``` -------------------------------- ### Search for entries with object class 'person' and 'cn=John Doe' Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/query-builder-advanced.adoc This example shows how to combine multiple filter criteria using 'and' to search for entries that match both the object class 'person' and have a common name (cn) of 'John Doe'. ```java import static org.springframework.ldap.query.LdapQueryBuilder.query; ... List persons = ldapClient.search() .query(query().where("objectclass").is("person").and("cn").is("John Doe")) .map(new PersonAttributesMapper()).list(); ``` -------------------------------- ### Update Data using modifyAttributes Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/spring-ldap-basic-usage.adoc Demonstrates a more sophisticated update by using modifyAttributes, which applies explicit attribute modifications to a specific entry. This example uses ldapTemplate and ModificationItem. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { private LdapClient ldapClient; ... public void updateDescription(Person p) { Name dn = buildDn(p); Attribute attr = new BasicAttribute("description", p.getDescription()) ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr); ldapTemplate.modify().name(dn).attributes(item).execute(); } } ``` -------------------------------- ### Get Multi-Value Attribute with DirContextAdapter Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Illustrates retrieving multi-value attributes like 'roleNames' from an LDAP entry using DirContextAdapter's getStringAttributes method. This simplifies handling attributes with multiple values. ```java private static class PersonContextMapper implements ContextMapper { public Object mapFromContext(Object ctx) { DirContextAdapter context = (DirContextAdapter)ctx; Person p = new Person(); p.setFullName(context.getStringAttribute("cn")); p.setLastName(context.getStringAttribute("sn")); p.setDescription(context.getStringAttribute("description")); // The roleNames property of Person is an String array p.setRoleNames(context.getStringAttributes("roleNames")); return p; } } ``` -------------------------------- ### Build Spring LDAP Reference Documentation Source: https://github.com/spring-projects/spring-ldap/blob/main/readme.adoc Build the reference documentation for the current branch of Spring LDAP using Gradle. The output is published to the '_docs/build/site_' directory. ```bash ./gradlew :spring-ldap-docs:antora ``` -------------------------------- ### Compile, Test, and Build Spring LDAP Source: https://github.com/spring-projects/spring-ldap/blob/main/readme.adoc Compile the project, run tests, and build all JARs, distribution zips, and documentation using Gradle. ```bash ./gradlew build ``` -------------------------------- ### Prepare for Next Development Cycle Source: https://github.com/spring-projects/spring-ldap/blob/main/RELEASE.adoc Updates the build.gradle file to the next development snapshot version and commits the change. ```bash sed -i 's/version=(.*)/version=3.0.0-SNAPSHOT' git commit -am "Next Development Version" ``` -------------------------------- ### DnAttribute Annotation Example Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/odm.adoc Example of using the @DnAttribute annotation to map a field to a component of an entry's distinguished name. ```java @DnAttribute(name="uid") ``` -------------------------------- ### Search for entries with object class 'person' starting at a specific base DN Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/query-builder-advanced.adoc This snippet illustrates how to specify a base DN for the search, limiting the search scope to a particular part of the LDAP tree. It searches for entries with object class 'person' starting from 'dc=261consulting,dc=com'. ```java import static org.springframework.ldap.query.LdapQueryBuilder.query; ... List persons = ldapClient.search() .query(query().base("dc=261consulting,dc=com").where("objectclass").is("person")) .map(new PersonAttributesMapper()).list(); ``` -------------------------------- ### Configure LdapPopulator Bean Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/testing.adoc Set up an `LdifPopulator` bean to populate the embedded LDAP server with data from an LDIF file. Ensure it depends on the embedded server bean. ```xml ``` -------------------------------- ### Get LDAP Context Mapper Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Provides the ContextMapper implementation for mapping LDAP entries to Person objects. ```java protected ContextMapper getContextMapper() { return new PersonContextMapper(); } ``` -------------------------------- ### Build Gradle Configuration Source: https://github.com/spring-projects/spring-ldap/blob/main/buildSrc/src/test/resources/samples/showcase/sgbcs-docs/src/docs/asciidoc/index.adoc This snippet displays the build.gradle file content, typically used for project build configuration. ```groovy plugins { id 'org.asciidoctor.jvm.convert' } repositories { mavenCentral() } asciidoctorj { version '3.0.0' } dependencies { asciidoctor 'org.asciidoctor:asciidoctorj-pdf:3.0.0' } configurations { asciidoctorRuntimeOnly } // tag::build-gradle[] asciidoctor { inputs.dir "src/docs/asciidoc" outputs.dir "build/docs" options[:backend] = 'pdf' options[:eruby] = 'classpath:/templates/pdf.yml' options[:attributes] = [ 'endpoint-url': 'http://localhost:8080', 'sourcedir': '../java' ] } // end::build-gradle[] ``` -------------------------------- ### List Available Gradle Tasks Source: https://github.com/spring-projects/spring-ldap/blob/main/readme.adoc Discover all available tasks in the Spring LDAP Gradle build system. ```bash ./gradlew tasks ``` -------------------------------- ### Add Spring Boot LDAP Starter (Gradle) Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/getting-spring-ldap.adoc Add the spring-boot-starter-ldap dependency to your build.gradle file for Spring Boot integration. ```groovy dependencies { implementation "org.springframework.boot:spring-boot-starter-ldap" } ``` -------------------------------- ### Simplest ContextSource Declaration Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/configuration.adoc Configure the LdapContextSource with minimal required attributes: username, password, and server URL. ```xml ``` -------------------------------- ### Create LDAP Entry with DirContextAdapter Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Demonstrates creating a new LDAP entry using DirContextAdapter by setting attributes like objectclass, cn, sn, and description before binding. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { ... public void create(Person p) { Name dn = buildDn(p); DirContextAdapter context = new DirContextAdapter(dn); context.setAttributeValues("objectclass", new String[] {"top", "person"}); context.setAttributeValue("cn", p.getFullname()); context.setAttributeValue("sn", p.getLastname()); context.setAttributeValue("description", p.getDescription()); ldapClient.bind(dn).object(context).execute(); } } ``` -------------------------------- ### Format and Check Code Style Source: https://github.com/spring-projects/spring-ldap/blob/main/CONTRIBUTING.adoc Run this command to format the code and check for style compliance. It's recommended before submitting a pull request. ```bash ./gradlew format check ``` -------------------------------- ### Basic User Authentication with DirContext Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/user-authentication.adoc Authenticates a user by obtaining a DirContext using provided DN and credentials. Ensure the DirContext is always closed. ```java public boolean authenticate(String userDn, String credentials) { DirContext ctx = null; try { ctx = contextSource.getContext(userDn, credentials); return true; } catch (Exception e) { // Context creation failed - authentication did not succeed logger.error("Login failed", e); return false; } finally { // It is imperative that the created DirContext instance is always closed LdapUtils.closeContext(ctx); } } ``` -------------------------------- ### Import ObjectDirectoryMapperConfiguration Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/odm.adoc Import ObjectDirectoryMapperConfiguration to make ObjectDirectoryMapper available as a @Bean when not using Spring Boot. ```java @Import(ObjectDirectoryMapperConfiguration.class) @Configuration public class LdapConfig { // ... } ``` -------------------------------- ### Simplest LdapClient Declaration Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/configuration.adoc Declares the simplest possible LdapClient instance, referencing the default ContextSource. Use this when basic LDAP operations are needed without complex configurations. ```xml ``` -------------------------------- ### Add Data using LdapClient Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/spring-ldap-basic-usage.adoc Demonstrates how to add a new LDAP entry by binding a distinguished name with attributes using LdapClient. This involves manually building the Attributes object. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { private LdapClient ldapClient; ... public void create(Person p) { Name dn = buildDn(p); ldapClient.bind(dn).attributes(buildAttributes(p)).execute(); } private Attributes buildAttributes(Person p) { Attributes attrs = new BasicAttributes(); BasicAttribute ocattr = new BasicAttribute("objectclass"); ocattr.add("top"); ocattr.add("person"); attrs.put(ocattr); attrs.put("cn", "Some Person"); attrs.put("sn", "Person"); return attrs; } } ``` -------------------------------- ### Build Spring LDAP Source: https://github.com/spring-projects/spring-ldap/blob/main/RELEASE.adoc Executes the build and check task for the Spring LDAP project. ```bash gw check ``` -------------------------------- ### Run Additional Style Checks Source: https://github.com/spring-projects/spring-ldap/blob/main/CONTRIBUTING.adoc Execute these commands to perform additional style checks on main and test sources before submitting a pull request. ```bash ./gradlew checkstyleMain checkstyleTest ``` -------------------------------- ### Refactored Create and Update with DirContextAdapter Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Illustrates refactoring common mapping logic into a separate method for both creating and updating LDAP entries, promoting code reuse. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { private LdapClient ldapClient; ... public void create(Person p) { Name dn = buildDn(p); DirContextAdapter context = new DirContextAdapter(dn); context.setAttributeValues("objectclass", new String[] {"top", "person"}); mapToContext(p, context); ldapClient.bind(dn).object(context).execute(); } public void update(Person p) { Name dn = buildDn(p); DirContextOperations context = ldapClient.search().name(dn).single(); mapToContext(person, context); ldapClient.modify(dn).attributes(context.getModificationItems()).execute(); } protected void mapToContext (Person p, DirContextOperations context) { context.setAttributeValue("cn", p.getFullName()); context.setAttributeValue("sn", p.getLastName()); context.setAttributeValue("description", p.getDescription()); } } ``` -------------------------------- ### Custom ContextSource Configuration for Observability Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/observability.adoc If not using Spring Boot or publishing your own `ContextSource`, manually create and wrap it with `ObservationContextSource` to enable observability. ```java @Bean ContextSource contextSource(ObservationRegistry registry) { ContextSource observed = createContextSource(); return new ObservationContextSource(observed, registry); } ``` -------------------------------- ### Configure LdapTemplate with ObjectDirectoryMapper Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/odm.adoc Supply a configured ObjectDirectoryMapper to your LdapTemplate instance to enable custom converter usage. ```java @Bean LdapTemplate ldapTemplate(ContextSource contextSource, ObjectDirectoryMapper odm) { LdapTemplate ldap = new LdapTemplate(contextSource); ldap.setObjectDirectoryMapper(odm); return ldap; } ``` -------------------------------- ### Search LDAP Entry with ContextMapper Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Demonstrates searching for an LDAP entry and mapping its attributes to a Person object using a custom ContextMapper. Requires the ldapClient instance. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { ... private static class PersonContextMapper implements ContextMapper { public Object mapFromContext(Object ctx) { DirContextAdapter context = (DirContextAdapter)ctx; Person p = new Person(); p.setFullName(context.getStringAttribute("cn")); p.setLastName(context.getStringAttribute("sn")); p.setDescription(context.getStringAttribute("description")); return p; } } public Person findByPrimaryKey( String name, String company, String country) { Name dn = buildDn(name, company, country); return ldapClient.search().name(dn).map(new PersonContextMapper()).single(); } } ``` -------------------------------- ### Convenience Search Methods with DirContextProcessor Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/processing-the-dircontext.adoc Provides overloaded search methods in LdapTemplate that accept a DirContextProcessor for simplified usage. ```java public void search(Name base, String filter, SearchControls controls, NameClassPairHandler handler, DirContextProcessor processor) public void search(String base, String filter, SearchControls controls, NameClassPairHandler handler, DirContextProcessor processor) public void search(Name base, String filter, SearchControls controls, AttributesMapper mapper, DirContextProcessor processor) public void search(String base, String filter, SearchControls controls, AttributesMapper mapper, DirContextProcessor processor) public void search(Name base, String filter, SearchControls controls, ContextMapper mapper, DirContextProcessor processor) public void search(String base, String filter, SearchControls controls, ContextMapper mapper, DirContextProcessor processor) ``` -------------------------------- ### Configure BaseLdapPathBeanPostProcessor Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/configuration.adoc Define a `BaseLdapPathBeanPostProcessor` in the application context to automatically inject the base LDAP path into beans implementing `BaseLdapNameAware`. This simplifies DN construction. ```xml ... ... **** ``` -------------------------------- ### Simplest LdapTemplate Declaration Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/configuration.adoc Declares the simplest possible LdapTemplate instance, referencing the default ContextSource. This is suitable for basic LDAP operations when no specific configurations are required. ```java ``` -------------------------------- ### Basic LDAP Connection Pool Configuration Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/pooling.adoc Configure a basic LDAP connection pool by nesting the element within the element. ```xml ... ... ``` -------------------------------- ### Add Spring Boot LDAP Starter (Maven) Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/getting-spring-ldap.adoc Include the spring-boot-starter-ldap dependency in your Maven pom.xml to integrate Spring LDAP with Spring Boot. ```xml org.springframework.boot spring-boot-starter-ldap ``` -------------------------------- ### Tag and Push Release Source: https://github.com/spring-projects/spring-ldap/blob/main/RELEASE.adoc Tags the release commit with the release version and pushes the tag to the origin. ```bash git tag ${RELEASE} git push origin ${RELEASE} ``` -------------------------------- ### Add Member to LDAP Group Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Demonstrates how to add a person as a member to an LDAP group. Requires an LdapClient and base LDAP path configuration. ```java public void addMemberToGroup(String groupName, Person p) { Name groupDn = buildGroupDn(groupName); Name userDn = buildPersonDn( person.getFullname(), person.getCompany(), person.getCountry()); DirContextOperation ctx = ldapClient.search().name(groupDn).single(); ctx.addAttributeValue("member", userDn); ldapClient.modify(groupDn).attributes(ctx.getModificationItems()).execute(); } ``` -------------------------------- ### Gradle Dependency Management with Spring BOM Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/getting-spring-ldap.adoc Configure Gradle to import the Spring Framework BOM using the dependency management plugin. ```groovy plugins { id "io.spring.dependency-management" version "1.0.6.RELEASE" } dependencyManagement { imports { mavenBom 'org.springframework:spring-framework-bom:{spring-core-version}' } } ``` -------------------------------- ### Clone Spring LDAP Repository Source: https://github.com/spring-projects/spring-ldap/blob/main/readme.adoc Clone the official Spring LDAP project repository from GitHub. ```bash git clone git@github.com:spring-projects/spring-ldap.git ``` -------------------------------- ### Building and Encoding an LDAP Filter Source: https://github.com/spring-projects/spring-ldap/blob/main/core/src/main/java/org/springframework/ldap/filter/package.html Demonstrates how to use AndFilter and OrFilter to construct a nested LDAP filter and then encode it into a string representation. This is useful for creating dynamic LDAP queries. ```java AndFilter andFilter = new AndFilter(); andFilter.and(new EqualsFilter("objectclass", "person")); andFilter.and(new EqualsFilter("cn", "Some CN")); OrFilter orFilter = new OrFilter(); orFilter.or(andFilter); orFilter.or(new EqualsFilter("objectclass", "organizationalUnit")); System.out.println(orFilter.encode()); ``` -------------------------------- ### Custom DirContext Method using ContextExecutor Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/adding-missing-overloaded-api-methods.adoc Implements a custom DirContext method like lookupLink using ContextExecutor and executeReadOnly. Ensure the executor correctly calls the desired DirContext method. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { ... public Object lookupLink(final Name name) { ContextExecutor executor = new ContextExecutor() { public Object executeWithContext(DirContext ctx) { return ctx.lookupLink(name); } }; return ldapTemplate.executeReadOnly(executor); } } ``` -------------------------------- ### AbstractRequestControlDirContextProcessor Signatures Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/processing-the-dircontext.adoc Abstract base class for implementing request control DirContextProcessors, handling control retrieval and providing template methods. ```java public abstract class AbstractRequestControlDirContextProcessor implements DirContextProcessor { public void preProcess(DirContext ctx) throws NamingException { ... } public abstract Control createRequestControl(); } ``` -------------------------------- ### Update LDAP Entry with DirContextAdapter Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Shows how to update an existing LDAP entry by first searching for it, modifying its attributes using DirContextAdapter, and then executing the modification. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { ... public void update(Person p) { Name dn = buildDn(p); DirContextOperations context = ldapClient.search().name(dn).single(); context.setAttributeValue("cn", p.getFullname()); context.setAttributeValue("sn", p.getLastname()); context.setAttributeValue("description", p.getDescription()); ldapClient.modify(dn).attributes(context.getModificationItems()).execute(); } } ``` -------------------------------- ### Minimal Spring Boot Configuration for Observability Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/observability.adoc Configure a Spring Boot application to observe LDAP operations by publishing a `ContextSourceObservationPostProcessor` bean. This automatically wraps the `LdapContextSource` for timing and tracing. ```java @Bean static ContextSourceObservationPostProcessor observationPostProcessor(ObjectProvider provider) { return new ContextSourceObservationPostProcessor(provider); } ``` -------------------------------- ### Create Person in LDAP Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Implementation for creating a new person entry in LDAP. Uses DirContextAdapter to set attributes. ```java public void create(Person person) { DirContextAdapter context = new DirContextAdapter(buildDn(person)); mapToContext(person, context); ldapClient.bind(context.getDn()).object(context).execute(); } ``` -------------------------------- ### Notify on Slack Source: https://github.com/spring-projects/spring-ldap/blob/main/RELEASE.adoc Announces the new release on the #spring-release Slack channel. ```bash spring-ldap-announcing `3.0.0-M4` is out! ``` -------------------------------- ### Add Spring LDAP Core Dependency (Gradle) Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/getting-spring-ldap.adoc Use the dependencyManagement plugin in Gradle to import the spring-ldap-core Maven BOM for standalone usage. ```groovy plugins { id "io.spring.dependency-management" version "1.0.6.RELEASE" } dependencyManagement { imports { mavenBom 'org.springframework.ldap:spring-ldap-core:{project-version}' } } ``` -------------------------------- ### Update build.gradle Version Source: https://github.com/spring-projects/spring-ldap/blob/main/RELEASE.adoc Sets the release version in the build.gradle file using an environment variable. ```bash export RELEASE=3.0.0-M4 sed -i 's/version=(.*)/version=${RELEASE}/' build.gradle ``` -------------------------------- ### Maven Dependency Management with Spring BOM Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/getting-spring-ldap.adoc Configure Maven to import the Spring Framework BOM for consistent dependency versions. ```xml org.springframework spring-framework-bom {spring-core-version} pom import ``` -------------------------------- ### LdapTemplate Search Method with DirContextProcessor Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/processing-the-dircontext.adoc Shows how LdapTemplate's search method utilizes a DirContextProcessor for pre- and post-search operations. ```java public void search(SearchExecutor se, NameClassPairCallbackHandler handler, DirContextProcessor processor) throws DataAccessException; ``` -------------------------------- ### Setting LDAP Objectclass and Attributes Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/dirobjectfactory.adoc Shows how to set object class and attribute values for a new LDAP entry using DirContextOperations. This is typically done when creating or modifying directory objects. ```java context.setAttributeValues("objectclass", new String[] {"top", "person"}); context.setAttributeValue("cn", person.getFullName()); context.setAttributeValue("sn", person.getLastName()); context.setAttributeValue("description", person.getDescription()); ``` -------------------------------- ### Implement BaseLdapNameAware Interface Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/configuration.adoc Implement the `BaseLdapNameAware` interface and its `setBaseLdapPath` method to receive the base LDAP path. This is useful for constructing full DNs relative to the LDAP tree root. ```java package com.example.service; public class PersonService implements PersonService**, BaseLdapNameAware** { ... **private LdapName basePath; public void setBaseLdapPath(LdapName basePath) { this.basePath = basePath; }** ... private LdapName getFullPersonDn(Person person) { return LdapNameBuilder.newInstance(**basePath**) .add(person.getDn()) .build(); } ... } ``` -------------------------------- ### Authenticate User with LdapClient Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/user-authentication.adoc A simplified method for authenticating a user using LdapClient by specifying the search query, user identifier, and password. ```java ldapClient.authenticate().query(query().where("uid").is("john.doe")).password("secret").execute(); ``` -------------------------------- ### Search for Person Names by Last Name Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/spring-ldap-basic-usage.adoc Builds an LDAP query to find persons by their last name and retrieves their common names (cn). This demonstrates basic query construction and execution. ```java public List getPersonNamesByLastName(String lastName) { LdapQuery query = query() .base("dc=261consulting,dc=com") .attributes("cn", "sn") .where("objectclass").is("person") .and("sn").is(lastName); return ldapClient.search().query(query) .map((Attributes attrs) -> (String) attrs.get("cn").get()).single(); } } ``` -------------------------------- ### Custom Search Method with ContextMapper Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/adding-missing-overloaded-api-methods.adoc Implements a custom search using SearchExecutor and ContextMapperCallbackHandler. When using ContextMapperCallbackHandler, ensure setReturningObjFlag(true) is called on SearchControls. ```java package com.example.repo; public class PersonRepoImpl implements PersonRepo { ... public List search(final Name base, final String filter, final String[] params, final SearchControls ctls) { SearchExecutor executor = new SearchExecutor() { public NamingEnumeration executeSearch(DirContext ctx) { return ctx.search(base, filter, params, ctls); } }; CollectingNameClassPairCallbackHandler handler = new ContextMapperCallbackHandler(new PersonContextMapper()); ldapTemplate.search(executor, handler); return handler.getList(); } } ``` -------------------------------- ### Configure LdifPopulator for Embedded LDAP Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/testing.adoc Use LdifPopulator to create and populate an embedded LDAP server from an LDIF file. Requires the embedded LDAP server bean and specifies base DN and clean-up behavior. ```xml ``` -------------------------------- ### Gradle Snapshot Repository Configuration Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/getting-spring-ldap.adoc Configure Gradle to use the Spring Snapshot repository for snapshot versions. ```groovy repositories { maven { url 'https://repo.spring.io/snapshot' } } ``` -------------------------------- ### Configure TestContextSourceFactoryBean Bean Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/testing.adoc Use `TestContextSourceFactoryBean` to configure a `ContextSource` for testing against an embedded LDAP server. Specify partition details, credentials, and LDIF file. ```xml ``` -------------------------------- ### Gradle Milestone Repository Configuration Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/getting-spring-ldap.adoc Configure Gradle to use the Spring Milestone repository for milestone or release candidate versions. ```groovy repositories { maven { url 'https://repo.spring.io/milestone' } } ``` -------------------------------- ### Include ApacheDS Dependencies for Gradle Source: https://github.com/spring-projects/spring-ldap/blob/main/modules/ROOT/pages/testing.adoc Add the necessary ApacheDS dependencies to your Gradle project for testing. These are required for running an embedded ApacheDS server. ```groovy testCompile "org.apache.directory.server:apacheds-core:1.5.5", "org.apache.directory.server:apacheds-core-entry:1.5.5", "org.apache.directory.server:apacheds-protocol-shared:1.5.5", "org.apache.directory.server:apacheds-protocol-ldap:1.5.5", "org.apache.directory.server:apacheds-server-jndi:1.5.5", "org.apache.directory.shared:shared-ldap:0.9.15" ```