Here has updated to SpringBoot 2.0.2. For projects that support Kotlin. Here, I will write about the work that occurred at that time.
--Before migration
--After migration
Also, since this project is running as a REST API server, we were able to avoid Thymeleaf migrations. I'm migrating a Spring MVC project separately, so I'll write about that separately.
We will modify pom.xml
to upgrade the Spring Boot version.
Excerpt of changes
pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
- <version>1.5.8.RELEASE</version>
+ <version>2.0.2.RELEASE</version>
<relativePath />
</parent>
・ ・ ・
<dependency>
<!-- https://docs.spring.io/spring-session/docs/current/reference/html5/guides/java-redis.html -->
<groupId>org.springframework.session</groupId>
- <artifactId>spring-session</artifactId>
+ <artifactId>spring-session-data-redis</artifactId>
</dependency>
・ ・ ・
<!-- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#jackson--json-support -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-json</artifactId>
+ </dependency>
・ ・ ・
<!-Originally I was using Hikari PC, so I deleted the dependency-->
<!-- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#configuring-a-datasource -->
- <dependency>
- <groupId>com.zaxxer</groupId>
- <artifactId>HikariCP</artifactId>
- </dependency>
・ ・ ・
<!--Delete here after testing->
<!-- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.0-Migration-Guide#before-you-start -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-properties-migrator</artifactId>
+ <scope>runtime</scope>
+ </dependency>
- public class XxxApplication extends WebMvcConfigurerAdapter {
+ public class XxxApplication implements WebMvcConfigurer{
After setting pom.xml
, build and repeat the modification.
First of all, the following error occurred.
Error:(41, 41) Kotlin: Type inference failed: fun <S : #{table name}!> findOne(p0: Example<S!>!): Optional<S!>!
cannot be applied to
(Long)
Error:(41, 49) Kotlin: Type mismatch: inferred type is Long but Example<(???..???)>! was expected
This is due to a change in the Spring Data CRUD method. https://spring.io/blog/2017/06/20/a-preview-on-spring-data-kay#improved-naming-for-crud-repository-methods
Change the error on the first line from findOne
to findById
.
The error on the second line is get
from ʻOptional because the return value of
findByIdis
Java Optional`.
Similarly, the arguments for save
and delete
have changed from those that pass List
to those that pass ʻEntity, so call the
saveAlland
deleteAllmethods instead. Of course, if only one record is affected, it is better to use
save and
delete`, so consult with the time available for migration.
Error:(13, 53) java:Package org.springframework.session.data.redis.config does not exist
Although the order is out of order, ConfigureRedisAction
could not be resolved by the following definition set to use ElastiCache.
This is because it was cut out into a package called spring-session-data-redis
.
https://docs.spring.io/spring-session/docs/current/reference/html5/guides/java-redis.html
@Bean
public static ConfigureRedisAction configureRedisAction() {
return ConfigureRedisAction.NO_OP;
}
See the spring-session
part of pom.xml
for the modifications.
Also, I didn't add the lettuce
dependency because spring-boot-starter-data-redis
was originally included in the dependency.
In line with this, we have replaced it with javax.validation.constraints.NotEmpty
and so on.
Error:(7, 51) java:Can't find symbol
symbol:Class DataSourceBuilder
place:Package org.springframework.boot.autoconfigure.jdbc
This seemed to happen because I was working with multiple data sources.
application.properties
hoge.datasource.driver-class-name = com.mysql.jdbc.Driver
hoge.datasource.url = jdbc:mysql://127.0.0.1:33306/hoge
hoge.datasource.username = hoge
hoge.datasource.password = fuga
#Others omitted
#Above x for multiple data sources
Originally it was set as follows
HogeDatabaseConfig.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "hogeEntityManagerFactory", transactionManagerRef = "hogeTransactionManager", basePackages = {
"jp.xxx.data.hoge.repository" })
public class HogeDatabaseConfig extends AbstractDatabaseConfig {
@Bean(name = "hogeDataSource")
@ConfigurationProperties(prefix = "hoge.datasource")
public DataSource hogeDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "hogeEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean hogeEntityManagerFactory(EntityManagerFactoryBuilder builder,
return builder.dataSource(hogeDataSource)
.packages("jp.xxx.data.hoge.entity").persistenceUnit("hoge")
.properties(buildProperties()).build();
}
@Bean(name = "hogeTransactionManager")
public PlatformTransactionManager hogeTransactionManager(
@Qualifier("hogeEntityManagerFactory") EntityManagerFactory hogeEntityManagerFactory) {
return new JpaTransactionManager(hogeEntityManagerFactory);
}
}
However, I fixed it as follows. I think there is a better way to do this part.
HogeDatabaseConfig.java
@Configuration
@ConfigurationProperties(prefix = "hoge.datasource")
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "hogeEntityManagerFactory", transactionManagerRef = "hogeTransactionManager", basePackages = {
"jp.xxx.data.hoge.repository" })
public class HogeDatabaseConfig extends AbstractDatabaseConfig {
@Autowired
private Environment env;
@Bean(name = "hogeDataSource")
public DataSource hogeDataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("hoge.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("hoge.datasource.url"));
dataSource.setUsername(env.getProperty("hoge.datasource.username"));
dataSource.setPassword(env.getProperty("hoge.datasource.password"));
return dataSource;
}
@Bean(name = "hogeEntityManagerFactory")
public EntityManagerFactory hogeEntityManagerFactory(
@Qualifier("hogeDataSource") DataSource hogeDataSource) {
final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(hogeDataSource);
factoryBean.setPersistenceUnitName("hoge");
factoryBean.setPackagesToScan("jp.xxx.data.hoge.entity");
factoryBean.setJpaPropertyMap(buildProperties());
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.afterPropertiesSet();
return factoryBean.getNativeEntityManagerFactory();
}
@Bean(name = "hogeTransactionManager")
public PlatformTransactionManager hogeTransactionManager(
@Qualifier("hogeEntityManagerFactory") EntityManagerFactory hogeEntityManagerFactory) {
return new JpaTransactionManager(hogeEntityManagerFactory);
}
}
Although Tomcat started, the following error log was flowing.
java.lang.ClassCastException: jp.xxx.service.HogeService$Fuga cannot be cast to org.springframework.core.io.support.ResourceRegion
at org.springframework.http.converter.ResourceRegionHttpMessageConverter.writeResourceRegionCollection(ResourceRegionHttpMessageConverter.java:182)
at org.springframework.http.converter.ResourceRegionHttpMessageConverter.writeInternal(ResourceRegionHttpMessageConverter.java:139)
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:102)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:272)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:180)
at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:119)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
It seems that it is occurring because PostgreSQL is also in the data source.
This was avoided by creating and placing hibernate.properties
.
hibernate.properties
hibernate.jdbc.lob.non_contextual_creation = true
Up to this point, no error has occurred by the time of startup.
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method jp.xxx.controller.HogeController.createFuga, parameter form
at jp.xxx.controller.HogeController.createCampaign(HogeController.kt)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
The argument type of form
was converted from HogeForm
to the nullable type of HogeForm?
.
Failed to convert value of type 'java.lang.String[]' to required type 'java.util.Date'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2018-06-11T00:00:00'; nested exception is java.lang.IllegalArgumentException
I was a little addicted to this part, but I didn't understand the cause, but it worked by changing the object that received the data from the Kotlin Data class to a normal Kotlin class.
I didn't have time to investigate the cause, so I rewrote the PUT part to POST ...
List <Object>
, it cannot be converted to JSON and an error will occur.I forgot to take the error log.
Originally such an implementation In the first place, do not return with List
@GetMapping("/hoge")
public List<Object> hoge() {
return hogeService.hoges();
}
Since the return type was quite complicated, I made it JSON on the Controller side and returned it.
@GetMapping("/hoge")
public String hoge() throws JsonProcessingException {
final List<Object> hoges = hogeService.hoges();
final ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(hoges);
}
With the above, the migration is completed and the migration is completed.
Recommended Posts