1
votes

I have the following spring configuration:

<context:annotation-config />
<security:global-method-security jsr250-annotations="enabled"  pre-post-annotations="enabled" proxy-target-class="true" />

<tx:annotation-driven  />

<aop:aspectj-autoproxy />

<context:component-scan base-package="com.web,com.security" />

i have enabled proxy-target-class in global-method-security, because i want use @PreAuthorize annotation in the controller (i aware that spring team doesn't encourage this), and using aop aspectJ as 'interceptor' in service when saving an object.

it seem that because the proxy configuration in global-method-security enabled and the default aop aspectj is using proxy implementation. it failed to autowiring the bean in all controller. proxying proxy ?

controller

@RequestMapping(value = "add")
@PreAuthorize("@securityPermission.validatePermission()")
public String add(Model model) {
   //codes
}

my service class with @Aspect annotation

@SuppressWarnings("serial")
@Aspect
@Service
public class InterceptorServiceImpl extends BaseServiceImplementation implements InterceptorService {
@Autowired
    private LogRepository logRepository;

@Around("execution(* com.repository.CardRequestRepository.save(..))")
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class,timeout = 30)
   public Object checkProcess(ProceedingJoinPoint joinPoint) throws Throwable{
   LOGGER.info("SERVICE : START Process checking Interceptor");

}   

error logs :

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'approvalActivityController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.csl.cms.service.ApprovalActivityService com.csl.cms.web.ApprovalActivityController.approvalActivityService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'approvalActivityServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.csl.cms.repository.CardRequestRepository com.csl.cms.service.serviceimplementasi.ApprovalActivityServiceImpl.cardRequestRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cardRequestRepository': Post-processing of the FactoryBean's object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy572]: 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.$Proxy572
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:388)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4791)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.manager.ManagerServlet.start(ManagerServlet.java:1256)
at org.apache.catalina.manager.ManagerServlet.doGet(ManagerServlet.java:376)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:581)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)


Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy572]: 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.$Proxy572
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:213)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:112)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1598)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:162)
... 65 more
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy572
    at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446)
    at net.sf.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33)
    at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
    at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
    at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
    at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
    at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:201)
    ... 72 more

repository class

public interface CardRequestRepository extends JpaRepository<CardRequest, Long>, CardRequestRepositoryCustom {
public List<CardRequest> findByCardholderId(Long cardholderId);

@Query("Select cr FROM CardRequest cr "
        + "LEFT JOIN FETCH cr.cardholder ch "
        + "LEFT JOIN FETCH ch.identityDocument "
        + "LEFT JOIN FETCH cr.program p "
        + "WHERE cr.id = :id")
public CardRequest findOneFetching(@Param("id") Long cardholderId);

}

public interface CardRequestRepositoryCustom {

    public List<CardRequest> findCardRequestWithDatatablesCriterias(DatatablesCriterias criterias);
.....

service impl class

@SuppressWarnings("serial")
@Service
public class ApprovalActivityServiceImpl extends BaseServiceImplementasi implements ApprovalActivityService {

    @Autowired
    private ApprovalActivityRepository approvalActivityRepository;
    ...
    @Autowired
    private MessageSource messageSource;

    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public ApprovalActivity findOne(Long id) {
        LOGGER.info("SERVICE : ApprovalActivity findOne id =" + id);
        return approvalActivityRepository.findOne(id);
    }
}

baseserviceimpl class

public abstract class BaseServiceImplementasi
  implements Serializable
{
  protected transient Logger LOGGER = Logger.getLogger(getClass());
}

is it possible using aop:aspectj-autoproxy and enable proxy-target-class at same time ? or anyone have another suggestion ? :)

Failed Autowire Issue resolved

as suggestion from @M.Deinum i resolved my autowiring issue, added proxy-target-class="true" attribute in :

<tx:annotation-driven /> 
<cache:annotation-driven />
<aop:aspectj-autoproxy />

and i remove @Service in the class with @Aspect annotation.

note : in the InterceptorServiceImpl i was using @Service because i want @Autowiring to call repository/service bean

aspect class issue that occurred :

it seem because i have removed the @Service annotation in my aspect class, the aop aspectj somehow did not executed, and no error in my logs.

1
The stack-trace indicates the error is in code you have not shown. Please post the code for CardRequestRepository and ApprovalActivityServiceImplgeoand
Why is your @Aspect a @Service ?! Seems a bit unnatural. When using proxies and one of them specifies proxy-target-class="true" everything will use class based proxies. You can try to set everything to proxy-target-class="true".M. Deinum
@geoand i have added the repository class and serviceImpl class, and i think there is no relevance with the my proxy issue.satrioaditya
@satrioaditya Does BaseServiceImplementasi autowire CardRequestRepository perhaps? Can you show it's code?geoand
@geoand i have added the code, but actually it only contains logger, there is no autowire in the classsatrioaditya

1 Answers

3
votes

I resolved my issue, it seem because the using of data jpa (JpaRepository) in my repository class. here is my xml configuration :

<security:global-method-security jsr250-annotations="enabled" pre-post-annotations="enabled" proxy-target-class="true"/> //enabled proxy to use @preAuthorize in controller
<tx:annotation-driven />
<cache:annotation-driven />
<aop:aspectj-autoproxy />
<context:component-scan base-package="com.xxx.xxx.service.serviceimplementasi" />  
<jpa:repositories  base-package="com.csl.cms.repository" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"  /> 

data jpa configs :

<!--Spring Data JPA Configuration-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
        <property name="dataSource" ref="c3p0DataSource-1" />
        <property name="packagesToScan" value="com.xxx.xxx.entity"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="databasePlatform" value="${database.dialect}" /> 
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
            </bean>
        </property>
    </bean>
    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />        
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
    </bean>

repository class :

public interface CardRequestRepository extends JpaRepository<CardRequest, Long>, CardRequestRepositoryCustom {
    public List<CardRequest> findByCardholderId(Long cardholderId);

in CardRequestRepositoryCustom class, create a custom save method using entityManager, so it will not depends on JpaRepository class.

public class CardRequestRepositoryImpl implements CardRequestRepositoryCustom {

    @PersistenceContext
    private EntityManager em;

 @Override
    public CardRequest customSave(CardRequest cardRequest) {
       em.persist(cardRequest);
       return cardRequest;
    }

i also changed my point cut class in my aspect class, use the repository custom class :

@SuppressWarnings("serial")
@Aspect
@Component
public class ApprovalInterceptorServiceImpl extends BaseServiceImplementasi implements ApprovalInterceptorService {

    @Autowired
    private LifecycleLogRepository lifecycleLogRepository;
    @Autowired
    private ApprovalDefinitionRepository approvalDefinitionRepository;
    @Around("execution(* com.xxx.xxx.repository.repositoryimplementasi.CardRequestRepositoryImpl.customSave(..))")
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class,timeout = 30)
    public CardRequest checkApprovalProcess(ProceedingJoinPoint joinPoint) throws Throwable{
    LOGGER.info("SERVICE : START Approval Process checking Interceptor");
                System.out.println("SERVICE : START Approval Process checking Interceptor");

                Object messageParam[] = new Object[1];
        Object[] objs = joinPoint.getArgs();
        CardRequest cardRequest = (CardRequest) objs[0];

....

in the aop aspect class, using @Component to autowiring the service bean and do not extends the repository class using jpaRepository, instead use/create a custom repository class and entityManager to save an object. with this configuration and codes my proxy class problem fixed.

if i applied @Component, @Autowired and using jpaRepository in my aspect class, the repository bean class failed to autowiring. still does not know why it happen.