파란하늘의 지식창고
Published 2022. 12. 1. 17:24
Upgrading to Spring Framework 6.x Study/Java
반응형

https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-6.x

이 페이지에서는 Spring Framework 6.0으로 upgrade 하는 방법에 대한 지침을 제공합니다.

Upgrading to Version 6.1

69 revisions 기준으로 작성됨

Baseline upgrades

Spring Framework 6.1은 다음 library를 통해 최소 요구 사항을 높였다:

  • SnakeYAML 2.0
  • Jackson 2.14
  • Kotlin Coroutines 1.7
  • Kotlin Serialization 1.5

Removed APIs

더 이상 사용되지 않는 여러 class, constructor 및 method가 code base 전체에서 제거되었다. 2944930604 참조.

몇 년 동안 공식적으로 또는 사실상 더 이상 사용되지 않는 RPC-style remote가 제거되었다.
이는 Hessian, HTTP Invoker, JMS Invoker 및 JAX-WS 지원에 영향을 미친다. 27422 참조.

Core Container

JDK 20에서 java.net.URL constructor가 더 이상 사용되지 않음에 따라 이제 상대 경로 처리를 포함하여 URL 확인이 URI 를 통해 일관되게 수행된다.
여기에는 전체 URL을 상대 경로로 지정할 때와 같이 흔하지 않은 경우에 대한 동작 변경이 포함된다. 2948128522 참조.

6.1에서 LocalVariableTableParameterNameDiscoverer 가 제거되었다.
StandardReflectionParameterNameDiscoverer 와 호환되도록 하려면 (-debug compiler flag를 사용하는 대신) parameter name 유지를 위해 일반적인 Java 8+ -parameters flag를 사용하여 Java source를 컴파일해야 한다.
Kotlin compiler에서는 -java-parameters flag를 사용하는 것이 좋다.

AutowireCapableBeanFactory.createBean(Class, int, boolean) 는 이제 더 이상 사용되지 않으며, 규칙에 기반한 createBean(Class) 를 선호한다.
후자는 6.1에서도 내부적으로 일관되게 사용된다. – 예, Quartz에서 SpringBeanJobFactory 및 Hibernate에서 SpringBeanContainer .

Array-to-collection 변환은 선언된 대상 Collection type에 대해 Set 이 아닌 List 결과를 선호한다.

application context가 닫히기 시작하면 ThreadPoolTaskExecutorThreadPoolTaskScheduler 가 graceful shutdown phase로 진입한다.
따라서 다른 component에서 callback을 stop 하거나 destroy 하는 동안에는 더 이상 추가 task submission이 허용되지 않는다.
후자가 필요한 경우, shutdown phase가 길어지는 대신 executor/scheduler의 acceptTasksAfterContextClose flag를 true 로 전환해야 한다.

ApplicationContext 를 통해 message 확인(internal MessageSource 에 access)은 context가 활성화되어 있는 동안 허용된다.
context가 닫힌 후 getMessage 를 시도하면 이제 IllegalStateException 이 발생한다.

native image를 build 할 때 사전 계산된 field에 대한 자세한 logging은 기본적으로 제거되었으며, 관련 상세 로그를 표시하려면 native-image compiler build argument로 -Dspring.native.precompute.log=verbose 를 전달하여 복원할 수 있다.

Data Access and Transactions

@TransactionalEventListener 는 동일한 method에서 잘못된 @Transactional 사용을 거부한다: REQUIRES_NEW 로만 허용된다.(@Async 와 함께 사용할 수 있음).

이제 Hibernate Validator 설정이 불완전한 경우 (예: EL provider가 없는 경우) JPA bootstrapping이 실패하므로 이러한 경우를 더 쉽게 디버깅할 수 있다.

HibernateJpaDialect 를 사용하는 경우 JpaTransactionManager 는 가능한 경우 commit/rollback exceptions을 DataAccessException subclass로 변환하므로, 이전에는 generic JpaSystemException 으로 전파되던 Hibernate transaction exception이 이제는 예를 들어 CannotAcquireLockException 으로 표시될 수 있다.
번역할 수 없는 fallback exception의 경우, 이제 commit/rollback에서 전파되던 이전의 TransactionSystemException 대신 JpaSystemException 이 일관되게 발생한다.

