Friday, 30 January 2015

AOP introduction

Aspects are generic feature that cuts across classes/methods/modules etc. It smells the execution of matching methods that it is expected to handle and executes as per different strategies that are defined later. The actual classes/methods are not aware of the logic being applied.

The cross cutting solutions may be exception handling, activity logging, transaction management, etc.
These can be defined as aspects which can work based on some configuration defined/or can be applied for any code matching its criteria.

Where are Aspects Used:

  • In legacy applications, which needs adapters across classes, which cannot be touched. Say, the tracing was missing in a legacy application. To get the tracing plugged in, we may need every class/method to be modified to add entering/existing.  Instead - A trace Aspect would do that by trapping all/certain method invocation, and introduce tracing before. Execute method using reflection. then add after tracing.
  •  Generic logic that needs to be handled in a detached class, keeping the intercepted classes unaware of

Crosscutting Across modules/classes/etc/,


How does Aspects work.

The aspects and their pointcuts are preloaded. When a method is invoked, The call goes to a Proxy, which hands off the method to be executed to the aspects, which is applicable to this method based on the pointcuts. Aspect chaining occurs and the actual method is executed at the necessary time based on the aspect ordering.



Advice chaining:  As it happens with spring 2.0


AOP Concepts in Spring:

In Spring AOP, aspects are implemented using regular classes (the schema-based approach) or regular classes annotated with the @Aspect annotation (@AspectJ style).

  • Join point: A point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.
  • Advice: Action taken by an aspect at a particular join point. Different types of advice include "around," "before" and "after" advice.
  • Pointcut: A predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name).
  • Introduction: (Also known as an inter-type declaration). Declaring additional methods or fields on behalf of a type. Spring AOP allows you to introduce new interfaces (and a corresponding implementation) to any proxied object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching.
  • Target object: Object being advised by one or more aspects. Also referred to as the advised object. Since Spring AOP is implemented using runtime proxies, this object will always be a proxied object.
  • AOP proxy: An object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy will be a JDK dynamic proxy or a CGLIB proxy. Proxy creation is transparent to users of the schema-based and @AspectJ styles of aspect declaration introduced in Spring 2.0.
  • Weaving: Linking aspects with other application types or objects to create an advised object. This can be done at compile time (using the AspectJ compiler, for example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks, performs weaving at runtime.
Types of Advices

  • @Before : Execute before a join point
  • @After (finally) : Execute after join point regardless of sucessul or exception case
  • @AfterReturning : Execute after join point on successful method execution
  • @AfterThrowing : Execute after join point on execption
  • @Around : Surrounds a joinpoint. The aspect will have complete control before during and after method invocation
Proxy: 

Spring using Java Dynamic proxies for AOP Proxies. CGLib is used when the objects do not implement an interfaces

How to Allow Spring to load @Aspect annotation

<aop:aspectj-autoproxy/>
 
 

Pointcut Expression

This expression defines the matching patter, to which these advices should be applied.

Simple syntax is defined as follows

 

Simple example of defining aspect in Spring.


Aspect



 
package org.first.aspects;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class FirstAspect
{

    @Before("execution(* org.first.*.*(..))")
    public void before()
    {
        System.out.println("---Logging before --");
    }

    @After("execution(* org.first.*.*(..))")
    public void after()
    {
        System.out.println("---Logging After--");
    }
}
 
 
 

Bean Class



 
package org.first;

public class FirstServiceImpl //implements FirstService
{

    public FirstServiceImpl()
    {
    }

    public String printMessage()
    {
        final String s = "--printMessage()---";
        System.out.println(s);
        return s;

    }

    public String messagePrint()
    {
        final String s = "--messagePrint()---";
        System.out.println(s);
        return s;

    }

}


beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" 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-3.0.xsd
  http://www.springframework.org/schema/aop
  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 
 
    <!--Aspect definitions are defined in the class --> 
    <aop:aspectj-autoproxy /> 
 
    <!-- Without this the aspects are not instantiated -->  
    <bean id="aspect" class="org.first.aspects.FirstAspect" />
</beans>

Dependencies


 
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>${spring-framework.version}</version>
</dependency>
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-aop</artifactId>
 <version>${spring-framework.version}</version>
</dependency>

<!--  @Aspect Annotation -->
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-aspects</artifactId>
 <version>${spring-framework.version}</version>
</dependency> 


Test code

 
import org.first.FirstService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AOPTest
{

    ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

    @Test
    public void testContext()
    {
        final FirstService service = (FirstService) ctx.getBean("firstService");
        service.printMessage();

    }
}


Output



References :   http://docs.spring.io/spring/docs/2.0.x/reference/aop.html
 
 

HIbernate : How to get more details on "Errors in Named Queries"


ERROR Seen when there is a problem in the named query 

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Dao': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DaoImpl': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/spring/sessionfactory-cfg.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Errors in named queries: select_records_with_auth


Just gives you a high level error.

To get more details change the loglevel. (Below example is of log4j)

<logger name='org.hibernate' level='DEBUG' additivity="false">
        <appender-ref ref='DebugLogFile'/>
</logger>

you will get indepth details as shown below

2015-01-30 14:46:29.864 UTC,ERROR,***-web,,org.hibernate.hql.PARSER,null,RMI TCP Connection(3)-127.0.0.1,line 2:10: expecting IDENT, found '*'
2015-01-30 14:46:29.874 UTC,DEBUG,index-web,,org.hibernate.hql.ast.ErrorCounter,null,RMI TCP Connection(3)-127.0.0.1,line 2:10: expecting IDENT, found '*'
antlr.MismatchedTokenException: expecting IDENT, found '*'
        at antlr.Parser.match(Parser.java:211) ~[antlr.jar:na]
        at org.hibernate.hql.antlr.HqlBaseParser.identifier(HqlBaseParser.java:1612) [hibernate-core.jar:3.6.10.Final]
        at org.hibernate.hql.antlr.HqlBaseParser.atom(HqlBaseParser.java:3691) [hibernate-core.jar:3.6.10.Final]