here i created a java ee 6 based web application to perform CRUD operation on weblogic embedded ldap. JSF 2.0 and Spring ldapTemplate has been used.
lets look at the codes as they speak a lot more than normal explanation,
the model person is a simple pojo
package model;
import java.io.Serializable;
import javax.inject.Named;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
/**
* @author nayef
*/
@Named
public class Person implements Serializable {
@NotEmpty(message = "the uid cant be empty")
private String uid;
@NotEmpty(message = "full name cant be empty")
@Size(max =20, min =5, message="you must provide a full name between 5 to 20 characters")
private String fullName;
@NotEmpty(message = "short name cant be empty")
@Size(max =10, min =3, message="you must provide a short name between 3 to 10 characters")
private String shortName;
@NotEmpty(message = "the password cant be empty")
private String password;
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
@Override
public String toString() {
return "Person{" + "uid=" + uid + ", fullName=" + fullName + ", shortName=" + shortName + '}';
}
}
the index page contains links of all the other pages,
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>starting page</title>
</h:head>
<h:body>
to create go to <h:link value="create page" outcome="create" />
<br/>
to search go to <h:link value="search page" outcome="search" />
<br/>
for list go to <h:link value="list page" outcome="list" />
</h:body>
</html>
the create.xhtml contains a simple form to create
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<title>create person</title>
</head>
<body>
<h:form>
<h:outputLabel value="Enter UID " />
<h:inputText value="#{personController.person.uid}" />
<br/>
<h:outputLabel value="Enter Full Name" />
<h:inputText value="#{personController.person.fullName}" />
<br />
<h:outputLabel value="Enter short Name" />
<h:inputText value="#{personController.person.shortName}" />
<br/>
<h:outputLabel value="Enter password" />
<h:inputSecret value="#{personController.person.password}" />
<br/>
<h:commandButton value="Create" action="#{personController.createPerson}" />
<h:commandButton value="Cancel" action="#{personController.cancel}" immediate="true"/>
</h:form>
<br/>
start page <h:link value="start page" outcome="index" />
<br/>
</body>
</html>
the modify.xhtml is like the following. it contains both options for update and delete.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<title>modify person</title>
</head>
<body>
<h:form id="modifyForm">
<h:outputLabel value="Enter UID " />
<h:outputText value="#{personController.person.uid}" />
<br/>
<h:outputLabel value="Enter Full Name" />
<h:inputText value="#{personController.person.fullName}" />
<br />
<h:outputLabel value="Enter short Name" />
<h:inputText value="#{personController.person.shortName}" />
<br />
<br/>
<h:outputLabel value="previous password" />
<h:inputSecret id="previousPassword" validator="#{personController.passwordValidator}" required="true">
</h:inputSecret>
<br/>
<h:outputLabel value="Enter password" />
<h:inputSecret value="#{personController.person.password}" />
<br/>
<h:commandButton value="Modify" action="#{personController.updatePerson}" />
<br/>
<h:commandButton value="Delete" action="#{personController.deletePerson}" immediate="true"/>
<br/>
<h:commandButton value="Cancel" action="#{personController.cancel}" immediate="true"/>
</h:form>
</body>
</html>
the list.xhtml lists all the entries and gives option to load entries for modification
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>person list</title>
</head>
<body>
<h:form>
<h:dataTable value="#{personController.personList}" var="personElement">
<h:column>
#{personElement.uid}
</h:column>
<br/>
<h:column>
#{personElement.fullName}
</h:column>
<br/>
<h:column>
#{personElement.shortName}
</h:column>
<br/>
<h:column>
<h:commandLink action="#{personController.loadPersonFromList(personElement.uid)}" value="load">
</h:commandLink>
</h:column>
</h:dataTable>
</h:form>
<br/>
to create go to <h:link value="create page" outcome="create" />
<br/>
start page <h:link value="start page" outcome="index" />
</body>
</html>
the search.xhtml lets you search entries using uid.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Search</title>
</head>
<body>
<h:form>
<h:outputLabel value="Enter your uid" />
<h:inputText value="#{personController.searchUid}" />
<h:commandButton value="Submit"
action="#{personController.loadPerson}" />
</h:form>
<br/>
start page <h:link value="start page" outcome="index" />
</body>
</html>
failure notification page,
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<title>failed</title>
</head>
<body>
<h1>failed</h1>
<br/>
start page <h:link value="start page" outcome="index" />
</body>
</html>
the controller for this CRUD operation is as follows,
package Controller;
import Dao.PersonDaoImpl;
import java.io.Serializable;
import java.util.List;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.inject.Inject;
import javax.inject.Named;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import model.Person;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
/**
*
* @author nayef
*/
@Named
@ConversationScoped
public class PersonController implements Serializable {
@Valid
@NotNull
private Person person = new Person();
@NotNull
String searchUid;
@Inject
private PersonDaoImpl dao;
@Inject
private Conversation conversation;
@Inject
private LdapTemplate ldapTemplate;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public String getSearchUid() {
return searchUid;
}
public void setSearchUid(String searchUid) {
this.searchUid = searchUid;
}
public LdapTemplate getLdapTemplate() {
return ldapTemplate;
}
public void setLdapTemplate(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
}
public List<Person> getPersonList() {
List<Person> personList = dao.findAll();
return personList;
}
public String createPerson() {
try {
dao.create(person);
} catch (Exception e) {
return "actionFailed?faces-redirect=true";
}
return "list?faces-redirect=true";
}
public String loadPerson() {
beginConversation();
try {
Person tempPerson = dao.findPersonByUid(searchUid);
this.person = tempPerson;
} catch (Exception e) {
endConversation();
if (e instanceof org.springframework.ldap.NameNotFoundException) {
} else {
System.out.println(e.toString());
}
return "actionFailed?faces-redirect=true";
}
return "modify?faces-redirect=true";
}
public String updatePerson() {
try {
dao.updatePersonByUid(this.getPerson());
} catch (Exception e) {
endConversation();
return "actionFailed?faces-redirect=true";
}
endConversation();
return "list?faces-redirect=true";
}
public String loadPersonFromList(String uid) {
beginConversation();
try {
Person tempPerson = dao.findPersonByUid(uid);
this.person = tempPerson;
} catch (Exception e) {
conversation.end();
endConversation();
return "actionFailed?faces-redirect=true";
}
return "modify?faces-redirect=true";
}
public String deletePerson() {
try {
dao.deletePersonByUid(this.getPerson());
} catch (Exception e) {
endConversation();
return "actionFailed?faces-redirect=true";
}
endConversation();
return "list?faces-redirect=true";
}
public String loadPersonList() {
endConversation();
return "list?faces-redirect=true";
}
public String cancel() {
endConversation();
return "index?faces-redirect=true";
}
public void passwordValidator(FacesContext context, UIComponent toValidate, Object value) {
String uid = this.getPerson().getUid();
String password = (String) value;
if (password == null || password.trim().length() < 1) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
"previous Password cant be empty", "previous Password cant be empty");
throw new ValidatorException(message);
}
if (!loginExistsInLdap(uid, password.trim())) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
"previous password not correct", "previous password not correct");
throw new ValidatorException(message);
}
}
public boolean loginExistsInLdap(String uid, String password) {
AndFilter filter = new AndFilter();
filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("uid", uid));
boolean legit = false;
try {
legit = this.ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), password);
} catch (Exception e) {
legit = false;
}
return legit;
}
private void beginConversation() {
if (conversation.isTransient()) {
conversation.begin();
}
}
private void endConversation() {
if (!conversation.isTransient()) {
conversation.end();
}
}
}
the dao layer is like this
package Dao;
import java.util.List;
import model.Person;
/**
*
* @author nayef
*/
public interface PersonDao {
public void create(Person p);
public void updatePersonByUid(Person p);
public void delete(Person p);
public Person findPersonByUid(String uid);
public List<Person> findAll();
}
dao layer implementation uses spring LdapTemplate for ldap operations
package Dao;
import java.io.Serializable;
import java.util.List;
import javax.inject.Inject;
import javax.naming.Name;
import model.Person;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.EqualsFilter;
/**
*
* @author nayef
*/
public class PersonDaoImpl implements PersonDao, Serializable {
@Inject
private LdapTemplate ldapTemplate;
public void setLdapTemplate(LdapTemplate l) {
ldapTemplate = l;
}
@Override
public void create(Person p) {
DirContextAdapter context = new DirContextAdapter();
mapToContext(p, context);
ldapTemplate.bind(buildDn(p), context, null);
}
@Override
public void delete(Person p) {
ldapTemplate.unbind(buildDn(p));
}
@Override
public List<person> findAll() {
EqualsFilter filter = new EqualsFilter(
"objectclass", "person");
return ldapTemplate.search(
DistinguishedName.EMPTY_PATH,
filter.encode(), getContextMapper());
}
@Override
public void updatePersonByUid(Person person) {
DistinguishedName dn = new DistinguishedName();
dn.add("ou", "people");
dn.add("uid", person.getUid());
DirContextAdapter context = (DirContextAdapter) ldapTemplate.lookup(dn);
mapToContext(person, context);
ldapTemplate.modifyAttributes(dn, context.getModificationItems());
}
@Override
public Person findPersonByUid(String uid) {
DistinguishedName dn = new DistinguishedName();
dn.add("ou", "people");
dn.add("uid", uid);
return (Person) ldapTemplate.lookup(dn, getContextMapper());
}
public void deletePersonByUid(Person person) {
DistinguishedName dn = new DistinguishedName();
dn.add("ou", "people");
dn.add("uid", person.getUid());
ldapTemplate.unbind(dn);
}
protected ContextMapper getContextMapper() {
return new PersonContextMapper();
}
protected Name buildDn(Person p) {
DistinguishedName dn = new DistinguishedName();
dn.add("ou", "people");
dn.add("uid", p.getUid());
return dn;
}
protected void mapToContext(Person p, DirContextAdapter context) {
context.setAttributeValues("objectclass", new String[]{"top",
"person", "inetOrgPerson", "organizationalPerson", "wlsuser"});
context.setAttributeValue("cn", p.getFullName());
context.setAttributeValue("sn", p.getShortName());
context.setAttributeValue("uid", p.getUid());
context.setAttributeValue("userPassword", p.getPassword());
}
private static class PersonContextMapper implements ContextMapper {
@Override
public Object mapFromContext(Object ctx) {
DirContextAdapter context = (DirContextAdapter) ctx;
Person p = new Person();
p.setFullName(context.getStringAttribute("cn"));
p.setShortName(context.getStringAttribute("sn"));
p.setUid(context.getStringAttribute("uid"));
return p;
}
}
}
References
1. https://blogs.oracle.com/jamesbayer/entry/look_inside_weblogic_server_em
2. http://today.java.net/pub/a/today/2006/04/18/ldaptemplate-java-ldap-made-simple.html
3. http://www.jayway.com/2009/02/02/simple-authentication-using-spring-ldap/