Web Applications

Spring MVC와 WebFlux는 이제 @Constraint annotation이 있는 controller method parameter에 대한 method validation을 기본으로 지원한다.
이 기능을 사용하려면 1) controller class level에서 @Validated 를 제거하여 AOP 기반 method validation을 opt out 하고, 2) mvcValidator 또는 webFluxValidator bean이 jakarta.validation.Validator type (예: LocalValidatorFactoryBean ) 인지 확인하고, 3) method parameter에 직접 constraint annotation을 추가해야 한다.
method validation이 필요한 경우 (즉, constraint annotation이 있는 경우) @Valid 가 있는 model attribute 및 request body argument 도 method level에서 validation을 수행하며, 이 경우 argument resolver level에서 더 이상 validation을 수행하지 않으므로 이중 validation 수행을 피할 수 있다.
BindingResult argument는 여전히 존중되지만, 존재하지 않거나 다른 parameter에서 method validation이 실패하면 MethodValidationException 이 발생한다.
아직 6.1 M1에서는 처리되지 않지만 M2에서는 30644와 함께 처리될 예정이다.
M1 지원에 대한 자세한 내용은 29825 를 참조하고, 기타 모든 관련 작업 및 feedback 제공에 대해서는 포괄적인 issue 30645 를 참조.

MethodArgumentNotValidExceptionWebExchangeBindException message argument가 변경되었다.
이제 오류는 작은따옴표와 괄호 없이 ", 및 " 로 연결된다.
Field error는 field name을 추가하는 등의 추가 작업 없이 MessageSource 를 통해 해결된다.
이를 통해 application은 개별 error code를 사용자 지정하여 error 형식을 완벽하게 제어할 수 있다.
30198 및 계획된 문서 개선 30653 참조.

Spring MVC에서 RouterFunctionMapping order를 3 에서 -1 로 변경하여 mapping의 default order를 보다 일관성 있게 개선했다.
즉, 이제 Spring MVC와 Spring WebFlux 모두에서 RouterFunctionMapping 이 항상 RequestMappingHandlerMapping 보다 먼저 정렬된다.
자세한 내용은 30278 참조.

DispatcherHandlerthrowExceptionIfNoHandlerFound property는 이제 기본적으로 true 로 설정되며 더 이상 사용되지 않는다.
resulting exception은 기본적으로 404 error로 처리되므로 동일한 결과를 얻을 수 있다.
마찬가지로, ResourceHttpRequestHandler 는 이제 기본적으로 404로 처리되며 대부분의 application에서 동일한 결과를 가져올 수 있는 NoResourceFoundException 을 발생시킨다.
29491 참조.

@RequestParam, @RequestHeader 및 기타 controller method argument annotation은 이제 input이 text가 없는 non-empty String인 경우 defaultValue를 사용한다.

ResponseBodyEmitter 는 이제 exception이 IOException 이 아닌 경우 response를 complete 한다.
issue 30687 참조.

Preflight check는 이제 HandlerInteceptor chain의 끝이 아닌 시작 지점에 실행된다.

HTTP interface client는 더 이상 blocking signature가 있는 method에 5초의 default timeout을 적용하지 않으며, 대신 기본 HTTP client의 default timeout 및 configuration 설정에 의존한다.
30248 참조.

WebFlux의 HTTP server Observability는 제한적이며 error를 제대로 관찰하지 못했다.
그 결과, WebHttpHandlerBuilder 에서 직접 계측하는 것을 선호하여 WebFlux ServerHttpObservationFilter 는 이제 더 이상 사용되지 않는다.
30013 참조.

ReactorResourceFactory class가 org.springframework.http.client.reactive package에서 org.springframework.http.client package로 이동되었다.

Messaging Applications

RSocket interface client는 더 이상 blocking signature가 있는 method에 대해 5초의 default timeout을 적용하지 않으며, 대신 RSocket client의 default timeout 및 configuration 설정과 RSocket transport에 의존한다.
30248 참조.

