DATAJDBC-136 - Fix ClassNotFoundException when MyBatis is not on the classpath.
This commit is contained in:
committed by
Greg Turnquist
parent
1291b5d33c
commit
2fbb3b00c7
@@ -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,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 {
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user