Friday, 6 June 2014

Form based authentication through Spring Security.

Form based authentication is another one of the most common requirement for web applications. In this post we will look how we can implement form based security through Spring.
security-config.xml:




 

 


  
            
        
        
   
   
   
   
   
   
   
   
   
    
  
  
   
  
  
  
  
 
 
 
 
 
  
   
  
   
 
 



Wednesday, 4 June 2014

How to implement Reference table Items (Look up items) in Java through AspectJ

In almost every application we require dynamic constants which can be loaded dynamically or on start up. Drop downs are one of the good example. System parameters from your table is another example. Let's take a specific scenario,
Say suppose we have got three security roles:
1) USER_ROLE,
2) USER_ADMIN,
3) USER_API

The requirement is we have to refer them in the form of constants in our code as well as some times we may have to compose drop down let's say on account settings page we have to show that drop down, a drop down for roles. For a drop down we may require key (code) and label for each constant.

Challenge:


We have to implement these reference values in the database so we can change these reference values with out changing code (or without a deployment of code). Also we still would be able to refer them in code but the key and value would be coming from database.

Implementation:


Initially, I wanted to implement it as Enum but I could not. If someone can, I would happy to see implementation.

In this implementation I have introduced annotation (@ReferenceList) to map the reference type to database.

package com.zohaib.research.referenceTypes;
import com.zohaib.research.annotations.ReferenceList;

@ReferenceList("UserRoleNames")
public class UserRoleNames extends CommonReferenceTypeImplementation{
 
 protected UserRoleNames(String constantName) {
  super(constantName);
  
 }

 public static UserRoleNames
  USER_ROLE  = new UserRoleNames("USER_ROLE"),
  ADMIN_ROLE = new UserRoleNames("ADMIN_ROLE"),
  API_ROLE   = new UserRoleNames("API_ROLE");  
 
}

My reference types will have some common operations so we have got CommonReferenceTypeImplementation as follows:

package com.zohaib.research.referenceTypes;

public class CommonReferenceTypeImplementation implements ReferenceType{

  private String code;
 private String label;
 private String name;
 private boolean initialized;
 
 protected CommonReferenceTypeImplementation(String constantName) {
  this.name = constantName;
 }
 
 @Override
 public void init(String code, String label){
  this.code  = code;
  this.label = label;
  this.initialized = true;
 }
 
 
 @Override
 public String getCode() {
  return this.code;
 }

  @Override
 public String getLabel() {
  return this.label;
 }
 
 @Override
 public String name(){
  return this.name;
 }
 
 @Override
 public boolean hasBeenInitialized(){
  return this.initialized;
 }
}

An interface:


package com.zohaib.research.referenceTypes;


public interface ReferenceType {
 
 public abstract String getCode();
 public abstract String getLabel();
 public void init(String code, String label);
 public boolean hasBeenInitialized();
 public String name();
 
}
Annotation:
package com.zohaib.research.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface ReferenceList {

 public String value();
}

Usage:

And I want to use that some thing like as follows:
@Controller
public class UserService {

       @Autowired
 private transient UserRepository userRepository;

 @Autowired
 private transient RefItemRepository refItemRepository;

 @Autowired
 private transient UserRoleRepository userRoleRepository;

 protected transient Log logger = LogFactory.getLog(getClass());

@RequestMapping(value = "/userService/saveUser", method = RequestMethod.POST)
 public @ResponseBody JSendResponse saveUser(@ModelAttribute User user) {
  User savedUser = null;
  try {

   user.setUserName(user.getEmail());
   user.setEnabled(Boolean.TRUE);
   savedUser = userRepository.save(user);

   // String role = UserRoleNames.USER_ROLE.getCode();
   // TODO: Remove following fetch from above line in future.
   /*
    * RefItem userRoleRefItem =
    * refItemRepository.findByName(UserRoleNames.ROLE_USER.toString());
    * String role = userRoleRefItem.getCode();
    */
   String role = UserRoleNames.USER_ROLE.getCode();
   UserRole userRole = new UserRole();
   userRole.setRoleName(role);
   userRole.setUserId(savedUser.getId());
   userRoleRepository.save(userRole);

  } catch (Exception ex) {
   logger.error("An Exception occurred in saving user!", ex);
   return JSendResponse.applicationError(ex.getMessage());
  }
  return JSendResponse.success("userId", savedUser.getId());
 }
}
Magic: The actual magic is a Aspect:
package com.zohaib.research.aspects;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.hibernate.service.spi.InjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Component;

