|
Hello everyone,
I am trying to set up MyBatis with Spring but encounter an autowire error during a unit test. I followed the pet store example very closely but can't get Spring to see my Mapper. Hopefully I am just doing something boneheaded! Thanks in advance for any help you can provide. Configuration: Spring 3.1.1 mybatis-spring 1.1.0 hsqldb 2.2.4 Java 1.6 ==================== My Mapper XML (located in com.bonddesk.bondapi.message.persistence): <mapper namespace="com.bonddesk.bondapi.message.persistence.MessageMapper"> <select id="getMessage" parameterType="long" resultType="Message"> select MSG_ID as messageId, USER_ID as userId, POSTED_TS as posted, EVENT_TYPE as eventType, MSG_READ as read, MSG_DELETED as deleted, ACTION_DONE as actionDone from USER_EVENT_STORE where messageId = #{messageId} </select> </mapper> ==================== My Mapper Class (located in com.bonddesk.bondapi.message.persistence): public interface MessageMapper { Message getMessage(long messageId); } ==================== My Spring Configuration: <!-- enable autowire --> <context:annotation-config /> <!-- enable component scanning (beware that this does not enable mapper scanning!) --> <context:component-scan base-package="com.bonddesk.bondapi" /> <!-- enable transaction demarcation with annotations --> <tx:annotation-driven /> <!-- configure property file locations --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations" value="classpath:jdbc.properties"/> </bean> <!-- message data source --> <bean id="dataSource" destroy-method="close" class="com.jolbox.bonecp.BoneCPDataSource"> <property name="driverClass" value="${jdbc.driverClassName}"/> <property name="jdbcUrl" value="${jdbc.url}${jdbc.schema}$ {jdbc.driverProperties}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="typeAliasesPackage" value="com.bonddesk.bondapi.message.domain" /> </bean> <!-- scan for mappers and let them be autowired --> <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.bonddesk.bondapi.message.persistence" /> </bean> </beans> ==================== My Repository (where mapper is being auto wired): @Repository public class MyBatisMessageRepository implements MessageRepository { @Autowired private MessageMapper messageMapper; @Override public Message getMessage(long messageId) { return messageMapper.getMessage(messageId); } } ==================== My Unit Test: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/applicationContext.xml") public class MyBatisMessageRepositoryTest { @Autowired private MessageRepository messageRepository; @Test public void getNewOrderMessage() { Message message = messageRepository.getMessage(515851L); assertThat(message, not(nullValue())); } } ==================== Relevant portions of the log output: Running com.bonddesk.bondapi.message.persistence.MyBatisMessageRepositoryTest 2012-03-20 11:14:41,467 [main] DEBUG org.mybatis.spring.mapper.MapperScannerConfigurer$Scanner - Ignored because not a concrete top-level class: file [/Users/bill/dev/projects/ bondapi/target/test-classes/com/bonddesk/bondapi/message/persistence/ MyBatisMessageRepositoryTest.class] 2012-03-20 11:14:41,468 [main] DEBUG org.mybatis.spring.mapper.MapperScannerConfigurer$Scanner - Identified candidate component class: file [/Users/bill/dev/projects/bondapi/ target/classes/com/bonddesk/bondapi/message/persistence/ MessageMapper.class] 2012-03-20 11:14:41,468 [main] DEBUG org.mybatis.spring.mapper.MapperScannerConfigurer$Scanner - Ignored because not a concrete top-level class: file [/Users/bill/dev/projects/ bondapi/target/classes/com/bonddesk/bondapi/message/persistence/ MyBatisMessageRepository.class] 2012-03-20 11:14:41,469 [main] DEBUG org.mybatis.spring.mapper.MapperScannerConfigurer$Scanner - Creating MapperFactoryBean with name 'messageMapper' and 'com.bonddesk.bondapi.message.persistence.MessageMapper' mapperInterface 2012-03-20 11:14:41,602 [main] ERROR org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@1efd9b97] to prepare test instance [com.bonddesk.bondapi.message.persistence.MyBatisMessageRepositoryTest@1bf1e666] … Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.bonddesk.bondapi.message.persistence.MessageMapper] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java: 924) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java: 793) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java: 707) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor $AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java: 478) … Tests in error: getNewOrderMessage(com.bonddesk.bondapi.message.persistence.MyBatisMessageRepositoryTest): Failed to load ApplicationContext |
|
I tried wiring everything up manually via Spring XML configuration and
it actually worked. While I am happy things are working, I would rather go back to using annotations and autowire. I don't understand why the MapperScannerConfigurer isn't working for me. ==================== Here is the Spring config that gets it working: <!-- enable autowire --> <context:annotation-config /> <!-- enable component scanning (beware that this does not enable mapper scanning!) --> <context:component-scan base-package="com.bonddesk.bondapi" /> <!-- enable transaction demarcation with annotations --> <tx:annotation-driven /> <!-- configure property file locations --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations" value="classpath:jdbc.properties"/> </bean> <!-- message data source --> <bean id="dataSource" destroy-method="close" class="com.jolbox.bonecp.BoneCPDataSource"> <property name="driverClass" value="${jdbc.driverClassName}"/> <property name="jdbcUrl" value="${jdbc.url}${jdbc.schema}$ {jdbc.driverProperties}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="typeAliasesPackage" value="com.bonddesk.bondapi.message.domain" /> </bean> <bean id="messageMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.bonddesk.bondapi.message.persistence.MessageMapper" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> <bean id="messageRepository" class="com.bonddesk.bondapi.message.persistence.MyBatisMessageRepository"> <constructor-arg ref="messageMapper" /> </bean> ==================== Here is the modified MessageRepository class: public class MyBatisMessageRepository implements MessageRepository { private MessageMapper messageMapper; public MyBatisMessageRepository(MessageMapper messageMapper) { this.messageMapper = messageMapper; } @Override public Message getMessage(long messageId) { return messageMapper.getMessage(messageId); } } |
| Powered by Nabble | Edit this page |
