When use the latest Spring Boot 3.0.0-SNAPSHOT together with mybatis-spring-boot 3.x(under development), we cannot deploy war file to the Tomcat 10. Until Spring Boot 3.0.0-RC2 it work fine.
Logs
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.0.0-SNAPSHOT)
2022-11-23T16:21:30.291+09:00 INFO 71116 --- [ main] s.mybatis.war.SampleWebApplication : Starting SampleWebApplication using Java 17.0.1 with PID 71116 (/Users/shimizukazuki/git-me/spring-boot-starter/mybatis-spring-boot-samples/mybatis-spring-boot-sample-war/target/cargo/configurations/tomcat10x/webapps/mybatis-spring-boot-sample-war/WEB-INF/classes started by shimizukazuki in /Users/shimizukazuki/git-me/spring-boot-starter/mybatis-spring-boot-samples/mybatis-spring-boot-sample-war/target/cargo/configurations/tomcat10x)
2022-11-23T16:21:30.296+09:00 INFO 71116 --- [ main] s.mybatis.war.SampleWebApplication : No active profile set, falling back to 1 default profile: "default"
2022-11-23T16:21:32.309+09:00 INFO 71116 --- [ main] .C.[.[.[/mybatis-spring-boot-sample-war] : Initializing Spring embedded WebApplicationContext
11月 23, 2022 4:21:32 午後 org.apache.catalina.core.ApplicationContext log
情報: Initializing Spring embedded WebApplicationContext
2022-11-23T16:21:32.313+09:00 INFO 71116 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1940 ms
2022-11-23T16:21:32.785+09:00 INFO 71116 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2022-11-23T16:21:33.322+09:00 INFO 71116 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:ff60724f-b1e3-44a5-a108-6e4484a3d63b user=SA
2022-11-23T16:21:33.326+09:00 INFO 71116 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2022-11-23T16:21:33.463+09:00 WARN 71116 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cityRestController' defined in file [/Users/shimizukazuki/git-me/spring-boot-starter/mybatis-spring-boot-samples/mybatis-spring-boot-sample-war/target/cargo/configurations/tomcat10x/webapps/mybatis-spring-boot-sample-war/WEB-INF/classes/sample/mybatis/war/controller/CityRestController.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'cityMapper' defined in file [/Users/shimizukazuki/git-me/spring-boot-starter/mybatis-spring-boot-samples/mybatis-spring-boot-sample-war/target/cargo/configurations/tomcat10x/webapps/mybatis-spring-boot-sample-war/WEB-INF/classes/sample/mybatis/war/mapper/CityMapper.class]: Cannot resolve reference to bean 'sqlSessionTemplate' while setting bean property 'sqlSessionTemplate'
2022-11-23T16:21:33.464+09:00 INFO 71116 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2022-11-23T16:21:33.467+09:00 INFO 71116 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2022-11-23T16:21:33.484+09:00 INFO 71116 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger :
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2022-11-23T16:21:33.548+09:00 ERROR 71116 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'mybatis.configuration.environment' to org.apache.ibatis.mapping.Environment:
Reason: java.lang.IllegalStateException: Failed to extract parameter names for public org.apache.ibatis.mapping.Environment(java.lang.String,org.apache.ibatis.transaction.TransactionFactory,javax.sql.DataSource)
Action:
Update your application's configuration
...
Caused by: org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'mybatis-org.mybatis.spring.boot.autoconfigure.MybatisProperties': Could not bind properties to 'MybatisProperties' : prefix=mybatis, ignoreInvalidFields=false, ignoreUnknownFields=true
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:92)
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:78)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1743)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1405)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:880)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:784)
... 93 more
Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'mybatis.configuration.environment' to org.apache.ibatis.mapping.Environment
at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:387)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:347)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:98)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:86)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:98)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:86)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:62)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:332)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:262)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:249)
at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:94)
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:89)
... 107 more
Caused by: java.lang.IllegalStateException: Failed to extract parameter names for public org.apache.ibatis.mapping.Environment(java.lang.String,org.apache.ibatis.transaction.TransactionFactory,javax.sql.DataSource)
at org.springframework.util.Assert.state(Assert.java:97)
at org.springframework.boot.context.properties.bind.ValueObjectBinder$DefaultValueObject.parseConstructorParameters(ValueObjectBinder.java:270)
at org.springframework.boot.context.properties.bind.ValueObjectBinder$DefaultValueObject.<init>(ValueObjectBinder.java:264)
at org.springframework.boot.context.properties.bind.ValueObjectBinder$DefaultValueObject.get(ValueObjectBinder.java:291)
at org.springframework.boot.context.properties.bind.ValueObjectBinder$ValueObject.get(ValueObjectBinder.java:198)
at org.springframework.boot.context.properties.bind.ValueObjectBinder.bind(ValueObjectBinder.java:67)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476)
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590)
at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576)
at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474)
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343)
... 132 more
Reproduce
- https://github.com/kazuki43zoo/spring-boot-starter/tree/gh-732/mybatis-spring-boot-samples/mybatis-spring-boot-sample-war
Start the Tomcat server using argo plugin:
./mvnw clean package cargo:run -Dmaven.test.skip -Denforcer.skip=true -pl mybatis-spring-boot-samples/mybatis-spring-boot-sample-war
Access to API:
curl http://localhost:18080/mybatis-spring-boot-sample-war/cities/CA -D -
HTTP/1.1 404
Content-Type: text/html;charset=utf-8
Content-Language: ja
Content-Length: 809
Date: Wed, 23 Nov 2022 07:32:51 GMT
<!doctype html><html lang="ja"><head><title>HTTPステータス 404 – 見つかりません。</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {fo} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTPステータス 404 – 見つかりません。</h1><hr class="lタイプ</b> ステータスレポート</p><p><b>説明</b> オリジンサーバーは、ターゲットリソースの現在の表現を見つけられなかったか、またはそれが存在することを開示するつもりはありません。</p><hr class="line" /><h3>Apache Tomcat
View container log file:
cat mybatis-spring-boot-samples/mybatis-spring-boot-sample-war/target/cargo/container.log
Downgrade to Spring Boot 3.0.0-RC2
Edit pom.xml stored the root directory as follow:
- <spring-boot.version>3.0.0-SNAPSHOT</spring-boot.version>
+ <spring-boot.version>3.0.0-RC2</spring-boot.version>
Start the Tomcat server using argo plugin:
./mvnw clean package cargo:run -Dmaven.test.skip -Denforcer.skip=true -pl mybatis-spring-boot-samples/mybatis-spring-boot-sample-war
Access to API:
curl http://localhost:18080/mybatis-spring-boot-sample-war/cities/CA -D -
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 23 Nov 2022 07:34:53 GMT
{"id":1,"name":"San Francisco","state":"CA","country":"US"}
Related issues
- mybatis/spring-boot-starter#734
Comment From: wilkinsona
Thanks for trying the snapshots. Due to this change in Spring Framework that corrects an oversight in 6.0.0 you need to compile your code with -parameters.
Comment From: kazuki43zoo
@wilkinsona Thanks for your feedback!! I understand it!!
Comment From: wilkinsona
Looking more closely, MybatisProperties is using org.apache.ibatis.session.Configuration as a nested configuration property. Unfortunately, we don't really recommend binding to complex third-party types like this. Configuration has a getter and setter for org.apache.ibatis.mapping.Environment. To have configuration properties bound to this class, constructor binding must be used. The constructor's arguments are:
Stringorg.apache.ibatis.transaction.TransactionFactoryjavax.sql.DataSource
Of these three arguments only String is a type that's suitable for configuration property binding. Both TransactionFactory and DataSource are interfaces so cannot be created from configuration properties.
I know it's quite a large amount of work but I would recommend that you stop trying to bind configuration properties directly to org.apache.ibatis.session.Configuration. Instead, you should bind to your own class designed specifically for configuration property binding and then create a Configuration instance using those properties. You can see an example of this in Boot's auto-configuration for Flyway.
This recommendation really applies for any version of Spring Boot as it makes configuration property binding more robust. Even if org.apache.ibatis.mapping.Environment had been compiled with -parameters, I would still recommend making these changes. In addition to addressing the problems described above, they allow you to control exactly what can and cannot be bound and for accurate metadata for the configuration properties to be generated. The recommendation becomes more important in 3.0 with the changes to parameter name discovery in Framework and also our GraalVM support.
Comment From: kazuki43zoo
@wilkinsona Thanks for your advice!! We consider to rewrite a recommended style's code as soon as possible.
Comment From: kazuki43zoo
NOTE: Compile the mybatis core module with -parameters, it worked fine.
Comment From: snicoll
@kazuki43zoo thank you so much for testing the snapshot and reporting the issue.
Comment From: wilkinsona
@kazuki43zoo We've refined things in Spring Framework based on your feedback: https://github.com/spring-projects/spring-framework/pull/29531, deferring the removal of LocalVariableTableParameterNameDiscoverer until Framework 6.1. This means that things will work as they did before without -parameters, albeit with a warning being logged each time parameter name discovery relies upon LocalVariableTableParameterNameDiscoverer.