Spring Expression Language (SpEL)의 보안 취약점이 Spring application에 악영향을 미칠 가능성을 줄이기 위해 팀은 신뢰할 수 없는 source의 SpEL expression 평가에 대한 지원을 기본적으로 비활성화하기로 결정했다.
core Spring Framework 내에서 이것은 WebSocket messaging의 SpEL 기반 selector header 지원, 특히 DefaultSubscriptionRegistry 에 적용된다.
selector header 지원은 그대로 유지되지만 Spring Framework 6.1부터 명시적으로 사용하도록 설정해야 한다. (30550 참조).
예를 들어 WebSocketMessageBrokerConfigurer 의 custom implementation은 configureMessageBroker() method를 재정의하고 다음과 같이 selector header name을 구성할 수 있다: registry.enableSimpleBroker().setSelectorHeaderName("selector"); .

Upgrading to Version 6.0

27 revision 기준으로 작성됨

Core Container

JSR-330 기반 @Inject annotation은 이제 jakarta.inject 에서 찾을 수 있습니다.
해당 JSR-250 기반 annotation @PostConstruct@PreDestroyjakarta.annotation 에서 찾을 수 있습니다.
당분간 Spring은 pre-compiled binaries의 일반적인 사용을 포함하여 해당 javax 도 계속 감지합니다.

core container는 기본적으로 java.beans.Introspector 없이 basic bean property determination을 수행합니다.
정교한 JavaBeans 사용의 경우 5.3.x와의 완전한 하위 호환성을 위해 META-INF/spring.factories file에 다음 내용을 지정하여 5.3-style 전체 java.beans.Introspector 사용을 가능하게 합니다 :
org.springframework.beans.BeanInfoFactory=org.springframework.beans.ExtendedBeanInfoFactory

당분간 5.3.x에 머무르는 경우 custom META-INF/spring.factories file을 통해 6.0-style property 결정 (및 더 나은 검사 성능!)과의 상위 호환성을 강제 적용할 수 있습니다 :
org.springframework.beans.BeanInfoFactory=org.springframework.beans.SimpleBeanInfoFactory

LocalVariableTableParameterNameDiscoverer 는 이제 더 이상 사용되지 않으며 성공적인 각 해결 시도에 대한 경고를 기록합니다.
(StandardReflectionParameterNameDiscoverer 가 name을 찾지 못한 경우에만 시작됨)
(-debug compiler flag에 의존하는 대신) parameter name 유지를 위해 common Java 8+ -parameters flag를 사용하여 Java source를 compile 하여 해당 경고를 피하거나 영향을 받는 코드의 관리자에게 report 하세요.
Kotlin compiler에서는 완전성을 위해 -java-parameters flag를 사용하는 것이 좋습니다.

LocalValidatorFactoryBean 은 이제 Bean Validation 3.0의 standard parameter name resolution에 의존하며, Kotlin이 사용하는 경우 추가적인 Kotlin reflection을 구성하면 됩니다.
Bean Validation setup에서 parameter names을 참조하는 경우, Java 8+ -parameters flag로 Java sources를 compile 해야 합니다.

ListenableFuture 는 CompletableFuture를 위해 더 이상 사용되지 않습니다. 27780을 참조하세요.

SimpleEvaluationContext 는 이제 일반 constructor resolution에 맞춰 array 할당을 비활성화합니다.

Data Access and Transactions

Jakarta EE migration으로 인해 hibernate-core-jakarta artifact를 사용하여 Hibernate ORM 5.6.x로 upgrade 하고 javax.persistence import를 jakarta.persistence (Jakarta EE 9)로 전환해야 합니다.
또는 Spring Boot 3.0과 함께 제공되는 the Hibernate version인 (jakarta.persistence 에 기반하여 EE 9 및 EE 10과 호환되는) Hibernate ORM 6.1로 즉시 migration 하는 것을 고려해 보십시오.

해당 Hibernate Validator generation은 jakarta.validation (Jakarta EE 9)을 기준으로 7.0.x입니다.
(Jakarta EE 10에 맞춰진) Hibernate Validator 8.0으로 바로 upgrade 할 수도 있습니다.

persistence provider로 선택한 EclipseLink의 경우 참조 버전은 3.0.x (Jakarta EE 9)이며 EclipseLink 4.0은 지원되는 최신 버전 (Jakarta EE 10)입니다.

