im trying to create some pointcuts and before advices for Repositories in order to enable filtering over entitymanager for some Repositories in Spring Data in Spring Boot. i also have web and service layer in project and AspectLogging works for both. But i couldnt do same for repositories. i have been struggling for 2 days and i tried so many things for fix it. i read almost every docs, issues and threads about this( proxy issues CGlib and JDK Proxy etc). i used jhipster for creating project.
i cant deploy Application except @Pointcut with CrudRepository. and even its deployed @Before isnt called for a method call in Repository. i think i have a similar Problem like in following question. proxy confusion
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.xxx.zzz.business.repository.ApplyRepository com.xxx.zzz.web.rest.applyResource.ApplyRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applyRepository': Post-processing of FactoryBean's singleton object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy173]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy173
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 61 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'applyRepository': Post-processing of FactoryBean's singleton object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy173]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy173
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:116)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1523)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:314)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1120)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 63 more
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy173]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy173
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:212)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:447)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:333)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:293)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1719)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:113)
... 70 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy173
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:56)
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:202)
... 77 more
Does anyone know what its could be ?
Classes and Configs look like following.
Repository:
public interface ApplyRepository extends JpaRepository<Apply,Long>,QueryDslPredicateExecutor<Apply> {
public Page<Apply> findAll(Predicate predicate, Pageable p);
}
...
}
Database Config:
@Configuration
@EnableJpaRepositories("com.xxx.zzz.business.repository")
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableTransactionManagement//(proxyTargetClass = false)
public class DatabaseConfiguration {
....
AspectJ Config:
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
// @EnableLoadTimeWeaving(aspectjWeaving = ... )
public class LoggingAspectConfiguration {
...
System Architecture:
@Aspect
public class SystemArchitecture {
/**
* A join point is in the web layer if the method is defined
* in a type in the com.xyz.someapp.web package or any sub-package
* under that.W
*/
@Pointcut("within(com.xxx.zzz.web.rest..*)")
public void inWebLayer() {
}
/**
* A join point is in the service layer if the method is defined
* in a type in the com.xyz.someapp.service package or any sub-package
* under that.
*/
@Pointcut("within(com.xxx.zzz.business.service..*)")
public void inServiceLayer() {
}
/**
* A join point is in the data access layer if the method is defined
* in a type in the com.xyz.someapp.dao package or any sub-package
* under that.
*/
@Pointcut("within(com.xxx.zzz.business.repository..*)")
public void inDataAccessLayer() {
}
/**
* All layers
*/
@Pointcut("inWebLayer() || inServiceLayer() || inDataAccessLayer()")
public void inALL(){
}
@Pointcut("within(org.springframework.data.repository.CrudRepository)")
//@Pointcut("execution(*org.springframework.data.repository.Repository+.* (..))")
//@Pointcut("execution(* com.xxx.zzz.business.repository+.*(..))")
//@Pointcut("execution(* org.springframework.data.jpa.repository.JpaRepository+.*(..))")
//@Pointcut("execution(* com.xxx.zzz.business.repository.ApplyRepository.*(..))")
public void inDATAExec(){}
}
FilterAspect:
@Aspect
@Transactional
public class FilterAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@PersistenceContext
private EntityManager entitymanager;
@Before("com.xxx.zzz.aop.logging.SystemArchitecture.inDATAExec())") // "execution(* com.xxx.zzz.business.repository.InvoiceRepository.*(..))"
public void doAccessCheck() {
if (TransactionSynchronizationManager.isActualTransactionActive() && SecurityUtils.isAuthenticated()) {
Session session = entitymanager.unwrap(Session.class);
session.enableFilter("GLOBAL_FILTER").setParameter("customerId", SecurityUtils.getCurrentCustomerId());
}
}
EDIT: i solved problem. it was related somehow to wrong pointscuts and names. i tried to change pointcuts for custom annotation in Repository. it doesnt work for method or class level. i read in following links issues about this. advice 1 advice 2 im struggling for hours for target and annotation. but no result. is it really imposible to add custom annotations in Spring Data Repositories for advicing ?
Annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
//@Inherited
public @interface CustomerRequired {
String value() default "customerrequired";
}
Repository:
public interface InvoiceRepository extends JpaRepository<Invoice,String>, QueryDslPredicateExecutor<Invoice> {
@CustomerRequired
public Page<Invoice> findAll(Predicate predicate, Pageable p);
...
}
Pointcut and Advice:
@Pointcut(value = "@target(customerRequired)",argNames = "customerRequired")
public void targetCustomer(@SuppressWarnings("unused") CustomerRequired customerRequired) {/**/}
@Before(value = "com.xxx.zzz.aop.logging.SystemArchitecture.targetCustomer(customerRequired) && com.xxx.zzz.aop.logging.SystemArchitecture.inDataLayer()")
public void doAccessCheck(JoinPoint joinPoint, CustomerRequired customerRequired) {
if (TransactionSynchronizationManager.isActualTransactionActive() && SecurityUtils.isAuthenticated()) {
Session session = entitymanager.unwrap(Session.class);
session.enableFilter("GLOBAL_FILTER").setParameter("customerId", SecurityUtils.getCurrentCustomerId());
}
}
To enable @AspectJ, spring AOP provides @EnableAspectJAutoProxy annotation which will be annotated in java configuration. To work with spring AOP and @AspectJ support, we need to create a class annotated with @Aspect annotation.
Crud Repository doesn't provide methods for implementing pagination and sorting. JpaRepository ties your repositories to the JPA persistence technology so it should be avoided. We should use CrudRepository or PagingAndSortingRepository depending on whether you need sorting and paging or not.
These Repositories are Java interfaces that allow you as the developer to define a data access contract. The Spring Data JPA framework can then inspect that contract, and automatically build the interface implementation under the covers for you.
Instead of using
@Pointcut("within(org.springframework.data.repository.CrudRepository)")
public void inDATAExec(){}
use like following
@Pointcut("this(org.springframework.data.repository.Repository)")
public void inDATAExec(){}
and what it does is
any join point (method execution only in Spring AOP) where the
proxy implements the Repository interface
You can have a look it at http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html
Hope it helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With