import com.zohaib.research.annotations.ReferenceList;
import com.zohaib.research.referenceTypes.ReferenceType;
import com.zohaib.research.relational.entities.RefItem;
import com.zohaib.research.repositories.jpa.RefItemRepository;
import com.zohaib.research.spring.SpringBeanUtils;

@Aspect
public class ReferenceTypeAspect {

 protected transient Log logger = LogFactory.getLog(getClass());
 
 
 @Before("execution(* com.zohaib.research.referenceTypes.CommonReferenceTypeImplementation.get*(..))")
 public void initializeReferenceType(JoinPoint joinPoint) throws Exception{
  if(logger.isDebugEnabled()){
   logger.debug("calling initializeReferenceType aspect....");
  }
  
  if(joinPoint.getThis() != null && joinPoint.getThis() instanceof ReferenceType){
   
   ReferenceType thisObject     = (ReferenceType) joinPoint.getThis();
   //Never ever call same method which you are already cross cutting. Otherwise infinite loop.
   //if(thisObject.getCode() == null && thisObject.getLabel() == null){
   //Lazy initialize reference item instance.
   if(! thisObject.hasBeenInitialized()){
    Class thisObjectClass = joinPoint.getThis().getClass();
    
    ReferenceList refListAnnotationOnClass = thisObjectClass.getAnnotation(ReferenceList.class);
    String referenceListName = refListAnnotationOnClass.value();
    String referenceItemName = thisObject.name();
    
    RefItemRepository refItemRepository = SpringBeanUtils.getBean(RefItemRepository.class);
    RefItem refItem = refItemRepository.findByNameAndRefListName(referenceItemName, referenceListName);
    thisObject.init(refItem.getCode(), refItem.getLabel());
   
   }
   
  }
  
 }
 
}
We need aop.xml which would be in META-INF folder (src/main/resources/META-INF/aop.xml)

 
  
 

Model: Following is my model in JPA POJO:
package com.zohaib.research.relational.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name="RefList")
public class RefList extends AbstractEntity{

 
 private static final long serialVersionUID = 7396124355136909774L;

 @Column(name = "name",nullable=false)
 private String name;
 
 @Column(name = "description",nullable=false)
 private String description;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }
 
}
package com.zohaib.research.relational.entities;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name="RefItem")
public class RefItem extends AbstractEntity{
 
 @Column(name = "name",nullable=false)
 private String name;
 
 @Column(name = "code",nullable=false)
 private String code;
 
 @Column(name = "label",nullable=false)
 private String label;
 
 @Column(name = "refListId",nullable=false)
 private Long refListId;
 
 @ManyToOne(fetch=FetchType.LAZY)
 @JoinColumn(name = "refListId",insertable=false,updatable=false)
 private RefList refList;
 
 @Column(name = "description")
 private String description;
 
 @Column(name = "archiveDate")
 @Temporal(TemporalType.TIMESTAMP)
 private Date archiveDate;
 
 

 public RefList getRefList() {
  return refList;
 }

