I have my spring project (Not Spring Boot) I turned on aspect with <aop:aspectj-autoproxy /> After I did it I have odd behaviour with my @PersistenceContext and @Transactional annotations.
When I had <aop:aspectj-autoproxy proxy-target-class="true" /> I had error in my generic class only in case I had internal call of methods.
For example: when I called method delete externally ad method find was called internally from delete method. Check example below.
My generic class example:
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class GenericServiceImpl<T extends IEntity<PK>, PK extends Serializable> implements IGenericService<T, PK> {
private final Class<T> type;
public GenericServiceImpl(final Class<T> type) {
this.type = type;
}
private EntityManager em;
@PersistenceContext
public final void setEntityManager(final EntityManager em) {
this.em = em;
}
public final EntityManager getEntityManager() {
return em;
}
public final void delete(final PK pk) { // I call this method externally
T o = find(pk); // internal call which didn't work
if (o != null) {
o.setDeleted(true);
save(o);
}
}
@Transactional(readOnly = true) // when I call this method externally everything works fine
public final T find(final PK pk) {
if (pk == null) {
return null;
}
T o = em.find(type, pk); // In case I call find method from delete method em is null
if (o != null && o.isDeleted()) {
return null;
} else {
return o;
}
}
}
When I had aop:aspectj-autoproxy/ I had 2 problems:
- It was no possible to get parameters name in aspect
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
methodSignature.getParameterNames(); // here I had null
But in my case I worked around it by using autogenerated name of parameters (for my case it was enough).
- When I turned on proxy-target-class="true" `<aop:aspectj-autoproxy proxy-target-class="true"/> I had error in my generic class only in case I had internal call of methods. For example: when I called method delete externally and method find was called internally from delete method. In this case my EntityManager was null. Check example above.
When I removed proxy-target-class="true" <aop:aspectj-autoproxy />
I fixed crash with em is null but I received odd methods behavior.
For example: After I called delete method my entity was deleted from database. But when I called the find the method I received previous state of entity.
It looks like my entity was cached in the persistence context.
How can I fix it?
JAVA version: 8 My POM deps (only meaningful):
<spring.version>4.3.30.RELEASE</spring.version>
....
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.19</version>
</dependency>