Showing posts with label AOP. Show all posts
Showing posts with label AOP. Show all posts

Tuesday, April 10, 2012

Spring: Spring ROM Support for Hibernate with MySQL Part 2

This is an article that extends the previous article Spring: Spring ROM Support for Hibernate with MySQL. I have extended that article by introducing how you can do declarative transaction management for your services. The sample code for this post can be found here.

Everything looks exactly the same as the previous post except for pom.xml and dao.xml Spring configuration file as follows.

In pom.xml I have added some aspectJ dependencies that enables AOP.
  <!--AspectJ dependency-->
  <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>${org.aspectj.version}</version>
  </dependency>
  <dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>${org.aspectj.version}</version>
  </dependency>

In the dao.xml I have defined the beans for declarative transaction management.
 <!-- transaction management -->
 <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
   <property name="sessionFactory" ref="sessionFactory"/>
 </bean>
 <tx:advice id="txAdvice" transaction-manager="txManager">
   <tx:attributes>
     <tx:method name="get" read-only="true"/>
     <tx:method name="*"/>
   </tx:attributes>
 </tx:advice>
 <aop:config>
   <aop:pointcut id="serviceOperationsPC"
          expression="execution(* org.fazlan.spring.hibernate.service.IService.*(..))"/>
   <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperationsPC"/>
 </aop:config>

Summary:
This article looked at how you can do declarative transaction management with Spring.

Wednesday, April 4, 2012

Spring: Spring AOP with XML Configuration

Overview:
This post will look how you could easily configure Spring AOP. Also, this article tries to focus on XML base configuration rather than AspectJ annotations. Moreover, XML based configuration will not have any restrictions on the under lying JDK version (e.i; for annotation based configuration to work, we require JDK 1.5 or higher). Sample code can be found here.

We'll be looking at the following AOP configurations,
  • Before - Runs before the execution of a method.
  • After - Runs after the execution of a method.
  • AfterReturning - Runs after the method returns a result.
  • AfterThrowing - Runs after the methods throws an exception.
  • Around - Runs whilst the method is executing.
Project Structure: Following diagram show the project structure I have used for this post.



Step 1: Maven Dependencies
 <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fazlan</groupId>
<artifactId>spring-aop</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>spring-aop</name>
<url>http://maven.apache.org</url>
<dependencies>
<!-- JUnit testing framework -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- Spring framework -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjrt</artifactId>
   <version>${org.aspectj.version}</version>
</dependency>
<dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjweaver</artifactId>
   <version>${org.aspectj.version}</version>
