CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-unboundid--unboundid-ldapsdk

Comprehensive Java LDAP SDK providing full LDAPv3 protocol support, connection pooling, schema handling, and persistence framework for LDAP directory operations.

Pending
Overview
Eval results
Files

persistence.mddocs/

Persistence Framework

Object-relational mapping system for treating LDAP entries as Java objects using annotations to define the mapping between Java classes and LDAP directory entries.

Capabilities

Core Persistence Classes

LDAPPersister

Main persister class providing CRUD operations for persistent objects.

/**
 * Main persister for object-relational mapping between Java objects and LDAP entries
 */
public class LDAPPersister<T> {
    // Constructors
    public LDAPPersister(Class<T> type, LDAPInterface ldapInterface) throws LDAPPersistException;
    public LDAPPersister(Class<T> type, LDAPInterface ldapInterface, String baseDN) throws LDAPPersistException;
    
    // CRUD operations
    public T get(String dn) throws LDAPPersistException;
    public T getByRDN(String rdn) throws LDAPPersistException;
    public T getByRDN(String parentDN, String rdn) throws LDAPPersistException;
    
    public PersistedObjects<T> search(Filter filter) throws LDAPPersistException;
    public PersistedObjects<T> search(String baseDN, SearchScope scope, Filter filter) throws LDAPPersistException;
    public PersistedObjects<T> search(String baseDN, SearchScope scope, Filter filter, String... attributes) throws LDAPPersistException;
    public PersistedObjects<T> searchForEntries(SearchRequest searchRequest) throws LDAPPersistException;
    
    public void add(T object) throws LDAPPersistException;
    public void add(T object, String parentDN) throws LDAPPersistException;
    
    public void modify(T object) throws LDAPPersistException;
    public void modify(T object, boolean deleteNullValues) throws LDAPPersistException;
    public void modify(T object, boolean deleteNullValues, String... attributesToModify) throws LDAPPersistException;
    
    public void delete(T object) throws LDAPPersistException;
    public void delete(String dn) throws LDAPPersistException;
    
    // Configuration
    public Class<T> getType();
    public LDAPInterface getLDAPInterface();
    public String getDefaultParentDN();
    public void setDefaultParentDN(String parentDN);
    
    // Utility methods
    public Entry encodeEntry(T object, String parentDN) throws LDAPPersistException;
    public T decodeEntry(Entry entry) throws LDAPPersistException;
    public String constructDN(T object, String parentDN) throws LDAPPersistException;
    public Filter createFilter(T object) throws LDAPPersistException;
}

PersistedObjects

Collection wrapper for search results containing persistent objects.

/**
 * Collection of persisted objects returned from search operations
 */
public class PersistedObjects<T> implements Iterable<T>, Serializable {
    // Iterator access
    public Iterator<T> iterator();
    public boolean hasMore();
    
    // Size information
    public int size();
    public boolean isEmpty();
    
    // List conversion
    public List<T> toList();
    public List<T> toList(int maxObjects);
    
    // Exception handling
    public List<LDAPPersistException> getExceptions();
    public boolean hasExceptions();
}

Object Mapping Annotations

@LDAPObject

Class-level annotation defining LDAP object class mapping.

/**
 * Class-level annotation for LDAP persistent objects
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface LDAPObject {
    /**
     * Object classes for this type (required)
     */
    String[] objectClass();
    
    /**
     * Structural object class (optional, defaults to first in objectClass array)
     */
    String structuralClass() default "";
    
    /**
     * Superior object classes (optional)
     */
    String[] superiorClass() default {};
    
    /**
     * Default parent DN for new instances (optional)
     */
    String defaultParentDN() default "";
    
    /**
     * Post-decode method name (optional)
     */
    String postDecodeMethod() default "";
    
    /**
     * Post-encode method name (optional)  
     */
    String postEncodeMethod() default "";
}

@LDAPField

Field-level annotation for attribute mapping.

