Aspect Oriented Programming – Advices

Aspect oriented Programming is a cross cutting concepts to OOP. AOP in Spring is used in replacement to EJB for it’s declarative programming style. in this tutorial we will look into different advices that AspectJ supports in Spring.

First of all an Advice is a functionality that we want to execute before or after some method is getting executed.
There are 4 types of Advices that Spring Supports.

  • BeforeAdvice : this advice is executed before every method call
  • AfterAdvice : this advice is executed after every method call. please note that this will not get executed if a method throws some exception
  • AfterThrowingAdvice : this advice is executed after every method throws some configured exceptions
  • AroundAdvice : this advice is executed before and after every method call

let us dive directly to code part as the above explanation is straight forward.
Step1: Let us look into POM.xml file

<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/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.spark.aop</groupId>
	<artifactId>AOPTutorial</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>AOPTutorial</name>
	<description>AOPTutorial</description>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.8.5</version>
		</dependency>
		<dependency>
			<groupId>aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.5.4</version>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>3.1</version>
		</dependency>
	</dependencies>

	<properties>
		<spring.version>4.1.8.RELEASE</spring.version>
	</properties>
</project>

Step2: let us look into our application-context.xml file, which acts as the spring configuration file.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

	<bean id="customerService" class="com.spark.aop.service.CustomerService">
		<property name="customerId" value="10"></property>
	</bean>

	<bean id="beforeAdvice" class="com.spark.aop.advice.BeforeAdvice" />
	<bean id="afterAdvice" class="com.spark.aop.advice.AfterAdvice" />
	<bean id="throwAdvice" class="com.spark.aop.advice.ThrowAdvice" />

	<bean id="customerServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">

		<property name="target" ref="customerService" />

		<property name="interceptorNames">
			<list>
				<value>beforeAdvice</value>
				<value>afterAdvice</value>
				<value>throwAdvice</value>
			</list>
		</property>
	</bean>
</beans>

now let us start writing the classes that were shown in the above configuration file.
Step3: write a class named BeforeAdvice.java which will implement MethodBeforeAdvice.java interface. this interface has before method which gets executed before every method call

package com.spark.aop.advice;

import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;

/**
 * @author Sony
 *
 */
public class BeforeAdvice implements MethodBeforeAdvice {
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("BeforeAdvice class : Before method !");
	}
}

Step4: Now let us write the service class as shown below, which has got some specific operations to be done.

/**
 * 
 */
package com.spark.aop.service;

/**
 * @author Sony
 *
 */
public class CustomerService {

	private int customerId;

	public int getCustomerId() {
		return customerId;
	}

	public void setCustomerId(int customerId) {
		this.customerId = customerId;
	}

	public void getCustomerById() {
		System.out.println("******* CustomerService*********"+customerId);
	}
	
	public void getException() throws IllegalArgumentException {
		 throw new IllegalArgumentException();
	}
}

Step5: finally let us code our main program through which we can start test our advice functionality.

package com.spark.aop.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.spark.aop.service.CustomerService;

public class App {
	public static void main(String[] args) {
		ApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] { "application-context.xml" });

		CustomerService cust = (CustomerService) appContext.getBean("customerServiceProxy");

		System.out.println("************Main Method*************");
		cust.getCustomerById();
		System.out.println("************Going to throw Exception*************");
		try {
			cust.getException();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		
	}
}

Misc : the code for AfterAdvice.java and ThrowAdvice.java are given below.

/**
 * 
 */
package com.spark.aop.advice;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

/**
 * @author Sony
 *
 */
public class AfterAdvice implements AfterReturningAdvice {

	public void afterReturning(Object object, Method method, Object[] objects, Object object2) throws Throwable {
		
		System.out.println("AfterAdvice class : After method !");
	}

}

/**
 * 
 */
package com.spark.aop.advice;

import org.springframework.aop.ThrowsAdvice;

/**
 * @author Sony
 *
 */
public class ThrowAdvice implements ThrowsAdvice{

	public void afterThrowing(IllegalArgumentException e) throws Throwable {
		System.out.println("ThrowAdvice class : Method Thrown exception !");
	}
}

That’s it guys we have finished coding advices in spring.
practical scenario : this kind of approach is very much useful while writing logging facility in projects.
please test the code on your own, and let me know if anything is needed.

Happy Advices πŸ™‚

Advertisements

Using SpringBoot , SpringData and MongoDB

Hello everybody, its a long gap that i have not written a post in my blog. This post could be my last post in 2015. today we are going to see how to integrate Spring’s one of the best feature Spring Boot with Spring data and MongoDB.