</dependency>
</dependencies>
<properties>
<org.aspectj.version>1.6.11</org.aspectj.version>
<org.springframework.version>3.1.1.RELEASE</org.springframework.version>
</properties>
</project>
Step 2: Creating POJO Classes and Service Implementation
Person.java
 public class Person {
private long id;
private String firstName;
private String lastName;
private static long ID_INDEXER = 1;
public Person() {
id = ID_INDEXER++;
}
public Person(String firstName, String lastName) {
this();
this.firstName = firstName;
this.lastName = lastName;
}
public long getId() {
return id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
Service Interface:
 public interface ICRUDService<T> {
Serializable save(T t);
void update(T t);
T get(Serializable id);
List<T> getAll();
}
Service Implementation:
 public class PersonService implements ICRUDService<Person>{
private static final Map<Serializable, Person> PERSON_MAP = new HashMap<Serializable, Person>();
public Serializable save(Person person) {
update(person);
return person.getId();
}
public void update(Person person) {
PERSON_MAP.put(person.getId(), person);
}
public Person get(Serializable id) {
return PERSON_MAP.get(id);
}
public List<Person> getAll() {
return new ArrayList<Person>(PERSON_MAP.values());
}
}

Step 3: Creating the Aspect Class
 public class LoggerAspect {
public void before(JoinPoint joinpoint) {
System.out.println("Log before of method --:> " + joinpoint.getSignature().getName());
if (joinpoint.getArgs().length > 0) {
 System.out.println(joinpoint.getArgs()[0]);
}
System.out.println("---------------------------------");
}
public void after(JoinPoint joinpoint) {
System.out.println("Log after of method --:> " + joinpoint.getSignature().getName());
System.out.println("---------------------------------");
}
public Object around(ProceedingJoinPoint joinpoint) throws Throwable {
long t1 = System.currentTimeMillis();
System.out.println("Log proceed of method --:> " + joinpoint.getSignature().getName());
Object obj = joinpoint.proceed();
System.out.println("Time taken to execute : " + (System.currentTimeMillis() - t1) + " milliseconds.");
System.out.println("---------------------------------");
return obj;
}
public void afterReturning(JoinPoint joinpoint, Object result) {
System.out.println("Log afterReturning of method --:> " + joinpoint.getSignature().getName()
   + " [" + result + "]");
System.out.println("---------------------------------");
}
public void afterThrowing(JoinPoint joinpoint, Throwable error) {
System.out.println("Log afterThrowing of method --:> " + joinpoint.getSignature().getName()
   + " [" + error.getMessage() + "]");
System.out.println("---------------------------------");
}
}

Step 4: Configuring the Spring Beans and Wiring the AOP to the Service Implementation
 <?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:aop="http://www.springframework.org/schema/aop"
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">
<bean id="personService" class="org.fazlan.spring.service.PersonService"/>
<!-- AOP Aspects-->
<bean id="loggerAspect" class="org.fazlan.spring.aop.LoggerAspect"/>
<aop:config>
<aop:pointcut id="personServicePC" expression="execution(* org.fazlan.spring.service.ICRUDService.*(..))"/>
<aop:aspect id="preLoggingAspects" ref="loggerAspect">
  <!-- @Before Aspect-->
  <aop:before method="before" pointcut-ref="personServicePC"/>
  <!-- @After Aspect-->
  <aop:after method="after" pointcut-ref="personServicePC"/>
  <!-- @After Aspect-->
  <aop:around method="around" pointcut-ref="personServicePC"/>
  <!-- @AfterReturning Aspect-->
  <aop:after-returning method="afterReturning" returning="result" pointcut-ref="personServicePC"/>
  <!-- @AfterThrowing Aspect-->
  <aop:after-throwing method="afterThrowing" throwing="error" pointcut-ref="personServicePC"/>
</aop:aspect>
</aop:config>
</beans>

Step 5: Trying out the AOP with a Simple Application Client
 public class Main {
public static void main(String... args) {
 ApplicationContext context =
 new ClassPathXmlApplicationContext("org/fazlan/spring/aop/spring-conf-application.xml");
 ICRUDService<Person> service = (ICRUDService<Person>) context.getBean("personService");
 Serializable id = service.save(new Person("First Name", "Second Name"));
 Person p1 = service.get(id);
 p1.setFirstName("Updated First Name");
 service.update(p1);
 service.save(new Person("Fazlan", "Sabar"));
 for(Person p: service.getAll()) {
   System.out.println(p);
 }
}
}
Sample output Generated:
 Apr 4, 2012 1:03:19 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [org/fazlan/spring/aop/spring-conf-application.xml]
Apr 4, 2012 1:03:19 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@56c163f: defining beans [personService,loggerAspect,org.springframework.aop.config.internalAutoProxyCreator,personServicePC,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1,org.springframework.aop.aspectj.AspectJPointcutAdvisor#2,org.springframework.aop.aspectj.AspectJPointcutAdvisor#3,org.springframework.aop.aspectj.AspectJPointcutAdvisor#4]; root of factory hierarchy
Log before of method --:> save
Person{id=1, firstName='First Name', lastName='Second Name'}
---------------------------------
Log proceed of method --:> save
Log after of method --:> save
---------------------------------
Time taken to execute : 1 milliseconds.
---------------------------------
Log afterReturning of method --:> save [1]
---------------------------------
Log before of method --:> get
1
---------------------------------
Log proceed of method --:> get
Log after of method --:> get
---------------------------------
Time taken to execute : 0 milliseconds.
---------------------------------
Log afterReturning of method --:> get [Person{id=1, firstName='First Name', lastName='Second Name'}]
---------------------------------
Log before of method --:> update
Person{id=1, firstName='Updated First Name', lastName='Second Name'}
---------------------------------
Log proceed of method --:> update
Log after of method --:> update
---------------------------------
Time taken to execute : 0 milliseconds.
---------------------------------
Log afterReturning of method --:> update [null]
---------------------------------
Log before of method --:> save
Person{id=2, firstName='Fazlan', lastName='Sabar'}
---------------------------------
Log proceed of method --:> save
Log after of method --:> save
---------------------------------
Time taken to execute : 0 milliseconds.
---------------------------------
Log afterReturning of method --:> save [2]
---------------------------------
Log before of method --:> getAll
---------------------------------
Log proceed of method --:> getAll
Log after of method --:> getAll
---------------------------------
Time taken to execute : 0 milliseconds.
---------------------------------
Log afterReturning of method --:> getAll [[Person{id=1, firstName='Updated First Name', lastName='Second Name'}, Person{id=2, firstName='Fazlan', lastName='Sabar'}]]
---------------------------------
Person{id=1, firstName='Updated First Name', lastName='Second Name'}
Person{id=2, firstName='Fazlan', lastName='Sabar'}  

Summary:
We looked at how Spring framework allows us to easily configure AOP via XML with little configuration.