/**
 * Field-level annotation for LDAP attribute mapping
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LDAPField {
    /**
     * LDAP attribute name (optional, defaults to field name)
     */
    String attribute() default "";
    
    /**
     * Whether this attribute is part of the RDN (optional)
     */
    boolean inRDN() default false;
    
    /**
     * Whether this is a required attribute (optional)
     */
    boolean requiredForDecode() default false;
    
    /**
     * Whether this is a required attribute for encoding (optional)
     */
    boolean requiredForEncode() default false;
    
    /**
     * Default values for encoding (optional)
     */
    String[] defaultEncodeValue() default {};
    
    /**
     * Default values for decoding (optional)
     */
    String[] defaultDecodeValue() default {};
    
    /**
     * Filter usage for this field (optional)
     */
    FilterUsage filterUsage() default FilterUsage.CONDITIONALLY_ALLOWED;
    
    /**
     * Whether to always include in modification (optional)
     */
    boolean alwaysModify() default false;
    
    /**
     * Whether to never include in modification (optional)
     */
    boolean neverModify() default false;
    
    /**
     * Attribute syntax OID (optional)
     */
    String syntaxOID() default "";
    
    /**
     * Matching rule OID (optional)
     */
    String matchingRuleOID() default "";
}

/**
 * Filter usage enumeration for field filtering
 */
public enum FilterUsage {
    ALWAYS_ALLOWED,
    CONDITIONALLY_ALLOWED,
    EXCLUDED;
}

@LDAPDNField

Special annotation for DN field mapping.

/**
 * Field annotation for DN mapping
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LDAPDNField {
    // No parameters - indicates this field contains the entry DN
}

@LDAPEntryField

Annotation for mapping entire entry object.

/**
 * Field annotation for whole entry mapping
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LDAPEntryField {
    // No parameters - indicates this field contains the Entry object
}

@LDAPGetter and @LDAPSetter

Method-level annotations for custom attribute access.

/**
 * Method annotation for getter methods
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LDAPGetter {
    /**
     * LDAP attribute name (required)
     */
    String attribute();
    
    /**
     * Whether this attribute is part of the RDN (optional)
     */
    boolean inRDN() default false;
    
    /**
     * Filter usage for this attribute (optional)
     */
    FilterUsage filterUsage() default FilterUsage.CONDITIONALLY_ALLOWED;
    
    /**
     * Attribute syntax OID (optional)
     */
    String syntaxOID() default "";
    
    /**
     * Matching rule OID (optional)
     */
    String matchingRuleOID() default "";
}

/**
 * Method annotation for setter methods
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LDAPSetter {
    /**
     * LDAP attribute name (required)
     */
    String attribute();
    
    /**
     * Whether this is a required attribute (optional)
     */
    boolean requiredForDecode() default false;
    
    /**
     * Whether this is a required attribute for encoding (optional)
     */
    boolean requiredForEncode() default false;
    
    /**
     * Default values for encoding (optional)
     */
    String[] defaultEncodeValue() default {};
    
    /**
     * Default values for decoding (optional)
     */
    String[] defaultDecodeValue() default {};
    
    /**
     * Whether to always include in modification (optional)
     */
    boolean alwaysModify() default false;
    
    /**
     * Whether to never include in modification (optional)
     */
    boolean neverModify() default false;
}

Exception Handling

LDAPPersistException

Exception class for persistence operations.

/**
 * Exception for LDAP persistence operations
 */
public class LDAPPersistException extends Exception {
    // Constructors
    public LDAPPersistException(String message);
    public LDAPPersistException(String message, Throwable cause);
    public LDAPPersistException(String message, String matchedDN, ResultCode resultCode, String diagnosticMessage, String[] referralURLs, Control[] controls);
    
    // LDAP result information
    public String getMatchedDN();
    public ResultCode getResultCode();
    public String getDiagnosticMessage();
    public String[] getReferralURLs();
    public Control[] getControls();
    
    // Object information
    public Object getPartiallyDecodedObject();
    public void setPartiallyDecodedObject(Object obj);
}

Field Value Converters

Standard Converters

Built-in converters for common Java types.

/**
 * Interface for custom field value converters
 */
public interface ObjectEncoder {
    boolean supportsType(Class<?> type);
    String[] encodeFieldValue(Field field, Object value, String objectDN) throws LDAPPersistException;
    void decodeField(Field field, Object object, String attribute, String[] values) throws LDAPPersistException;
}

/**
 * Default object encoder supporting common Java types
 */
public class DefaultObjectEncoder implements ObjectEncoder {
    // Supports: String, primitives, primitive wrappers, arrays, Collections, Date, UUID, etc.
    public boolean supportsType(Class<?> type);
    public String[] encodeFieldValue(Field field, Object value, String objectDN) throws LDAPPersistException;
    public void decodeField(Field field, Object object, String attribute, String[] values) throws LDAPPersistException;
}

