blog-java2ブログエンジンをSpring Boot 1.4.0にアップグレードしてみました。
5件の修正を行ったのでご紹介。
ちなみにリリースノートの拙訳はこちら。
executable jarから起動すると、以下のエラーが発生しました。
2016-07-09 23:31:14,354 [main] WARN o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext(549) - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'loginAction': Unsatisfied dependency expressed through field 'us': Error creating bean with name 'userService':(中略): Is there an unresolvable circular reference?
2016-07-09 23:31:14,409 [main] WARN o.springframework.boot.SpringApplication(91) - Error handling failed (Error creating bean with name 'delegatingApplicationListener' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name (中略)
2016-07-09 23:31:14,467 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter(42) -
***************************
APPLICATION FAILED TO START
***************************
Description:
There is a circular dependency between 3 beans in the application context:
- loginAction (field protected net.afnf.blog.service.UserService net.afnf.blog.web.admin.LoginAction.us)
- userService (field private org.springframework.security.crypto.password.PasswordEncoder net.afnf.blog.service.UserService.passwordEncoder)
- securityConfig
- passwordEncoder
1.4からエラー原因が分かりやすくなっています。Autowire時に循環参照が発生したようです。
変更前のSecurityConfig.javaは以下。
// 変更前
@Override
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
JdbcDaoImpl userDetailsService = new JdbcDaoImpl();
userDetailsService.setDataSource(dataSource);
userDetailsService.setUsersByUsernameQuery
("select username, password, true from users where username = ?");
userDetailsService.setAuthoritiesByUsernameQuery
("select username, role from users where username = ?");
return userDetailsService;
}
@Autowired
public void configureGlobal(
AuthenticationManagerBuilder auth,
UserDetailsService userDetailsService,
PasswordEncoder passwordEncoder) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
ドキュメントを見るとGlobalAuthenticationConfigurerAdapter
を使うのが正解のようなので、以下のように変更しました。
// 変更後
@Configuration
public class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter {
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery
("select username, password, true from users where username = ?")
.authoritiesByUsernameQuery
("select username, role from users where username = ?")
.passwordEncoder(passwordEncoder());
}
}
いくつかのプロパティが変更されたので、これに対応しました。
# 変更前
shell.ssh.enabled=false
spring.datasource.min-idle=1
spring.datasource.initial-size=1
spring.datasource.max-active=2
spring.datasource.max-idle=1
# 変更後
management.shell.ssh.enabled=false
spring.datasource.tomcat.min-idle=1
spring.datasource.tomcat.initial-size=1
spring.datasource.tomcat.max-active=2
spring.datasource.tomcat.max-idle=1
SpringTestBase.javaクラスのアノテーションを以下のように変更しました。
// 変更前
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = BlogJava2App.class)
@WebIntegrationTest
public abstract class SpringTestBase {
// 変更後
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
public abstract class SpringTestBase {
統合テスト時のポート番号を固定したいので、WebEnvironment.DEFINED_PORT
を指定しました。
これまで二重起動は例外メッセージで判定していたのですが、PortInUseException
が返ってくるようになったので修正しました。
// 変更前
try {
return run(clazz, args);
}
catch (Exception e) {
// 二重起動
if ("Unable to start embedded Tomcat servlet container".equals(e.getMessage())) {
(略)
}
else {
throw e;
}
}
// 変更後
try {
return run(clazz, args);
}
// 二重起動
catch (PortInUseException e) {
(略)
}
これは Spring Boot 1.4 とは関係ないのですが、これまで使用していたmybatis-spring
をやめて、mybatis-spring-boot-starter
を使用するようにしました。
@Mapper
とmybatis.type-aliases-package=net.afnf.blog.domain
を導入し、MyBatisConfig.javaを削除しました。
@kazuki43zooさんのQiitaエントリが非常に参考になります。
結構影響がありました。特にexecutable jarになって初めて見つかるパターンの不具合は、対応が面倒ですね。
統合テストも問題なさそうだったので、既にリリース済です。