[JAVA] Ce que j'ai fait lors de la migration de la série Spring Boot 1.5 vers la série 2.0

introduction

Nous avons mis à jour SpringBoot 2.0.2. Pour les projets prenant en charge Kotlin dans ici. Ici, je vais écrire sur le travail qui a eu lieu à cette époque.

--Avant la migration

--Après la migration

De plus, étant donné que ce projet fonctionne en tant que serveur pour l'API REST, nous avons pu éviter la migration de Thymeleaf. Je migre un projet Spring MVC séparément, je vais donc écrire à ce sujet séparément.

J'ai principalement fait référence aux sites et articles suivants.

Tout d'abord, mise à niveau de Spring Boot

Modifiez pom.xml pour mettre à niveau la version de Spring Boot.

Extrait des changements

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>

・ ・ ・
      <!-À l'origine, j'utilisais Hikari PC, j'ai donc supprimé la dépendance-->
      <!-- 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>

・ ・ ・

      <!--Supprimer ici après le test->
      <!-- 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>

Évitez d'utiliser le WebMvcConfigurerAdapter de la classe Application

- public class XxxApplication extends WebMvcConfigurerAdapter {
+ public class XxxApplication implements WebMvcConfigurer{

Construire-> Réparer-> Reconstruire

Après avoir défini pom.xml, compilez et répétez la modification.

Erreur de compilation dans findOne du référentiel JPA

Tout d'abord, l'erreur suivante s'est produite.

Error:(41, 41) Kotlin: Type inference failed: fun <S : #{nom de la table}!> 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

Cela est dû à un changement de la méthode Spring Data CRUD. https://spring.io/blog/2017/06/20/a-preview-on-spring-data-kay#improved-naming-for-crud-repository-methods

Modifiez l'erreur sur la première ligne de findOne à findById. L'erreur sur la deuxième ligne est get from ʻOptional car la valeur de retour de findById est Java Optional`.

De même, les arguments pour save et delete ont changé de ceux qui passent List à ceux qui passent ʻEntity, alors appelez les méthodes saveAlletdeleteAllà la place. Bien sûr, si un seul enregistrement est affecté, il est préférable d'utilisersave et delete`, donc consultez le temps disponible pour la migration.

Impossible de résoudre ConfigureRedisAction

Error:(13, 53) java:Organisation du package.springframework.session.data.redis.la configuration n'existe pas

Bien que l'ordre soit dans le désordre, ConfigureRedisAction n'a pas pu être résolu avec la définition suivante définie pour utiliser ElastiCache. C'est parce qu'il a été découpé dans un package appelé 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;
	}

Voir la partie spring-session de pom.xml pour les modifications. De plus, je n'ai pas ajouté la dépendance lettuce car spring-boot-starter-data-redis était à l'origine inclus dans la dépendance.

Obsolète, par exemple org.hibernate.validator.constraints.NotBlank

Conformément à cela, nous l'avons remplacé par quelque chose comme javax.validation.constraints.NotEmpty.

Erreur lors de la configuration automatique de jdbc

Error:(7, 51) java:Impossible de trouver le symbole
symbole:Classe DataSourceBuilder
endroit:Organisation du package.springframework.boot.autoconfigure.jdbc

Cela semblait se produire parce que je travaillais avec plusieurs sources de données.

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
#Autres omis
#Au-dessus de x pour plusieurs sources de données

À l'origine, il était défini comme suit

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);
 	}
 }

Cependant, je l'ai corrigé comme suit. Je pense qu'il y a une meilleure façon de faire cette partie.

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);
 	}
 }

Tomcat commence ici

Bien que Tomcat ait démarré, le journal des erreurs suivant coulait.

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)

Il semble que cela se produise parce que PostgreSQL est également dans la source de données.

Cela a été évité en créant et en plaçant hibernate.properties.

hibernate.properties


hibernate.jdbc.lob.non_contextual_creation = true

Jusqu'à ce point, aucune erreur ne s'est produite au moment du démarrage.

Exception ClassCastException soudaine

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)

Correspondant en convertissant le type d'argument de form de HogeForm au type Nullable deHogeForm?.

Erreur de conversion du type de date

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

J'étais un peu accro à cette partie et la cause n'était pas claire, mais cela fonctionnait en changeant l'objet qui recevait les données de la classe Kotlin Data en une classe Kotlin normale.

Si c'est PUT, la valeur de form ne sera pas transmise

Je n'ai pas eu le temps d'enquêter sur la cause, j'ai donc réécrit la partie PUT en POST ...

Si le type de retour du contrôleur REST est «List », il ne peut pas être converti en JSON et une erreur se produit.

J'ai oublié de prendre le journal des erreurs.

À l'origine une telle mise en œuvre En premier lieu, ne revenez pas avec List ...

    @GetMapping("/hoge")
    public List<Object> hoge() {
        return hogeService.hoges();
    }

Comme le type de retour était assez compliqué, je l'ai fait JSON du côté Controller et l'ai retourné.

    @GetMapping("/hoge")
    public String hoge() throws JsonProcessingException {
        final List<Object> hoges = hogeService.hoges();
        final ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(hoges);
    }

Avec ce qui précède, la migration est terminée et la migration est terminée.

Recommended Posts