Usage Examples

Basic Object Mapping

import com.unboundid.ldap.sdk.*;
import com.unboundid.ldap.sdk.persist.*;

/**
 * Simple person object with LDAP mapping
 */
@LDAPObject(objectClass = {"inetOrgPerson"}, defaultParentDN = "ou=people,dc=example,dc=com")
public class Person {
    @LDAPDNField
    private String dn;
    
    @LDAPField(attribute = "cn", inRDN = true, requiredForEncode = true)
    private String commonName;
    
    @LDAPField(attribute = "sn", requiredForEncode = true)
    private String surname;
    
    @LDAPField(attribute = "givenName")
    private String givenName;
    
    @LDAPField(attribute = "mail")
    private String email;
    
    @LDAPField(attribute = "telephoneNumber")
    private String[] phoneNumbers;
    
    @LDAPField(attribute = "employeeNumber")
    private Integer employeeNumber;
    
    @LDAPField(attribute = "description")
    private String description;
    
    // Constructors
    public Person() {}
    
    public Person(String commonName, String surname, String email) {
        this.commonName = commonName;
        this.surname = surname;
        this.email = email;
    }
    
    // Getters and setters
    public String getDn() { return dn; }
    public void setDn(String dn) { this.dn = dn; }
    
    public String getCommonName() { return commonName; }
    public void setCommonName(String commonName) { this.commonName = commonName; }
    
    public String getSurname() { return surname; }
    public void setSurname(String surname) { this.surname = surname; }
    
    public String getGivenName() { return givenName; }
    public void setGivenName(String givenName) { this.givenName = givenName; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public String[] getPhoneNumbers() { return phoneNumbers; }
    public void setPhoneNumbers(String[] phoneNumbers) { this.phoneNumbers = phoneNumbers; }
    
    public Integer getEmployeeNumber() { return employeeNumber; }
    public void setEmployeeNumber(Integer employeeNumber) { this.employeeNumber = employeeNumber; }
    
    public String getDescription() { return description; }
    public void setDescription(String description) { this.description = description; }
    
    @Override
    public String toString() {
        return "Person{dn='" + dn + "', cn='" + commonName + "', sn='" + surname + "'}";
    }
}

// Usage
public class PersonManager {
    public static void main(String[] args) throws Exception {
        LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);
        
        try {
            connection.bind("cn=admin,dc=example,dc=com", "password");
            
            // Create persister
            LDAPPersister<Person> persister = new LDAPPersister<>(Person.class, connection);
            
            // Create new person
            Person john = new Person("John Doe", "Doe", "john.doe@example.com");
            john.setGivenName("John");
            john.setEmployeeNumber(12345);
            john.setPhoneNumbers(new String[]{"+1-555-0123", "+1-555-0124"});
            john.setDescription("Software Engineer");
            
            // Add to LDAP
            persister.add(john);
            System.out.println("Added person: " + john.getDn());
            
            // Retrieve from LDAP
            Person retrieved = persister.get(john.getDn());
            System.out.println("Retrieved: " + retrieved);
            System.out.println("Email: " + retrieved.getEmail());
            System.out.println("Employee Number: " + retrieved.getEmployeeNumber());
            
            // Modify person
            retrieved.setDescription("Senior Software Engineer");
            retrieved.setPhoneNumbers(new String[]{"+1-555-0123", "+1-555-9999"});
            persister.modify(retrieved);
            System.out.println("Modified person");
            
            // Search for people
            Filter searchFilter = Filter.createEqualityFilter("department", "Engineering");
            PersistedObjects<Person> results = persister.search(searchFilter);
            
            System.out.println("Search results:");
            for (Person person : results) {
                System.out.println("  " + person);
            }
            
            // Delete person
            persister.delete(retrieved);
            System.out.println("Deleted person");
            
        } finally {
            connection.close();
        }
    }
}

Advanced Object Mapping with Getters/Setters

import com.unboundid.ldap.sdk.*;
import com.unboundid.ldap.sdk.persist.*;
import java.util.*;

/**
 * Advanced user object with custom attribute handling
 */
@LDAPObject(
    objectClass = {"inetOrgPerson", "customUser"},
    structuralClass = "inetOrgPerson",
    defaultParentDN = "ou=users,dc=example,dc=com"
)
public class User {
    @LDAPDNField
    private String dn;
    
    @LDAPField(attribute = "cn", inRDN = true)
    private String fullName;
    
