Showing posts with label Java EE 6. Show all posts
Showing posts with label Java EE 6. Show all posts

Friday, January 4, 2013

CRUD operation on weblogic embedded ldap using spring ldapTemplate, jsf and CDI

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.

the applicationContext.xml is the same as described in my previous post on weblogic embedded ldap. injection of Spring ldapTemplate via CDI is also similar to that post.

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/

Thursday, December 20, 2012

Authentication Using Weblogic Embedded Ldap

Here we use the Weblogic embedded Ldap for authentication purpose of our java EE 6 application. JSF is used as view technology. For communicating with ldap, springLdap library has been used.

Pre requisites: you need an installed weblogic server and its Embedded Ldap properly set.

The spring beans for ldapTemplate are described in the applicationContext.xml
  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    
    <bean id="contextSource" class="org.springframework.ldap.core.support.DirContextSource">
        <property name="url" value="ldap://127.0.0.1:7001">
        </property>
        <property name="userDn" value="cn=Admin"> 
        </property>
        <property name="password" value="adminpass0">
        </property>
        <property name="base" value="ou=myrealm,dc=base_domain">
        </property>
    </bean>
 
    <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
        <constructor-arg ref="contextSource" />
    </bean>
    
</beans>

the view page for login is a simple xhtml file with two input fields

<!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>login page</title>
    </head>
<body>
<h:form>
    <h:outputLabel value="Enter your user ID " />
    <h:inputText value="#{loginController.uid}" />

    <h:outputLabel value="Enter your password" />
    <h:inputSecret value="#{loginController.password}" />
    
    <h:commandButton value="Submit"
                     action="#{loginController.checkLogin}" />
</h:form>
   
</body>
</html>

controller for logging contains methods for authentication.



package Controller;

import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.hibernate.validator.constraints.NotEmpty;
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
@RequestScoped
public class LoginController {

    @NotEmpty(message = "the uid cant be empty")
    private String uid;
    @NotEmpty(message = "the password cant be empty")
    private String password;
    @Inject
    private LdapTemplate ldapTemplate;

   // getters setters need be here.  

    public String checkLogin() {
        if (loginFromLdap()) {
            return "success?faces-redirect=true";
        } else {
            return "failed?faces-redirect=true";
        }
    }

    public boolean loginFromLdap() {
        AndFilter filter = new AndFilter();
        filter.and(new EqualsFilter("objectclass", "person")).and(new EqualsFilter("uid", this.getUid()));
        boolean legit = false;

        try {
            legit = this.ldapTemplate.authenticate(DistinguishedName.EMPTY_PATH, filter.toString(), this.getPassword());
        } catch (Exception e) {
            legit = false;
        }

        return legit;

    }
}


the injected ldapTemplate is produced using a producer method described in injecting-spring-bean-using-cdi .

the success page and failure pages just display the outcome of the authentication.


<?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">

    <head>
        <title>Success</title>
    </head>
    <body>
        <div>your credentials were found in ldap</div>
    </body>
</html>


<?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">

    <head>
        <title>Failure</title>
    </head>
    <body>
        <div>your credentials were NOT found in ldap</div>
    </body>
</html>


Resources:
1. http://www.jayway.com/2009/02/02/simple-authentication-using-spring-ldap/
2. http://today.java.net/pub/a/today/2006/04/18/ldaptemplate-java-ldap-made-simple.html
3. http://java.dzone.com/articles/accessing-weblogic-embedded
4. https://blogs.oracle.com/jamesbayer/entry/look_inside_weblogic_server_em
5. http://nayefreza.blogspot.com/2012/12/injecting-spring-bean-using-cdi.html

Monday, December 17, 2012

Creating custom converters for jsf (h:selectOneMenu , h:selectManyCheckbox , h:selectManyListbox).

Suppose we have two models, Book and Author. each book having a list of authors. both books and authors are objects and for creating books we need to select authors for that book from an author list. here we use jsf. we use custom converter to convert author names in the list into author objects so that the selected authors from the view are turned into author list for the book. here is how we do it.

the book and author models are as follows,

@Entity
@Table(name = "BOOKS")

public class Book implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    Long book_id;
    @NotNull(message = "book title cant be empty")
    String title;
    @NotNull(message = "book isbn cant be empty")
    String isbn;
    @Temporal(javax.persistence.TemporalType.DATE)
    Date publishDate;
        Double price;
    
    
    @JoinTable(name = "BOOK_AUTHOR", joinColumns = {
        @JoinColumn(name = "BOOK_ID",
        referencedColumnName = "BOOK_ID")},
    inverseJoinColumns = {
        @JoinColumn(name = "AUTHOR_ID",
        referencedColumnName = "AUTHOR_ID")})
    @ManyToMany
    List<Author> authors;
//getter setters equals and hashcode
@Entity
public class Author implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="AUTHOR_ID")        
    Long author_id;
    String name;

    
    @JoinTable(name = "BOOK_AUTHOR", joinColumns = {
        @JoinColumn(name = "AUTHOR_ID",
        referencedColumnName = "AUTHOR_ID")},
    inverseJoinColumns = {
        @JoinColumn(name = "BOOK_ID",
        referencedColumnName = "BOOK_ID")})
    @ManyToMany(mappedBy = "authors")
    List<Book> books;
//getter setters equals and hashcode

