Announcement Announcement Module
Collapse
No announcement yet.
Problem when calling a transactionnal service inside a LTW aspect. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem when calling a transactionnal service inside a LTW aspect.

    Hi,

    I have transactions problems when I call services inside LTW aspects.
    Here is what I'm trying to do:

    Code:
    @Aspect
    public class MyAspect {
      
      @Autowired
      UserService userService;
    
      @AfterReturning(
      pointcut = "......."
        )
      public void f() {
          userService.list();   // Problem here No Hibernate Session bound to thread ....
      }
    
    }
    So I have an aspect "weaved" at load time (not managed by Spring).

    Inside f() I call a transactionnal service "userService.list()", the following exception is thrown :
    org.springframework.orm.hibernate3.HibernateSystem Exception: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here.
    I do not understand why this exception is thrown because when I use my service "userService.list()" outside the aspect it works. Transactions on "UserService.list()" are configure using <tx-advice> and works everywhere in the application.

    But it does not work inside the "MyAspect" LTW aspect, why ???
    Because "MyAspect" isn't managed by Spring ?

    Thanks.

  • #2
    Your aspects are created before the other beans and are needed before proxying. So you are working with an unproxied/unadviced userService, whereas your other beans have a proxied instance. (I would expect to see some info/warn messages in your logfile if you would enable that loglevel).

    Instead of injecting your dependency lazy look it up. Make your aspect ApplicationContextAware and retrieve the bean from the context and then use it.

    Comment


    • #3
      Ok, thanks for your help, I've tried to do what you said.

      My code is the following:

      Code:
      @Aspect
      public class MyAspect implements ApplicationContextAware {
        
        private UserService userService;
        private static ApplicationContext applicationContext;
      
        @AfterReturning(
        pointcut = "......."
          )
        public void f() {
            this.getUserService().list();   // Problem here No Hibernate Session bound to thread ....
        }
      
        @Override
        public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
          this.applicationContext = applicationContext;
        }
      
        private UserService getUserService() {
          if(this.userService == null) {
            this.userService = (UserService)   this.applicationContext.getBean("userService ");
          }
          	
          return this.userService;
        }
      }
      But the hibernate exception is thrown again...
      In fact there is an other weird thing, I have multiple advices in my aspect.
      It appears that advices which are executed after transactionnal services (and use transactionnal services) does not throw this exception.
      But advices executed after functions like "f()" (not transactionnal) which use transactionnal services throw an hibernate exception indicating that the Hibernate Session is not bound to the current thread.

      Here is the detail of the exception trace I obtain after execution of an advice like "f()" (in this case UserService is replaced by ExecutionReportService) :
      DEBUG 2008-06-26 13:55:03,343 (AbstractMessageListenerContainer.java:577) - Initiating transaction rollback on application exception
      org.springframework.orm.hibernate3.HibernateSystem Exception: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
      at org.springframework.orm.hibernate3.SessionFactoryU tils.convertHibernateAccessException(SessionFactor yUtils.java:661)
      at org.springframework.orm.hibernate3.AbstractSession FactoryBean.convertHibernateAccessException(Abstra ctSessionFactoryBean.java:303)
      at org.springframework.orm.hibernate3.AbstractSession FactoryBean.translateExceptionIfPossible(AbstractS essionFactoryBean.java:282)
      at org.springframework.dao.support.ChainedPersistence ExceptionTranslator.translateExceptionIfPossible(C hainedPersistenceExceptionTranslator.java:62)
      at org.springframework.dao.support.DataAccessUtils.tr anslateIfNecessary(DataAccessUtils.java:212)
      at org.springframework.dao.support.PersistenceExcepti onTranslationInterceptor.invoke(PersistenceExcepti onTranslationInterceptor.java:146)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :171)
      at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:204)
      at $Proxy54.findRunning(Unknown Source)
      at com.mycompany.imp.server.services.workflow.deploye d.impl.ExecutionReportServiceImpl.findRunning(Exec utionReportServiceImpl.java:84)
      at com.mycompany.imp.server.services.workflow.aspects .WorkflowExecutionReportMaker.addJvmState(Workflow ExecutionReportMaker.java:194)
      at com.mycompany.imp.server.services.workflow.cpe.jms .server.impl.OnJvmStateListenerImpl.onJvmState(OnJ vmStateListenerImpl.java:106)
      at com.mycompany.imp.server.services.workflow.cpe.jms .server.impl.CpeInstanceMDP.executeOnJvmStateListe ners(CpeInstanceMDP.java:177)
      at com.mycompany.imp.server.services.workflow.cpe.jms .server.impl.CpeInstanceMDP.onJvmState(CpeInstance MDP.java:287)
      at com.mycompany.imp.server.services.workflow.cpe.jms .server.impl.CpeInstanceMDP.onMessage(CpeInstanceM DP.java:129)
      at org.springframework.jms.listener.AbstractMessageLi stenerContainer.doInvokeListener(AbstractMessageLi stenerContainer.java:531)
      at org.springframework.jms.listener.AbstractMessageLi stenerContainer.invokeListener(AbstractMessageList enerContainer.java:466)
      at org.springframework.jms.listener.AbstractMessageLi stenerContainer.doExecuteListener(AbstractMessageL istenerContainer.java:435)
      at org.springframework.jms.listener.AbstractPollingMe ssageListenerContainer.doReceiveAndExecute(Abstrac tPollingMessageListenerContainer.java:322)
      at org.springframework.jms.listener.AbstractPollingMe ssageListenerContainer.receiveAndExecute(AbstractP ollingMessageListenerContainer.java:260)
      at org.springframework.jms.listener.DefaultMessageLis tenerContainer$AsyncMessageListenerInvoker.invokeL istener(DefaultMessageListenerContainer.java:944)
      at org.springframework.jms.listener.DefaultMessageLis tenerContainer$AsyncMessageListenerInvoker.run(Def aultMessageListenerContainer.java:868)
      at java.lang.Thread.run(Thread.java:619)
      Caused by: org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
      at org.springframework.orm.hibernate3.SpringSessionCo ntext.currentSession(SpringSessionContext.java:63)
      at org.hibernate.impl.SessionFactoryImpl.getCurrentSe ssion(SessionFactoryImpl.java:544)
      at com.mycompany.imp.server.dao.hbm.AbstractHbmImpDao .createCriteria(AbstractHbmImpDao.java:93)
      at com.mycompany.imp.server.dao.hbm.AbstractHbmImpDao .createCriteria(AbstractHbmImpDao.java:134)
      at com.mycompany.imp.server.dao.workflow.hbm.HbmExecu tionReportDao.findRunning(HbmExecutionReportDao.ja va:82)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.springframework.aop.support.AopUtils.invokeJoi npointUsingReflection(AopUtils.java:310)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.invokeJoinpoint(ReflectiveMethodInvocat ion.java:182)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :149)
      at org.springframework.dao.support.PersistenceExcepti onTranslationInterceptor.invoke(PersistenceExcepti onTranslationInterceptor.java:138)
      ... 17 more
      So, do you know why this isn't working even with aspect class implementing ApplicationContextAware ?

      Thanks.

      Comment


      • #4
        Hi, I have not found any solution to my problem, I think the problem is that I'm running an advice after a "not transactionnal" function.

        If it could help this is the code of the advice which does not works.

        Code:
        @AfterReturning(
                pointcut = "execution("
                    + "void com.mycompany.imp.server.services.workflow.cpe.jms.server.impl.OnJvmStateListenerImpl.onJvmState(..))"
                    + " && target(target) && args(jvmState,..)"
            )
            public void addJvmState(Object target, JvmState jvmState)
            {
                Validate.isNotNull(jvmState, "jvmState");
        
                OnJvmStateListenerImpl onJvmStateListener = (OnJvmStateListenerImpl) target;
        
                ExecutionReport executionReport = this.getExecutionReportService().findRunning(onJvmStateListener .getCpeInstanceManager().getDeployedUimaWorkflow());
                    
        
                // -- Adds the new JvmState and updates the report
                executionReport.addExchangeMessage(new jvmStateMessage(jvmState));
        
                this.getExecutionReportService().update(executionReport);
            }
        
        private ExecutionReportService getExecutionReportService()
            {
                if (this.executionReportService == null)
                {
                    this.executionReportService = (ExecutionReportService) applicationContext.getBean("executionReportService");
                }
        
                return this.executionReportService;
            }
        I think the problem could be:
        - "OnJvmStateListenerImpl()" is created with a new() (call to a constructor) and is not managed by Spring ??
        - the call to onJvmState() is done inside a Spring Message Driven Pojo, is this a problem ?? I don't remember how the Spring MDP container but perhaps this is the cause of "no hibernate session bound to thread" because the MDP container create new threads ?

        So is this could help to solve my problems ??

        Comment

        Working...
        X