Spring Boot:(courtesy Spring.io) Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”. Most Spring Boot applications need very little Spring configuration.


Features:

  • Create stand-alone Spring applications
  • Embed Tomcat, Jetty
  • Automatically configure Spring whenever possible
  • Absolutely no code generation and no requirement for XML configuration

Now let us create a project that can integrate the above mentioned technology stack.
spring-boot-proj

Step 1: create the mongo-db.properties file in src/main/resources folder

MONGO_DB_HOST=127.0.0.1
MONGO_DB_PORT=27017
DB=school

Step 2: create the application configuration java class which is responsible for creating the MongoTemplate object. below is AppConfig.java

/**
 * 
 */
package com.spark.spring.practice.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;

import com.mongodb.Mongo;
import com.mongodb.MongoClient;

/**
 * @author Sony
 *
 */
@Configuration
@PropertySource(value = "classpath:mongo-config.properties")
public class AppConfig {

	@Value("${MONGO_DB_HOST}")
	private String MONGO_DB_HOST;

	@Value("${MONGO_DB_PORT}")
	private int MONGO_DB_PORT;

	@Value("${DB}")
	private String DB;

	protected String getDatabaseName() {
		return DB;
	}

	@Bean
	public Mongo getMongo() throws Exception {
		return new MongoClient(MONGO_DB_HOST, MONGO_DB_PORT);
	}

	@Bean
	public MongoDbFactory mongoDbFactory() throws Exception {
		return new SimpleMongoDbFactory(getMongo(), getDatabaseName());
	}

	@Bean
	public MongoTemplate mongoTemplate() throws Exception {

		MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());

		return mongoTemplate;

	}
}

Step 3: create the pojo classes which are mapped as documents in mongodb. below are the Student.java and Score.java respectively

/**
 * 
 */
package com.spark.spring.practice.beans;

import java.util.List;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

/**
 * @author Sony
 *
 */
@Document(collection = "students")
public class Student {

	@Id
	private int _id;
	@Field(value="name")
	private String name;
	@Field(value="scores")
	List<Score> scores;

	public int get_id() {
		return _id;
	}

	public void set_id(int _id) {
		this._id = _id;
	}

	public String getName() {
		return name;
	}

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

	public List<Score> getScores() {
		return scores;
	}

	public void setScores(List<Score> scores) {
		this.scores = scores;
	}

}

/**
 * 
 */
package com.spark.spring.practice.beans;

/**
 * @author Sony
 *
 */
public class Score {

	private String type;
	private double score;

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public double getScore() {
		return score;
	}

	public void setScore(double score) {
		this.score = score;
	}

}

Step 4: create the controller class which can handle the request coming from client. in this example the controller is called GlobalController.java. The controller class is autowired with MongoTemplate Object and StudentRepository, so let us create StudentRepository so that it will get injected into the controller, when the class loads to spring container. MongoTemplate is readily configured in the AppConfig.java file.

/**
 * 
 */
package com.spark.spring.practice.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.spark.spring.practice.beans.Student;
import com.spark.spring.practice.repositories.StudentRepository;

/**
 * @author Sony
 *
 */
@RestController
@RequestMapping(value = "/rest/v1/students")
public class GlobalController {
	
	Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private MongoTemplate mongoTemplate;
	
	@Autowired
	private StudentRepository studentRepository;

	@RequestMapping(value = "/findall", method = RequestMethod.GET)
	public List<Student> getAllStudents() {
		List<Student> students = studentRepository.findAll();
		return students;
	}
}

Step 5: create the repository interface which will extend the MongRepository<T,ID> interface from spring library.

/**
 * 
 */
package com.spark.spring.practice.repositories;

import org.springframework.data.mongodb.repository.MongoRepository;

import com.spark.spring.practice.beans.Student;

/**
 * @author Sony
 *
 */
public interface StudentRepository extends MongoRepository<Student, Integer> {

}

Step 6: create the main class which will act as booting mechanism and will start the project with the help of @SpringBootApplication & @EnableMongoRepositories annotations

/**
 * 
 */
package com.spark.spring.practice.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

/**
 * @author Sony
 *
 */
@SpringBootApplication
@ComponentScan(basePackages={"com.spark.spring.practice"})
@EnableMongoRepositories(basePackages={"com.spark.spring.practice"})
public class SpringBootMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		SpringApplication.run(SpringBootMain.class, args);
	}

}

that’s all guys we are done with coding part. Its time for us to run the project. once you ran the project with out errors then below is the kind of output that can be seen on console.
Spring-boot-console

now open the REST-client add-on either in chrome or firefox and test your services.
Happy Spring-booting πŸ™‚