    @LDAPField(attribute = "sn", requiredForEncode = true)
    private String lastName;
    
    @LDAPField(attribute = "givenName")
    private String firstName;
    
    @LDAPField(attribute = "mail")
    private String primaryEmail;
    
    private Set<String> emailAddresses = new HashSet<>();
    private List<String> roles = new ArrayList<>();
    private Date lastLoginTime;
    private boolean isActive = true;
    
    // Standard getters/setters
    public String getDn() { return dn; }
    public void setDn(String dn) { this.dn = dn; }
    
    public String getFullName() { return fullName; }
    public void setFullName(String fullName) { this.fullName = fullName; }
    
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    
    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    
    public String getPrimaryEmail() { return primaryEmail; }
    public void setPrimaryEmail(String primaryEmail) { this.primaryEmail = primaryEmail; }
    
    // Custom getter/setter methods with LDAP annotations
    @LDAPGetter(attribute = "mailAlternateAddress")
    public String[] getEmailAddresses() {
        return emailAddresses.toArray(new String[0]);
    }
    
    @LDAPSetter(attribute = "mailAlternateAddress")
    public void setEmailAddresses(String[] addresses) {
        emailAddresses.clear();
        if (addresses != null) {
            Collections.addAll(emailAddresses, addresses);
        }
    }
    
    public void addEmailAddress(String email) {
        emailAddresses.add(email);
    }
    
    public void removeEmailAddress(String email) {
        emailAddresses.remove(email);
    }
    
    @LDAPGetter(attribute = "customRole")
    public String[] getRoles() {
        return roles.toArray(new String[0]);
    }
    
    @LDAPSetter(attribute = "customRole")
    public void setRoles(String[] userRoles) {
        roles.clear();
        if (userRoles != null) {
            Collections.addAll(roles, userRoles);
        }
    }
    
    public void addRole(String role) {
        if (!roles.contains(role)) {
            roles.add(role);
        }
    }
    
    public void removeRole(String role) {
        roles.remove(role);
    }
    
    @LDAPGetter(attribute = "lastLoginTime", syntaxOID = "1.3.6.1.4.1.1466.115.121.1.24")
    public String getLastLoginTimeString() {
        if (lastLoginTime == null) return null;
        return String.valueOf(lastLoginTime.getTime());
    }
    
    @LDAPSetter(attribute = "lastLoginTime")
    public void setLastLoginTimeString(String timestamp) {
        if (timestamp == null || timestamp.isEmpty()) {
            lastLoginTime = null;
        } else {
            try {
                lastLoginTime = new Date(Long.parseLong(timestamp));
            } catch (NumberFormatException e) {
                lastLoginTime = null;
            }
        }
    }
    
    public Date getLastLoginTime() { return lastLoginTime; }
    public void setLastLoginTime(Date lastLoginTime) { this.lastLoginTime = lastLoginTime; }
    
    @LDAPGetter(attribute = "customActive")
    public String getActiveString() {
        return isActive ? "TRUE" : "FALSE";
    }
    
    @LDAPSetter(attribute = "customActive", defaultDecodeValue = {"TRUE"})
    public void setActiveString(String active) {
        isActive = "TRUE".equalsIgnoreCase(active);
    }
    
    public boolean isActive() { return isActive; }
    public void setActive(boolean active) { isActive = active; }
    
    @Override
    public String toString() {
        return String.format("User{dn='%s', fullName='%s', primaryEmail='%s', roles=%s, active=%s}",
            dn, fullName, primaryEmail, roles, isActive);
    }
}

Complex Search Operations

import com.unboundid.ldap.sdk.*;
import com.unboundid.ldap.sdk.persist.*;

public class UserSearchExamples {
    public static void searchExamples() throws Exception {
        LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);
        
