Ehab Al-Hakawati
Ehab Al-Hakawati

Reputation: 992

Spring AOP and Spring JPA, Aspect to be executed

I have been writing an aspect that manipulates some of my JPA entities getters. It is supposed to re-format the returned text based on the clients locale. Because not all of my getters should be reformatted I introduced an annotation @ReFormat.

The problem is my aspect is never intercepted when I advise it to an JPA entity but it works fine on non JPA entities (it works when I create my own entity object via a copy constructor).

My annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface ReFormat {

}

My aspect:

@Aspect
public class ReFormatAspect {
    @AfterReturning(pointcut = "@annotation(com.path.ReFormat)", returning = "response")
    public Object formatter(JoinPoint joinPoint, Object response) {
       return response;
    }
}

Now this aspect is intercepted successfully within my MVC controllers (or at any other place except spring data) but not for my entities.

@Entity
@Table(name = "place", schema = "db")
public class TestEntity {

   @Id
   @Column(name = "id")
   protected long id;

   @Column(name = "about", columnDefinition = "TEXT DEFAULT NULL")
   protected String about;

   @ReFormat
   public String getAbout() {
       return this.about;
   }

}

I expected a point cut once the getAbout method is called, but it does not work.

Given the facts above I suppose that JPA (Hibernate) is overriding any interceptor may be by CGLib or javassist.

Note: I have this inside my context

<context:annotation-config />
<context:spring-configured />
<aop:aspectj-autoproxy proxy-target-class="true" />

So what is the exact issue, and how do I intercept any method inside an entity?

I understand this should be the view layer work, but still I need to know why :D

Upvotes: 3

Views: 4458

Answers (3)

Domi
Domi

Reputation: 1749

It is possible to use AspectJ aspects together with the Spring DI container. The Spring AOP documentation sais:

Domain objects often fall into this category because they are often created programmatically using the new operator, or by an ORM tool as a result of a database query.

I created a GitHub project where I use your @ReFormat annotation on a method of a bean annotated with @Entity. In order to be able to use DI within your AspectJ aspect you need to use the aspectOf() approach. This is even possible with JavaConfig. So you don't have to use XML configuration at all.

Upvotes: 1

dsinczak
dsinczak

Reputation: 217

You can always use AspectJ and wave your aspect in compile time. But this way you will not have an access to spring DI container.

Upvotes: 2

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279970

Your Entities are not managed by Spring, they are managed by the underlying JPA implementation. Because of this, Spring cannot wrap them in proxies and provide the wanted behavior.

There's no Spring way to solve this. Hibernate might have some interceptor tool for that (that wraps entities as they are created) but I don't know it. Maybe extending EmptyInterceptor.

Upvotes: 3

Related Questions