(관련 글)
이전 글과 같은 WebFlux 코드를 완성하고
baseUrl 관련해 .yml 파일로 관리하기 위해 변수에 넣어 주었다.
1
2
3
4
5
@Value("${url.server1}")
private String baseUrl1;
@Value("${url.server2}")
private String baseUrl2;
그리고 실행을 하니 baseUrl 이 지정한 빌더에 들어가지 않는 문제가 발생하였다.
.yml 에 지정한 값을 불러오지 못한 것으로 보인다.
1
2
this.webClient1 = webClientBuilder.clientConnector(new ReactorClientHttpConnector(httpClient)).baseUrl(baseUrl1).build();
this.webClient2 = webClientBuilder.clientConnector(new ReactorClientHttpConnector(httpClient)).baseUrl(baseUrl2).build();
컨피그 파일의 생성자부분에서 실행되고 있는 이 코드는
프로젝트가 시작되기도 전, 디비가 연결되기도 전에 실행되는 것을 로그로 확인하였다.
@Configuration 애플리케이션이 시작될 때 설정 파일로서 작동하여
.yml 파일에서 지정한 변수를 가지고 오기도 전에 이미 baseUrl 설정 부분이 작동이 끝나
baseUrl 이 null 이 들어가는 문제이다.
환경변수나 직접 값을 넣어 실행했을 때는 문제가 없이 잘 작동하였으나 .yml 에 넣었더니 이런문제가 발생하였다.
어쩔 수 없이 또한번 코드를 수정한다.
같은 파일의 생성자 부분이 아닌 api 호출부분에서 직접 baseUrl를 넣어주는 것으로 수정한다.
이 부분은 메소드 실행시 실행되는 부분으로 .yml 설정한 값을 잘 불러오고 있는 것도 로그로 확인하였다.
분리했던 생성자부분의 webClientBuilder 에서 baseUrl를 설정하지 않기로 결정했으니 분리할 필요가 없어졌다.
이부분을 다시 하나로 만들어주고
1
2
3
4
this.webClient = webClientBuilder
.clientConnector(new ReactorClientHttpConnector(httpClient))
// .baseUrl(baseUrl) // 해당 코드 제거
.build();
baseUrl(baseUrl1).build()
baseUrl(baseUrl2).build()
이런 방식으로 직접 넣어주도록 코드를 수정한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
return webClient.mutate().baseUrl(baseUrl1).build() // baseUrl 설정 추가
.post()
.uri(uriBuilder -> {
URI uri = uriBuilder.path("/task.do").build();
log.info("[{}] Sending POST request to URL: {}", "Task-Server-Connection", uri);
return uri;
})
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(bodyBuilder.build())) // 멀티파트 데이터를 요청데이터에 추가
.retrieve()
.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
.onErrorResume(throwable -> {
// 서버1로 요청시 통신 중 오류가 발생했을 땐 exception 을 던지지 않고, 같은 과정으로 서버2로 요청을 재시도 한다.
log.error(SERVER1_CONNECTION_ERROR.getErrorCode() + " :: "+ SERVER1_CONNECTION_ERROR.getErrorMsg());
return webClient.mutate().baseUrl(baseUrl1).build() // baseUrl 설정 추가
.post()
.uri(uriBuilder -> {
URI uri = uriBuilder.path("/task.do").build();
log.info("[{}] Sending POST request to URL: {}", "Task-Server-Connection", uri);
return uri;
})
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(bodyBuilder.build()))
.retrieve()
.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
.transform(this::handleServerErrors); // 2server: 서버2로 재요청도 실패했을 경우의 에러 처리 로직
})
.doOnSuccess(map -> {handleDoOnSuccess(value, map);}) // 통신 성공 후: 성공시 처리되는 로직
.doOnError(ApiClient::handleDoOnError) // 통신 성공 후: 통신은 성공했으나 처리중의 오류 처리 로직
.then();