        try {
            connection.bind("cn=admin,dc=example,dc=com", "password");
            LDAPPersister<User> persister = new LDAPPersister<>(User.class, connection);
            
            // Search by email domain
            Filter emailDomainFilter = Filter.createSubstringFilter("mail", null, new String[]{"@example.com"}, null);
            PersistedObjects<User> domainUsers = persister.search(emailDomainFilter);
            
            System.out.println("Users with @example.com email:");
            for (User user : domainUsers) {
                System.out.println("  " + user.getFullName() + " - " + user.getPrimaryEmail());
            }
            
            // Search by role
            Filter roleFilter = Filter.createEqualityFilter("customRole", "admin");
            PersistedObjects<User> adminUsers = persister.search(roleFilter);
            
            System.out.println("\nAdmin users:");
            for (User user : adminUsers) {
                System.out.println("  " + user.getFullName() + " - Roles: " + Arrays.toString(user.getRoles()));
            }
            
            // Complex search - active engineering users
            Filter complexFilter = Filter.createANDFilter(
                Filter.createEqualityFilter("customActive", "TRUE"),
                Filter.createORFilter(
                    Filter.createEqualityFilter("customRole", "engineer"),
                    Filter.createEqualityFilter("customRole", "senior-engineer"),
                    Filter.createEqualityFilter("customRole", "architect")
                )
            );
            
            PersistedObjects<User> engineeringUsers = persister.search(
                "ou=users,dc=example,dc=com",
                SearchScope.SUB,
                complexFilter
            );
            
            System.out.println("\nActive engineering users:");
            for (User user : engineeringUsers) {
                System.out.println("  " + user.getFullName() + " - " + Arrays.toString(user.getRoles()));
            }
            
            // Search with limited attributes
            PersistedObjects<User> limitedResults = persister.search(
                "ou=users,dc=example,dc=com",
                SearchScope.ONE,
                Filter.createPresenceFilter("mail"),
                "cn", "mail", "customRole"  // Only retrieve these attributes
            );
            
            System.out.println("\nLimited attribute search:");
            for (User user : limitedResults) {
                System.out.println("  " + user.getFullName() + " - " + user.getPrimaryEmail());
                // Note: other fields may be null since they weren't retrieved
            }
            
        } finally {
            connection.close();
        }
    }
}

Bulk Operations

import com.unboundid.ldap.sdk.*;
import com.unboundid.ldap.sdk.persist.*;
import java.util.*;

public class BulkOperations {
    public static void bulkOperationsExample() throws Exception {
        LDAPConnection connection = new LDAPConnection("ldap.example.com", 389);
        
        try {
            connection.bind("cn=admin,dc=example,dc=com", "password");
            LDAPPersister<User> persister = new LDAPPersister<>(User.class, connection);
            
            // Create multiple users
            List<User> newUsers = Arrays.asList(
                createUser("Alice Johnson", "Johnson", "Alice", "alice.johnson@example.com", "developer"),
                createUser("Bob Smith", "Smith", "Bob", "bob.smith@example.com", "tester"),
                createUser("Carol Davis", "Davis", "Carol", "carol.davis@example.com", "analyst"),
                createUser("David Wilson", "Wilson", "David", "david.wilson@example.com", "manager")
            );
            
            // Add users in batch
            List<String> addedDNs = new ArrayList<>();
            for (User user : newUsers) {
                try {
                    persister.add(user);
                    addedDNs.add(user.getDn());
                    System.out.println("Added: " + user.getFullName());
                } catch (LDAPPersistException e) {
                    System.err.println("Failed to add " + user.getFullName() + ": " + e.getMessage());
                }
            }
            
            // Bulk modification - add a role to all new users
            for (String dn : addedDNs) {
                try {
                    User user = persister.get(dn);
                    user.addRole("employee");
                    user.setLastLoginTime(new Date());
                    
                    // Modify only specific attributes
                    persister.modify(user, false, "customRole", "lastLoginTime");
                    System.out.println("Updated roles for: " + user.getFullName());
                } catch (LDAPPersistException e) {
                    System.err.println("Failed to update " + dn + ": " + e.getMessage());
                }
            }
            
            // Bulk search and update - deactivate users with no recent login
            Calendar cutoff = Calendar.getInstance();
            cutoff.add(Calendar.MONTH, -6);  // 6 months ago
            
            PersistedObjects<User> allUsers = persister.search(Filter.createPresenceFilter("cn"));
            for (User user : allUsers) {
                if (user.getLastLoginTime() != null && user.getLastLoginTime().before(cutoff.getTime())) {
                    user.setActive(false);
                    persister.modify(user, false, "customActive");
                    System.out.println("Deactivated inactive user: " + user.getFullName());
                }
            }
            
            // Bulk delete - remove test users
            Filter testUserFilter = Filter.createSubstringFilter("cn", "Test", null, null);
            PersistedObjects<User> testUsers = persister.search(testUserFilter);
            
            for (User testUser : testUsers) {
                try {
                    persister.delete(testUser);
                    System.out.println("Deleted test user: " + testUser.getFullName());
                } catch (LDAPPersistException e) {
                    System.err.println("Failed to delete " + testUser.getFullName() + ": " + e.getMessage());
                }
            }
            
        } finally {
            connection.close();
        }
    }
    
