Browse Source

DATAJDBC-136 - Fix ClassNotFoundException when MyBatis is not on the classpath.

pull/21/head
Jens Schauder 8 years ago committed by Greg Turnquist
parent
commit
2fbb3b00c7
No known key found for this signature in database
GPG Key ID: CB2FA4D512B5C413
  1. 16
      src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java
  2. 25
      src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java

16
src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java

@ -118,12 +118,22 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend @@ -118,12 +118,22 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
private Optional<DataAccessStrategy> createMyBatisDataAccessStrategy() {
if (!ClassUtils.isPresent("org.apache.ibatis.session.SqlSessionFactory", this.getClass().getClassLoader())) {
String myBatisSqlSessionFactoryClassName = "org.apache.ibatis.session.SqlSessionFactory";
ClassLoader classLoader = this.getClass().getClassLoader();
if (!ClassUtils.isPresent(myBatisSqlSessionFactoryClassName, classLoader)) {
return Optional.empty();
}
return getBean(SqlSessionFactory.class, SQL_SESSION_FACTORY_BEAN_NAME)
.map(ssf -> new MyBatisDataAccessStrategy(ssf));
try {
return getBean(classLoader.loadClass(myBatisSqlSessionFactoryClassName), SQL_SESSION_FACTORY_BEAN_NAME)
// note that the cast to SqlSessionFactory happens in a lambda, which is basically a separate class
// thus it won't get loaded if this code path doesn't get executed.
.map(ssf -> new MyBatisDataAccessStrategy((SqlSessionFactory) ssf));
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Detected MyBatis on classpath but failed to load the class " + myBatisSqlSessionFactoryClassName);
}
}
private Optional<DataAccessStrategy> createDefaultAccessStrategy(JdbcMappingContext context,

25
src/test/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBeanUnitTests.java

@ -25,9 +25,11 @@ import org.springframework.data.jdbc.core.DelegatingDataAccessStrategy; @@ -25,9 +25,11 @@ import org.springframework.data.jdbc.core.DelegatingDataAccessStrategy;
import org.springframework.data.jdbc.mybatis.MyBatisDataAccessStrategy;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.instrument.classloading.ShadowingClassLoader;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.util.ReflectionUtils;
/**
* Tests the dependency injection for {@link JdbcRepositoryFactoryBean}.
@ -211,6 +213,29 @@ public class JdbcRepositoryFactoryBeanUnitTests { @@ -211,6 +213,29 @@ public class JdbcRepositoryFactoryBeanUnitTests {
assertThat(findDataAccessStrategy(factory, MyBatisDataAccessStrategy.class)).isNotNull();
}
@Test // DATAJDBC-136
public void canBeLoadedWithoutMyBatis() throws Exception {
String sqlSessionFactoryClassName = SqlSessionFactory.class.getName();
ShadowingClassLoader classLoader = new ShadowingClassLoader(this.getClass().getClassLoader()) {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.equals(sqlSessionFactoryClassName)) {
throw new ClassNotFoundException("%s is configured not to get loaded by this classloader");
}
return super.loadClass(name);
}
};
Class<?> loadedClass = classLoader.loadClass(JdbcRepositoryFactoryBean.class.getName());
assertThat(loadedClass).isNotNull();
ReflectionUtils.getAllDeclaredMethods(loadedClass);
}
private Condition<? super RepositoryFactorySupport> using(NamedParameterJdbcOperations expectedOperations) {
Predicate<RepositoryFactorySupport> predicate = r -> extractNamedParameterJdbcOperations(r) == expectedOperations;

Loading…
Cancel
Save