Spring의 default JDBC exception translator는 이제 JDBC 4 기반 SQLExceptionSubclassTranslator 입니다.
SQLErrorCodeSQLExceptionTranslator 는 여전히 user-provided sql-error-codes.xml file을 사용합니다.
classpath root에 있는 (잠재적으로 비어있는) user-provided file이나 명시적 SQLErrorCodeSQLExceptionTranslator 설정에 의해 trigger 될 때도 Spring의 legacy default error code mapping을 선택할 수 있습니다.

Web Applications

Jakarta EE migration으로 인해 undertow-servlet-jakarta artifact를 사용하여 Tomcat 10, Jetty 11 또는 Undertow 2.2.19로 upgrade 하고 javax.servlet import를 jakarta.servlet (Jakarta EE 9)으로 전환해야 합니다.
최신 server generation의 경우 Tomcat 10.1 및 Undertow 2.3 (Jakarta EE 10)을 고려하십시오.

몇 가지 오래된 Servlet 기반 통합이 중단되었습니다.
예를 들어 Apache Commons FileUpload (org.springframework.web.multipart.commons.CommonsMultipartyResolver ), Apache Tiles 및 FreeMarker JSP는 org.springframework.web.servlet.view 하위 package에서 지원합니다.
multipart file upload 및 일반 FreeMarker template view기 필요한 경우 org.springframework.web.multipart.support.StandardServletMultipartResolver 를 권장하며 REST 지향 web architecture에 일반적으로 초점을 맞춥니다.

Spring MVC 및 Spring WebFlux는 더 이상 type-level @RequestMapping annotation 만을 기반으로 controller를 감지하지 않습니다.
이는 web controller에 대한 interface 기반 AOP proxy가 더 이상 작동하지 않을 수 있음을 의미합니다.
그러한 controller에 대해 class 기반 proxy를 활성화하십시오.
그렇지 않으면 interface에도 @Controller annotation을 달아야 합니다.
22154를 참조하십시오.

HttpMethod 는 이제 class이며 더 이상 enum이 아닙니다.
public API는 유지 관리 되지만 일부 migration이 필요할 수 있습니다.
(예: EnumSet<HttpMethod> 에서 Set<HttpMethod> 로 변경, switch 대신 if else 사용)
이 결정의 근거는 27697을 참조하십시오.

Kotlin extension function WebTestClient.ResponseSpec::expectBodynow 는 Java BodySpec type을 반환하고 더 이상 workaround type KotlinBodySpec 을 사용하지 않습니다.
Spring 6.0은 Kotlin 1.6을 사용하여 이 workaround가 필요한 버그를 수정했습니다. (KT-5464)
이는 consumeWith 를 더 이상 사용할 수 없음을 의미합니다.

RestTemplate , 즉 HttpComponentsClientHttpRequestFactory 에는 Apache HttpClient 5가 필요합니다.

Servlet 5.0 and 6.0 API jar 간 주요 변경 사항으로 인해 Spring에서 제공하는 Servlet mock(MockHttpServletRequest , MockHttpSession )에는 이제 Servlet 6.0이 필요합니다.
Servlet 5.0 기반 code를 테스트하는 데 사용할 수 있지만 test classpath에서 Servlet 6.0 API(또는 그 이상)에 대해 실행해야 합니다.
production code는 여전히 Servlet 5.0에 대해 compile 되고 Servlet 5.0 기반 container와의 통합 테스트를 받을 수 있습니다.
mock 기반 test만 Servlet 6.0 API jar에 대해 실행해야 합니다.

SourceHttpMessageConverter 는 이제 Spring MVC 및 RestTemplate 에서 더 이상 default로 설정되지 않습니다.
결과적으로 javax.xml.transfrom.Source 를 사용하는 Spring web application은 이제 SourceHttpMessageConverter 를 명시적으로 구성해야 합니다.
converter 등록 순서는 중요하며 SourceHttpMessageConverter 는 보통 MappingJackson2HttpMessageConverter 같은 "catch-all" converter 보다 먼저 등록되어야 합니다.

반응형
profile

파란하늘의 지식창고

@Bluesky_

도움이 되었다면 광고를 클릭해주세요