Home > Hibernate > Hibernate Ldap bridge

Hibernate Ldap bridge

It is not uncommon for enterprises to store their employee information in LDAP. Now this poses an interesting challenge for building ORM applications that need access to employee information. For example, consider writing an application that tracks the projects an employee is currently working on. Such an application would have the following simple domain model:

An ORM mapping tool such as Hibernate can easily map this domain model to a database backend. However, since the employee data comes from LDAP, hibernate out of box cannot create the mapping between Project and Employee domain objects. One way to solve this problem would be to implement a custom EntityPersister. In this post I will show a simple hack for achieving this using JPA EntityListeners.

First let us create Java objects and relationships between them. Here is some minimal code:

public class Employee implements Serializable
{
  private Long id;
  private String firstName;
  private String lastName;
  
  // Other fields, getters, setters and other logic
}

public class Project implements Serializable
{
  private Long Id;
  private String name;
  private String description;
  
  private Employee employee;
  
  // Getters, setters and other logic  
}

The next step is to define tables in the database. Here is the table structure:

PROJECT
———–
PROJECT_ID | NAME | DESCRIPTION | EMPLOYEE_ID |

EMPLOYEE
—————-
EMPLOYEE_ID |
Since all the employee information (including EMPLOYEE_ID) is available in LDAP, this table simply holds the unique id of an employee.

Then, create mappings for the domain objects using JPA. The mapping for Application is straightforward:

@Entity
@Table(name="PROJECT")
public class Project implements Serializable 
{
  @Id
  @Column(name="PROJECT_ID")
  // Sequence generator declarations
  private Long Id;
  
  @Column(name="NAME")
  private String name;
  
  @Column(name="DESCRIPTION")
  private String description;
  
  @ManyToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
  @JoinColumn(name="EMPLOYEE_ID")
  private Employee employee;

  // Getters, setters and other logic  
}

@Entity
@Table(name="EMPLOYEE")
public class Employee implements Serializable
{
  @Id
  @GeneratedValue(generator="assigned")
  @GenericGenerator(name="assigned", strategy="assigned")
  @Column(name="EMPLOYEE_ID")
  private Long id;
  
  @Transient
  private String firstName;
  
  @Transient
  private String lastName;
  
  // Getters, setters and other logic
}

With these mappings in place, hibernate can easily load the Project
object and the corresponding Employee object. To populate the
transient fields in the Employee object, an EntityListener needs to be
created. Here is a simple implementation for the entity listener:

public class EmployeeEntityListener
{
  @PostLoad
  public void loadEmployee(Employee employee)
  {
    Map<String, String> employeeData = // Read the employee data from LDAP using the employee Id as the key
    employee.setFirstName(employeeData.get("FIRST_NAME"));
    employee.setLastName(employeeData.get("LAST_NAME"));
  }
}

Finally register this entitylistener:

@Entity
@Table(name="EMPLOYEE")
@EntityListeners(EmployeeEntityListener.class)
public class Employee implements Serializable
{
  ——-

Categories: Hibernate Tags: , ,
  1. Erik
    September 12th, 2008 at 09:24 | #1

    DataNucleus (JPA and JDO implementation) supports LDAP out of the box. checkout on http://datanuclues.org

  2. January 19th, 2010 at 06:41 | #2

    I tried this with Hibernate 3.3.2.GA and Hibernate Annotations 3.4.0.GA,
    the EmployeeEntityListener gets never called!

  3. Balaji
    January 28th, 2010 at 08:33 | #3

    Did you make sure that Hibernate is scanning the package that contains EmployeeEntityListener?

  4. Deryl Spielman
    October 4th, 2010 at 12:49 | #4

    Is it suitable to read from an LDAP server all of the time? If you load 100 employees it’s going to look up each employee 100 times.

  5. October 4th, 2010 at 13:14 | #5

    Deryl,
    I agree that if you load 100 employees this technique will do 100 lookups. But, I believe that LDAP servers are designed to be read efficient (Write Once, Read Many principle) and depending upon your LDAP load and performance requirements this might not be a problem. I have not personally tried this, but how about lazy loading the relationship to user? This does not decrease the number of connections but definitely space the requests.

    I wish there was a better way to integrate LDAP and Hibernate.

  1. No trackbacks yet.