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.

Sunday, December 16, 2012

Work Flow in Spring SimpleFormController


Here is the sequence of method execution in org.springframework.web.servlet.mvc.SimpleFormController

GET received :

1.  protected Object formBackingObject(HttpServletRequest request) throws Exception
can be overridden to retrieve object from DB or setting default values to object.
2.  protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception
allows to register custom editor
3. if bindNewForm == true then  ServletRequestDataBinder is used for binding
4. protected abstract ModelAndView showForm(HttpServletRequest request, HttpServletResponse response, BindException errors) throws Exception
prepares form model and view including reference and errors. for reference data it calls
protected Map referenceData(HttpServletRequest request, Object command, Errors errors) throws Exception which creates reference data map for request.
view is rendered.

POST received :

1. if sessionForm == false calls formBackingObject(…) mehotd
else gets object from session
2. ServletRequestDataBinder is used for binding
3. protected void onBind(HttpServletRequest request, Object command, BindException errors) throws Exception
used for custom processing after binding and before validation.
4. if validateOnBinding == true then registered validator is invoked. validator registers errors (if any).
5. protected void onBindAndValidate(HttpServletRequest request, Object command, BindException errors) throws Exception
used for custom processing after binding and validation.
6. protected ModelAndView processFormSubmission(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors) throws Exception
if error occurred then shows the form again using showForm(…) method
else calls
protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response,
Object command, BindException errors) throws Exception
this method can be simply used to lead the user to a success page. this can also be overriden to provide custom submission handling like storing the object to the database. Implementations can also perform custom validation and call showForm(…) to return to the form.
References:

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
}