BookController class is used as the book crud controller.

@Named
@ConversationScoped
public class BookController implements Serializable{

    @EJB
    BookDao dao;
    @Valid
    Book selectedBook;
    @Inject
    Conversation conversation;

    public Book getSelectedBook() {
        if (selectedBook == null) {
            selectedBook = new Book();
        }
        return selectedBook;
    }

    public void setSelectedBook(Book selectedBook) {
        this.selectedBook = selectedBook;
    }

    public BookDao getDao() {
        return dao;
    }

    public void setDao(BookDao dao) {
        this.dao = dao;
    }

    public String createBook() {
       try {
            dao.create(selectedBook);
        } catch (Exception e) {

            String message = "creation failed !!" + e.getMessage();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(message));

            return "createBook";
        }

        String message = "creation successful !!";
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(message));
        return "bookList?faces-redirect=true";

    }

//other methods for bookController

}

here bookDao is the dao layer implementation for book crud operation. we wont cover that here.

now we write a custom converter for author class (which by the way is the main goal of this post).

@FacesConverter(value = "authorConverter")
public class AuthorConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (context == null) {
            throw new NullPointerException("context");
        }
        if (component == null) {
            throw new NullPointerException("component");
        }
        FacesContext ctx = FacesContext.getCurrentInstance();
        ValueExpression vex =
                ctx.getApplication().getExpressionFactory().createValueExpression(ctx.getELContext(),
                "#{authorController}", AuthorController.class);
        AuthorController authorController = (AuthorController) vex.getValue(ctx.getELContext());
        Author author;
        try {
            author = authorController.load(Long.valueOf(value)); //todo
        } catch (Exception e) {
            e.printStackTrace();
            throw new ConverterException();
        }

        if (author == null) {
            throw new ConverterException();
        }

        return author;
    }

    @Override
    public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {
        if (arg0 == null) {
            throw new NullPointerException("context");
        }
        if (arg1 == null) {
            throw new NullPointerException("component");
        }
        return String.valueOf(((Author)arg2).getAuthor_id());
    }
}

the jsf view for creatBook.xhtml will be something like this

<!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>create book</title>
    </head>
    <body>
        <h:messages globalOnly="true" />
        <h:form>
            <h:outputLabel value="Enter Title" />
            <h:inputText value="#{bookController.selectedBook.title}" />

            <br/>

            <h:outputLabel value="Enter ISBN" />
            <h:inputText value="#{bookController.selectedBook.isbn}" />

            <br />

            <h:outputLabel value="Enter Price" />
            <h:inputText value="#{bookController.selectedBook.price}">
                       
            </h:inputText>

            <br/>

            <h:outputLabel value="Enter publishing date" />
            <h:inputText value="#{bookController.selectedBook.publishDate}"> 
                         <f:convertDateTime type="date" pattern="dd/mm/yyyy"/>
            </h:inputText>

            <br/>

            <h:outputLabel value="select authors from list" />
            <h:selectManyMenu value="#{bookController.selectedBook.authors}" converter="authorConverter">
                <f:selectItems value="#{authorController.authorListAsSelectItems}"/>
            </h:selectManyMenu>

            <br/>

            <h:commandButton value="Create" action="#{bookController.createBook()}" />
        </h:form>
    </body>
</html>

here we can see use of authorController for retrieving list of authors. part of authorController is like this:

@Named
@RequestScoped
public class AuthorController {

    @EJB
    AuthorDao dao;

// other properties, getter and setter methods and other methods for crud operations
   
   public List<SelectItem> getAuthorListAsSelectItems(){
    
        List<SelectItem> items = new ArrayList<SelectItem>();
        
        List<Author> authorList = getAuthorList();
        
        for(Author author:authorList){
        
            items.add(new SelectItem(author, author.getName()));
        }
        
        return items;
    }

    public List<Author> getAuthorList() {

        return dao.findAll();

    }

}

the browser output will be like the following image


i hope the code will be self explanatory on how it works.

Monday, December 3, 2012

Injecting a spring bean using CDI

A few days back i was facing trouble injecting a spring bean using CDI. after a bit of google-ing i found the following solution. all you got to do is add the spring bean definition in  applicationContext.xml . then create a producer method that produces that bean and supplies it to the CDI for injecting where necessary.

for example i needed the following beans to be injected (its the applicationContext.xml file  )

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
    
    <bean id="contextSource" class="org.springframework.ldap.core.support.DirContextSource">
        <property name="url" value="ldap://127.0.0.1:7001">
        </property>
        <property name="userDn" value="cn=Admin"> 
        </property>
        <property name="password" value="adminpass0">
        </property>
        <property name="base" value="ou=myrealm,dc=base_domain">
        </property>
    </bean>
 
    <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
        <constructor-arg ref="contextSource" />
    </bean>
    
</beans>



then i wrote a service class that had the producer method


@ApplicationScoped
public class ProducerServices {
     
        @Produces
        @ApplicationScoped
        public LdapTemplate getLdapTemplate() {
                return (LdapTemplate) ContextLoader.getCurrentWebApplicationContext().getBean(LdapTemplate.class);
        }
   
}

so when I later injected the spring bean in the following class it worked perfectly

@Named
public class PersonDaoImpl implements PersonDao{
    @Inject
    private LdapTemplate ldapTemplate;
//other stuff
}