Announcement Announcement Module
Collapse
No announcement yet.
@Transactional behaviour Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @Transactional behaviour

    Hello,
    can anyone help me understand the following @Transactional behaviour?

    Here is my very simple service interface

    Code:
    public interface UserRegistrationService {
    	
    	public List<User> findEnabledUsernames();
    	
    }

    Here is the implementation

    Code:
    public class UserRegistrationServiceImpl implements UserRegistrationService {
    
    private UserHome userRepository;
    
    	public UserHome getUserRepository() {
    	return userRepository;
    }
    
    	public void setUserRepository(UserHome userRepository) {
    		this.userRepository = userRepository;
    	}
    	
    	@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
    	public List<User> findEnabledUsernames() {
    		
    		return userRepository.findEnabled();
    
    	}
    UserHome is a hibernate DAO class as follows

    Code:
    public class UserHome implements  UserDao{
    	
    	private SessionFactory sessionFactory;
    
    	
    	public SessionFactory getSessionFactory() {
    		return sessionFactory;
    	}
    
    	public void setSessionFactory(SessionFactory sessionFactory) {
    		this.sessionFactory = sessionFactory;
    	}
    
            public List<User> findEnabled(){
    		try {
                            Query q =  sessionFactory.getCurrentSession().createQuery("from User where enabled=true");
    			List<User> results = q.list();
    
                            return results;
    
    		} catch (RuntimeException re) {
    			log.error("find by enabled failed", re);
    			throw re;
    		}
    	}

    Now, if i use @Transactional annotation on the CONCRETE SERVICE CLASS method (as shown) I get a Hibernate exception. The exception is not thrown if the @Trandsactional is put on the SERVICE INTERFACE Method.

    The exception is as follows

    Code:
    No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
    at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
    at com.flextest.domain.UserHome.findEnabled(UserHome.java:179)
    at com.movereg.business.UserRegistrationServiceImpl.findEnabledUsernames(UserRegistrationServiceImpl.java:30)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
    at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:66)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at $Proxy131.findEnabledUsernames(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597) at flex.messaging.services.remoting.adapters.JavaAdapter.invoke(JavaAdapter.java:421)
    at flex.messaging.services.RemotingService.serviceMessage(RemotingService.java:183)
    at flex.messaging.MessageBroker.routeMessageToService(MessageBroker.java:1503)
    at flex.messaging.endpoints.AbstractEndpoint.serviceMessage(AbstractEndpoint.java:884)
    at flex.messaging.endpoints.AbstractEndpoint$$FastClassByCGLIB$$1a3ef066.invoke(<generated>)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:700)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
    at org.springframework.flex.core.MessageInterceptionAdvice.invoke(MessageInterceptionAdvice.java:59)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:126)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.Cglib2AopProxy$FixedChainStaticTargetInterceptor.intercept(Cglib2AopProxy.java:582)
    at flex.messaging.endpoints.AMFEndpoint$$EnhancerByCGLIB$$a57f8d15.serviceMessage(<generated>)
    at flex.messaging.endpoints.amf.MessageBrokerFilter.invoke(MessageBrokerFilter.java:121)
    at flex.messaging.endpoints.amf.LegacyFilter.invoke(LegacyFilter.java:158)
    at flex.messaging.endpoints.amf.SessionFilter.invoke(SessionFilter.java:44) at
    flex.messaging.endpoints.amf.BatchProcessFilter.invoke(BatchProcessFilter.java:67)
    at flex.messaging.endpoints.amf.SerializationFilter.invoke(SerializationFilter.java:146)
    at flex.messaging.endpoints.BaseHTTPEndpoint.service(BaseHTTPEndpoint.java:278)
    at flex.messaging.endpoints.AMFEndpoint$$EnhancerByCGLIB$$a57f8d15.service(<generated>)
    at org.springframework.flex.servlet.MessageBrokerHandlerAdapter.handle(MessageBrokerHandlerAdapter.java:101)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:427)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:315)
    at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:287)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:218)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:98)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:222)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:166)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1096) at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:288)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:647)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:579)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:831)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
    at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
    at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)

    Here is context config file relevant part

    Code:
    <context:property-placeholder location="/WEB-INF/jdbc.properties" />
    	
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="${jdbc.driverClassName}" 
    	p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}"/>
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
    	p:dataSource-ref="dataSource" p:mappingDirectoryLocations="classpath:com/flextest/domain/hibernate/hbm/">
    
    		<property name="hibernateProperties">
    			<props>
    				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
    				<prop key="hibernate.show_sql">true</prop>
    			</props>
    		</property>
    </bean>
    
    
    <bean id="UserRepository" class="com.flextest.domain.UserHome">
    		<property name="sessionFactory" ref="sessionFactory" />
    		
    	</bean>
    
    <bean id="UserRegistrationService" class="com.flextest.business.UserRegistrationServiceImpl">
    		<property name="userRepository" ref="UserRepository" />
    		
    		<flex:remoting-destination />
    		<sec:intercept-methods>
    		<sec:protect access="ROLE_USER" method="findEnabledUsernames"/>
    		</sec:intercept-methods>
    	</bean>
    
    
    	<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory"/>
    
    
    <tx:annotation-driven transaction-manager="txManager"/>

    I'd like to keep my transaction annotations on service classes and not on interfaces

    Thanks in advance

  • #2
    The problem arised due to double proxying behavior. You have defined it as a flex destination and added some security measures with the sec namespace. This already creates a proxy, that proxy implements all the interfaces that your class does (that is also why the interface works when you put @Transactional in there. The class some $Proxy23 class doesn't have the annotations because it is dynamically created.

    to make it work you will have to enable class proxying for all types of proxying (not sure if that is possible with this usage of the flex and sec namespace) and then it should work. I consider this a work around and I suggest you also add a [url=
    JIRA[/url] issue for this. I think it should detect a JDK dynamic proxy and then use the target of the proxy to do its inspection instead of the real object.

    Comment

    Working...
    X