 public void setRefList(RefList refList) {
  this.refList = refList;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getCode() {
  return code;
 }

 public void setCode(String code) {
  this.code = code;
 }

 public String getLabel() {
  return label;
 }

 public void setLabel(String label) {
  this.label = label;
 }

 public Long getRefListId() {
  return refListId;
 }

 public void setRefListId(Long refListId) {
  this.refListId = refListId;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public Date getArchiveDate() {
  return archiveDate;
 }

 public void setArchiveDate(Date archiveDate) {
  this.archiveDate = archiveDate;
 }
  
}
package com.zohaib.research.relational.entities;

import java.io.Serializable;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;

import org.apache.commons.lang.builder.ToStringBuilder;

@MappedSuperclass
public class AbstractEntity implements Serializable{

 private static final long serialVersionUID = -992911032580505536L;
 
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private Long id;

 /**
  * Returns the identifier of the entity.
  * 
  * @return the id
  */
 public Long getId() {
  return id;
 }

 /*
  * (non-Javadoc)
  * 
  * @see java.lang.Object#equals(java.lang.Object)
  */
 @Override
 public boolean equals(Object obj) {

  if (this == obj) {
   return true;
  }

  if (this.id == null || obj == null
    || !(this.getClass().equals(obj.getClass()))) {
   return false;
  }

  AbstractEntity that = (AbstractEntity) obj;

  return this.id.equals(that.getId());
 }

 /*
  * (non-Javadoc)
  * 
  * @see java.lang.Object#hashCode()
  */
 @Override
 public int hashCode() {
  return id == null ? 0 : id.hashCode();
 }
 

 @Override
 public String toString()
 {
     return ToStringBuilder.reflectionToString(this);
 }
}
The hardest part: Following is POM.xml with right maven plugin configuration. I am trying to use aspect with out spring dependency.


 4.0.0
 com.zohaib.research
 researchPrj
 war
 1.0-SNAPSHOT
 Maven Webapp
 http://maven.apache.org

 

  
   Maven central
   http://central.maven.org/maven2
  

  
   maven2
   http://repo2.maven.org/maven2
  

  
   maven.springframework
   http://maven.springframework.org/release
  


  
   spring-milestones
   http://repo.spring.io/milestone
   
    true
   
  


 


 
  
  true
  4.0.3.RELEASE
  1.5.2.RELEASE
  3.2.3.RELEASE
  4.3.5.Final
  2.3.2
  5.1.30

 

 


  
   javax.servlet
   jstl
   1.2
  

  
   javax.servlet
   javax.servlet-api
   3.0.1
   provided
  


  
   org.springframework
   spring-webmvc
   ${org.springframework-version}
  


  
   org.springframework.data
   spring-data-jpa
   ${org.springData-version}
  

  
   org.springframework
   spring-tx
   ${org.springframework-version}
  

  
   org.aspectj
   aspectjrt
   1.6.5
  

  
   org.aspectj
   aspectjweaver
   1.8.0.RELEASE
  


  
  
   org.springframework.security
   spring-security-web
   ${spring.security.version}
  

  
   org.springframework.security
   spring-security-config
   ${spring.security.version}
  

  
  
   org.springframework.security
   spring-security-taglibs
   ${spring.security.version}
  


  
   org.hibernate
   hibernate-core
   ${hibernate.version}
  
  
   org.hibernate
   hibernate-entitymanager
   ${hibernate.version}
  


  
   mysql
   mysql-connector-java
   ${mysql.connector.version}
  

  
   opensymphony
   sitemesh
   2.4.2
  

  
   cglib
   cglib-nodep
   2.2
  

  
   commons-collections
   commons-collections
   3.1
  

  
   commons-dbcp
   commons-dbcp
   1.3
  


  
   commons-beanutils
   commons-beanutils
   1.8.3
  

  
   org.apache.httpcomponents
   httpclient
   4.1.1
  

  
   commons-fileupload
   commons-fileupload
   1.2.2
  

  
   commons-io
   commons-io
   1.4
  

  
   commons-lang
   commons-lang
   2.5
  

  
   commons-pool
   commons-pool
   1.5.4
  

  
   org.codehaus.jackson
   jackson-mapper-asl
   1.9.3
  


  
   junit
   junit
   3.8.1
   test
  

 

 
  ROOT
  
   
    org.apache.maven.plugins
    maven-compiler-plugin
    2.3.2
    
     1.6
     1.6
    
   
   
    org.apache.maven.plugins
    maven-war-plugin
    2.1.1
    
     false
    
   

   
    org.codehaus.mojo
    aspectj-maven-plugin
    1.5
    
    
     1.6
     1.6
     1.6
    
    
     
      
       compile
       test-compile
      
     
    
   

   
    org.apache.maven.plugins
    maven-site-plugin
    3.0
    
     
      
      
       org.codehaus.mojo
       cobertura-maven-plugin
       2.5.1
      
     
    
   
  
 



What Else: You may want to write implementations of repository but I am using Spring Data JPA repositories so I have got only interfaces, implementation will be generated by spring data:

package com.zohaib.research.repositories.jpa;

import java.io.Serializable;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public interface JpaBasedRepository extends JpaRepository {
 

}

package com.zohaib.research.repositories.jpa;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.zohaib.research.relational.entities.RefItem;

public interface RefItemRepository extends JpaBasedRepository{

 @Query("SELECT r FROM RefItem r WHERE r.name = :constantName")
 public RefItem findByName(@Param("constantName") String constantName);
 
 @Query("SELECT r FROM RefItem r inner join r.refList l WHERE r.name = :constantName and l.name = :refListName ")
 public RefItem findByNameAndRefListName(
   @Param("constantName") String constantName, 
   @Param("refListName") String refListName
 );
 
}

package com.zohaib.research.repositories.jpa;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.zohaib.research.relational.entities.RefList;

public interface RefListRepository extends JpaBasedRepository{
 
 @Query("SELECT l FROM RefList l WHERE l.name = :refListName")
 public RefList findByName(@Param("refListName") String refListName);
}