Skip to content

There is case that cannot scan classes using SpringBootVFS #301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 tasks done
kazuki43zoo opened this issue Mar 21, 2019 · 10 comments
Closed
2 tasks done

There is case that cannot scan classes using SpringBootVFS #301

kazuki43zoo opened this issue Mar 21, 2019 · 10 comments
Assignees
Labels
Milestone

Comments

@kazuki43zoo
Copy link
Member

kazuki43zoo commented Mar 21, 2019

Overview

See mybatis/mybatis-3#1500.

Conditions that matches this issue

If following all conditions are matched, the SpringBootVFS cannot scan classes correctly.

  • Run without executable jar(e.g. Maven/Gradle Plugin, IDE, etc...)
  • Scanning target classes are stored in jar file under maven local repository (e.g. ${HOME}/.m2/repository)
  • Specified scanning base package is matched with prefix of groupId

In this case, all conditions are matched as follow:

  • Run without executable jar because it use spring-boot-devtools
  • Scanning target classes are stored in $HOME/.m2/repository/com/bee/kuna/kuna-server-db/0.1.1-RELEASE/kuna-server-db-0.1.1-RELEASE.jar
  • Specified scanning base package is com.bee
  • GroupId of artifact that stared target classes is com.bee.kuna -> the groupId prefix is matched with scanning base package(com.bee)

Fix version

@kazuki43zoo
Copy link
Member Author

The valid workaround is changing the scanning base package to more nested package(e.g. com.bee.kuna.typehandler).

NOET:
Does not support the wildcard as the scanning base package (e.g. com.bee.*.typehandler). If you need to scan classes from multiple package, please specify base package for each. (e.g. mybatis.type-handlers-package=com.bee.kuna.typehandler,com.bee.foo.typehandler)

@kazuki43zoo
Copy link
Member Author

kazuki43zoo commented Mar 21, 2019

This issue's root cause are following code in SpringBootVFS.

private static String preserveSubpackageName(final Resource resource, final String rootPath) {
try {
final String uriStr = resource.getURI().toString();
final int start = uriStr.indexOf(rootPath);
return uriStr.substring(start);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

In this implementation, the MyBatis will try to scan the /com/bee/kuna/kuna-server-db/0.1.1-RELEASE/kuna-server-db-0.1.1-RELEASE.jar!com/bee/kuna/typehandler/FooTypeHandler.class.
In this case, the MyBatis should be scan com/bee/kuna/typehandler/FooTypeHandler.class.

I think uriStr.indexOf(rootPath); should be changed to uriStr.lastIndexOf(rootPath); .

New suggestion is as follow:

  @Override
  protected List<String> list(URL url, String path) throws IOException {
    String urlString = url.toString();
    String baseUrlString = urlString.endsWith("/") ? urlString : urlString.concat("/");
    Resource[] resources = resourceResolver.getResources(baseUrlString + "**/*.class");
    return Stream.of(resources)
        .map(resource -> preserveSubpackageName(baseUrlString, resource, path))
        .collect(Collectors.toList());
  }

  private static String preserveSubpackageName(final String baseUrlString, final Resource resource, final String rootPath) {
    try {
      return rootPath + (rootPath.endsWith("/") ? "" :  "/")
          + resource.getURL().toString().substring(baseUrlString.length());
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }

Above solution work fine on following runtime env:

  • IDE execution feature (Java application and XUnit)
  • Spring Boot Maven Plugin (mvn spring-boot:run)
  • Executable Jar file / War file (java -jar)
  • Deploying War file on Tomcat

@kazuki43zoo
Copy link
Member Author

kazuki43zoo commented Mar 21, 2019

@eddumelendez WDYT? Is correct my analysis and suggestion?

@kazuki43zoo
Copy link
Member Author

@wamaco

Thanks for your report!
I propose to apply workaround until fix this issue. See #301 (comment).

@kazuki43zoo kazuki43zoo modified the milestones: 1.3.4, 2.0.1 Mar 21, 2019
kazuki43zoo added a commit that referenced this issue Mar 26, 2019
Fix resources scanning bug on SpringBootVFS
@kazuki43zoo kazuki43zoo reopened this Mar 26, 2019
kazuki43zoo added a commit that referenced this issue Mar 27, 2019
Fix resources scanning bug on SpringBootVFS
@kazuki43zoo
Copy link
Member Author

kazuki43zoo commented Mar 27, 2019

Hi @wamaco,

I've fixed this and published snapshot version(2.0.1-SNAPSHOT, 1.3.4-SNAPSHOT) to sonatype-oss repository. If you are time, please check it.
About how to use snapshot version, see here.

Thanks!

@YannLex
Copy link

YannLex commented Mar 28, 2019

Hi @kazuki43zoo , thank you very much.
I have tested my code with 1.3.4-SNAPSHOT, and the warnings have disappeared.

I have a little suggestion, TypeHandler check all com.bee subpackages, now we can configure multiple packages like com.bee.kuna, com.bee.test, ..., but if we can configure it ascom.bee.*.typehandler.* will be great, like aspectj scanning do.

2019-03-28 10:57:30.323 DEBUG 37605 --- [  restartedMain] org.apache.ibatis.io.ResolverUtil        : Checking to see if class com.bee.kuna.server.logging.AccessLoggingProperties matches criteria [is assignable to TypeHandler]
2019-03-28 10:57:30.323 DEBUG 37605 --- [  restartedMain] org.apache.ibatis.io.ResolverUtil        : Checking to see if class com.bee.kuna.server.logging.AccessLoggingFilter matches criteria [is assignable to TypeHandler]

@naoki-iwami
Copy link

日本語にて失礼します。
こちら、現在のプロジェクトで試した(1.3.4-SNAPSHOT)ところ問題なく動きました。
該当のケースかどうかはわかりませんが、以下のような構成です。

@Indexed
@Configuration
@MapperScan(basePackageClasses = [ InfraConfig::class ], annotationClass = MybatisMapper::class)
@Profile("!ignore_mybatis")
class InfraDataSourceConfiguration {

    @Bean
    @Throws(Exception::class)
    fun sqlSessionFactory(dataSource: DataSource): SqlSessionFactory {
        val sessionFactory = SqlSessionFactoryBean()
        sessionFactory.setDataSource(dataSource)
        sessionFactory.setConfigLocation(ClassPathResource("/mybatis-config.xml"))
        sessionFactory.setFailFast(true)
        sessionFactory.vfs = SpringBootVFS::class.java
        return sessionFactory.`object`!!
    }

}

[mybatis-config.xml]
<configuration>
    <typeAliases>
        <typeAlias alias="velocity" type="org.mybatis.scripting.velocity.Driver"/>
        <package name="xxx.yyy" /><!-- このパッケージ配下にある @Alias をスキャンする -->
    </typeAliases>
</configuration>```

@kazuki43zoo
Copy link
Member Author

@wamaco Thanks for your working!

I have a little suggestion, TypeHandler check all com.bee subpackages, now we can configure multiple packages like com.bee.kuna, com.bee.test, ..., but if we can configure it ascom.bee..typehandler. will be great, like aspectj scanning do.

I will consider to support it!

@kazuki43zoo
Copy link
Member Author

@wamaco I've created #314.

@YannLex
Copy link

YannLex commented Apr 1, 2019

@wamaco I've created #314.

@kazuki43zoo thanks, I have subscribed, and I'm learning from you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants