I'm facing the following exception when using Java 8 (1.8.0_60), Spring 4.2.1 and MyBatis 3.3.0
Sep 29, 2015 11:02:58 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@246b179d: startup date [Tue Sep 29 11:02:58 EDT 2015]; root of context hierarchy
Sep 29, 2015 11:02:58 AM org.mybatis.spring.mapper.ClassPathMapperScanner checkCandidate
WARNING: Skipping MapperFactoryBean with name 'userMapper' and 'com.poc.test.spring4app.mapper.UserMapper' mapperInterface. Bean already defined with the same name!
Sep 29, 2015 11:02:58 AM org.mybatis.spring.mapper.ClassPathMapperScanner doScan
WARNING: No MyBatis mapper was found in '[com.poc.test.spring4app.mapper]' package. Please check your configuration.
Creating tables
Sep 29, 2015 11:02:59 AM org.springframework.context.annotation.AnnotationConfigApplicationContext refresh
WARNING: Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userMapper' defined in com.poc.test.spring4app.config.AppConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.poc.test.spring4app.mapper.UserMapper]: Factory method 'userMapper' threw exception; nested exception is org.apache.ibatis.binding.BindingException: Type interface com.poc.test.spring4app.mapper.UserMapper is not known to the MapperRegistry.
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at com.poc.test.spring4app.config.AppInitializer.main(AppInitializer.java:16)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.poc.test.spring4app.mapper.UserMapper]: Factory method 'userMapper' threw exception; nested exception is org.apache.ibatis.binding.BindingException: Type interface com.poc.test.spring4app.mapper.UserMapper is not known to the MapperRegistry.
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 13 more
Caused by: org.apache.ibatis.binding.BindingException: Type interface com.poc.test.spring4app.mapper.UserMapper is not known to the MapperRegistry.
at org.apache.ibatis.binding.MapperRegistry.getMapper(MapperRegistry.java:47)
at org.apache.ibatis.session.Configuration.getMapper(Configuration.java:675)
at org.mybatis.spring.SqlSessionTemplate.getMapper(SqlSessionTemplate.java:293)
at com.poc.test.spring4app.config.AppConfiguration.userMapper(AppConfiguration.java:51)
at com.poc.test.spring4app.config.AppConfiguration$$EnhancerBySpringCGLIB$$8dd4b125.CGLIB$userMapper$0(<generated>)
at com.poc.test.spring4app.config.AppConfiguration$$EnhancerBySpringCGLIB$$8dd4b125$$FastClassBySpringCGLIB$$677c8295.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318)
at com.poc.test.spring4app.config.AppConfiguration$$EnhancerBySpringCGLIB$$8dd4b125.userMapper(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 14 more
The application has been running fine using JDK 1.7 & Spring 3.2.2. But since Spring 4 is needed for JDK upgrade, I'm facing these compatibility issues.
Below are the sample code details. The below POC is based on the example in this blog. Thanks to Mike for that. The app works fine if I change Spring version from 4.2.1 to 3.2.9. In case of 4.2.1, I get the above exception.
POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.poc.test</groupId>
<artifactId>spring4app</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring4App</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>4.2.1.RELEASE</spring.version>
<spring-batch.version>3.0.5.RELEASE</spring-batch.version>
<mybatisVersion>3.3.0</mybatisVersion>
<mybatisSpringVersion>1.2.3</mybatisSpringVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
<version>${spring-batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>${spring-batch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- DB RELATED -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatisVersion}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatisSpringVersion}</version>
</dependency>
<!-- Binding for Log4J -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!-- H2Db related -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.167</version>
</dependency>
</dependencies>
<build>
<finalName>Spring4App</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<includes>
<include>**/${includeTestGroup}/**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>Spring4App</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
AppInitializer
package com.poc.test.spring4app.config;
import java.util.List;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import com.poc.test.spring4app.domain.User;
import com.poc.test.spring4app.mapper.UserMapper;
public class AppInitializer {
public static void main(String[] args) {
AbstractApplicationContext context = null;
try {
context = new AnnotationConfigApplicationContext(
AppConfiguration.class);
context.registerShutdownHook();
UserMapper userMapper = context.getBean(UserMapper.class);
List<User> users = userMapper.getAllUsers();
System.out.println(users.toString());
context.close();
}
catch (final Exception e) {
if (context != null) {
context.close();
}
}
}
}
AppConfiguration
package com.poc.test.spring4app.config;
import javax.sql.DataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import com.poc.test.spring4app.mapper.UserMapper;
@Configuration
@MapperScan("com.poc.test.spring4app.mapper")
public class AppConfiguration {
@Bean
public DataSource dataSource() {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(org.h2.Driver.class);
dataSource.setUsername("sa");
dataSource.setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setPassword("");
// create a table and populate some data
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
System.out.println("Creating tables");
jdbcTemplate.execute("drop table users if exists");
jdbcTemplate.execute("create table users(id serial, firstName varchar(255), lastName varchar(255), email varchar(255))");
jdbcTemplate.update("INSERT INTO users(firstName, lastName, email) values (?,?,?)", "FirstName", "LastName", "[email protected]");
return dataSource;
}
@Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
@Bean
public SqlSessionFactoryBean sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setTypeAliasesPackage("com.poc.test.spring4app.mapper");
return sessionFactory;
}
@Bean
public UserMapper userMapper() throws Exception {
final SqlSessionTemplate sessionTemplate = new SqlSessionTemplate(sqlSessionFactory().getObject());
return sessionTemplate.getMapper(UserMapper.class);
}
}
User Mapper
package com.poc.test.spring4app.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import com.poc.test.spring4app.domain.User;
public interface UserMapper {
@Select("select id, firstName, lastName, email from users")
@Results(value={
@Result(column="id", property="id"),
@Result(column="firstName", property="firstName"),
@Result(column="lastName", property="lastName"),
@Result(column="email", property="email")
})
List<User> getAllUsers();
}
User
package com.poc.test.spring4app.domain;
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private long id;
private String firstName;
private String lastName;
private String email;
/**
* @return the id
*/
public long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(long id) {
this.id = id;
}
/**
* @return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* @param firstName the firstName to set
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* @return the lastName
*/
public String getLastName() {
return lastName;
}
/**
* @param lastName the lastName to set
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* @return the email
*/
public String getEmail() {
return email;
}
/**
* @param email the email to set
*/
public void setEmail(String email) {
this.email = email;
}
// getters and setters
}