So my Spring education continues. Currently I'm trying to learn some of the annotations and the things they bring to Spring 3. So I've got a mini webapp that can connect to a DB and put stuff in through a form and display records and so on. Everything works fine. I decided to try and get Spring to auto-detect the service bean that I have marked as @Transactional but doing that stops the app from saving to the DB. So:
@Transactional
public class ReservationServiceImpl implements ReservationService {
that works. I have a bean declaration of this class in my springcourt-data.xml files. No problems. When I do this though:
@Transacational
@Service("reservationService")
public class ReservationServiceImpl implements ReservationService {
it no longer works. And I do have
<context:component-scan base-package="com.springcourt" />
in the springcourt-servlet.xml file. So can anyone tell me what I'm screwing up? All I do is add another annotation to this class and remove the bean definition from the xml file and it no longer saves data to the DB. I can still query records and stuff from the DB though so obviously it's using the autodetected service bean.
Here are the config files:
springcourt-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="com.springcourt" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="com.springcourt.web.ReservationBindingInitializer" />
</property>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
And:
springcourt-data.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="admin" />
<property name="initialSize" value="5" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven />
<bean id="reservationService" class="com.springcourt.service.ReservationServiceImpl"/>
</beans>
When you use @Service and component scanning the bean is created by the context created by the dispatcher servlet (mvc). Since the transaction:annotation driven is defined in the root application context it doesn't apply to the beans in the servlets context. You can verify this by removing the @Service and moving the bean definition to the servlet context file - you should see the same result.
Where as when you don't use component scanning - the bean is defined in the XML of the root application context.
The fix is to change the component-scan tag in the web layer to only include web layer classes - either by using a different base package or by using an include / exclude filter. Add another component scan in the root application context for the other beans.
Querying might be working because you might have a OpenEntityManagerInViewInterceptor / Filter configured.