    private static User createUser(String fullName, String lastName, String firstName, String email, String role) {
        User user = new User();
        user.setFullName(fullName);
        user.setLastName(lastName);
        user.setFirstName(firstName);
        user.setPrimaryEmail(email);
        user.addRole(role);
        user.setActive(true);
        return user;
    }
}

Custom Field Encoding

import com.unboundid.ldap.sdk.*;
import com.unboundid.ldap.sdk.persist.*;
import java.lang.reflect.Field;
import java.util.*;

/**
 * Custom encoder for handling special field types
 */
public class CustomObjectEncoder implements ObjectEncoder {
    
    public boolean supportsType(Class<?> type) {
        return Map.class.isAssignableFrom(type) || 
               Set.class.isAssignableFrom(type) ||
               Date.class.isAssignableFrom(type);
    }
    
    public String[] encodeFieldValue(Field field, Object value, String objectDN) throws LDAPPersistException {
        if (value == null) {
            return new String[0];
        }
        
        if (value instanceof Map) {
            Map<?, ?> map = (Map<?, ?>) value;
            List<String> values = new ArrayList<>();
            for (Map.Entry<?, ?> entry : map.entrySet()) {
                values.add(entry.getKey() + "=" + entry.getValue());
            }
            return values.toArray(new String[0]);
        }
        
        if (value instanceof Set) {
            Set<?> set = (Set<?>) value;
            List<String> values = new ArrayList<>();
            for (Object item : set) {
                values.add(item.toString());
            }
            return values.toArray(new String[0]);
        }
        
        if (value instanceof Date) {
            Date date = (Date) value;
            return new String[]{String.valueOf(date.getTime())};
        }
        
        throw new LDAPPersistException("Unsupported type: " + value.getClass().getSimpleName());
    }
    
    public void decodeField(Field field, Object object, String attribute, String[] values) throws LDAPPersistException {
        if (values == null || values.length == 0) {
            return;
        }
        
        try {
            field.setAccessible(true);
            Class<?> fieldType = field.getType();
            
            if (Map.class.isAssignableFrom(fieldType)) {
                Map<String, String> map = new HashMap<>();
                for (String value : values) {
                    String[] parts = value.split("=", 2);
                    if (parts.length == 2) {
                        map.put(parts[0], parts[1]);
                    }
                }
                field.set(object, map);
            }
            else if (Set.class.isAssignableFrom(fieldType)) {
                Set<String> set = new HashSet<>(Arrays.asList(values));
                field.set(object, set);
            }
            else if (Date.class.isAssignableFrom(fieldType)) {
                long timestamp = Long.parseLong(values[0]);
                field.set(object, new Date(timestamp));
            }
            
        } catch (Exception e) {
            throw new LDAPPersistException("Failed to decode field " + field.getName() + ": " + e.getMessage(), e);
        }
    }
}

/**
 * Example object using custom encoding
 */
@LDAPObject(objectClass = {"customObject"})
public class CustomEncodedObject {
    @LDAPDNField
    private String dn;
    
    @LDAPField(attribute = "cn", inRDN = true)
    private String name;
    
    @LDAPField(attribute = "customProperties")
    private Map<String, String> properties = new HashMap<>();
    
    @LDAPField(attribute = "customTags")
    private Set<String> tags = new HashSet<>();
    
    @LDAPField(attribute = "customTimestamp")
    private Date timestamp;
    
    // Getters and setters...
    public String getDn() { return dn; }
    public void setDn(String dn) { this.dn = dn; }
    
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    
    public Map<String, String> getProperties() { return properties; }
    public void setProperties(Map<String, String> properties) { this.properties = properties; }
    
    public Set<String> getTags() { return tags; }
    public void setTags(Set<String> tags) { this.tags = tags; }
    
    public Date getTimestamp() { return timestamp; }
    public void setTimestamp(Date timestamp) { this.timestamp = timestamp; }
}

Install with Tessl CLI

npx tessl i tessl/maven-com-unboundid--unboundid-ldapsdk

docs

authentication.md

controls-extensions.md

core-operations.md

data-types.md

index.md

ldif.md

persistence.md

schema.md

search.md

tile.json