3. 그레이들 멀티프로젝트 - RestTemplate
[배경]
앞서 구현한 두개의 어플리케이션 간의 호출이 일어나게 하자.
1. RestController 만들기
weather-application내에 비가 오는 확율을 계산해주는 ForecastController를 만든다.
package com.example.monorepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(value = "/weather")
public class ForecastController {
@Autowired
ForecastService forecastService;
@GetMapping(value = "/forecast/{days}")
public List<Double> forecast(@PathVariable int days) {
return forecastService.predict(days);
}
}
Autowired로 주입받는 ForecastService는 다음과 같다;
package com.example.monorepo;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class ForecastService {
public List<Double> predict(int days) {
List<Double> rainProbabilityList = new ArrayList<>();
for (int i = 1; i <= days; i++) {
if (i == 5) {
rainProbabilityList.add(1.0);
} else if (i % 2 == 0) {
rainProbabilityList.add(0.5);
} else{
rainProbabilityList.add(0.1);
}
}
return rainProbabilityList;
}
}
오늘부터 5일 후의 비가 올 확율이 100%, 오늘부터 짝수만큼의 날들은 비올 확율 50%, 그 외엔 10%라고 임시 설정.
2. RestController 동작 확인
WeatherApplication을 구동시킨다.
http://localhost:8081/weather/forecast/7
[
0.1,
0.5,
0.1,
0.5,
1,
0.5,
0.1
]
3. 어플리케이션간의 호출
main-application의 MainController에서 weather-application의 ForecastController호출해보자.
RestTemplate을 이용한다.
앞으로 1주일의 야외수업 여부를 알아보는 api endpoint 이다.
임의의 임계치인 0.4보다 같거나 높은 비 올 확률이면, 야외수업을 가지 않고, 0.4보다 낮으면 야외수업을 간다고 알려준다.
main-application에 PlanService를 만든다.
package com.example.monorepo;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Service
public class PlanService {
public List<Boolean> canGoOutsideForWeek(double threshold) {
RestTemplate restTemplate = new RestTemplate();
// create headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// send POST request
String url = "http://localhost:8081/weather/forecast/7";
ResponseEntity<Object[]> response = restTemplate.getForEntity(url, Object[].class);
ArrayList<Double> body = new ArrayList(Arrays.asList(response.getBody()));
ArrayList<Boolean> yesno = new ArrayList<>();
for (Double d : body) {
if (d < threshold) {
yesno.add(true);
} else {
yesno.add(false);
}
}
return yesno;
}
}
RestTemplate call에 대한 자세한 내용은 이전 글(https://2ndprince.tistory.com/12) 참고
MainController에도 PlanService를 주입받고, endpoint 하나를 더 추가했다.
package com.example.monorepo;
import com.example.monorepo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping(value = "/main")
public class MainController {
@Autowired
PlanService planService;
@GetMapping(value = "/demo")
public User demo(){
User myUser = new User();
myUser.setAge(10);
myUser.setName("2nd prince");
myUser.setId("1");
return myUser;
}
@GetMapping("/weekly")
public String makeWeeklyPlan(){
List<Boolean> booleans = planService.canGoOutsideForWeek(0.4);
return booleans.toString();
}
}
http://localhost:8080/main/weekly를 get으로 실행해본다.
[true, false, true, false, false, false, true]
WeatherApplication을 호출하여 받은 비올 확율 값을 이용하여 야외수업을 나갈지 여부를 결정해주는 endpoint를 만들었다.
Client Request -> MainController -> PlanService -> ForestController -> ForecastService -> ForecastController -> PlanService -> MainController -> Client Response 의 흐름이다.
소스코드
https://github.com/2ndPrince/monorepo/tree/monorepo_restTemplate
[TroubleShooting]
1. restTemplate call으로 List<Double>을 받아온다. Object[].class으로 하였다. type safe하지 못한 좋지 않은 방법인데, 이것을 해결하려면 ParameterizedTypeReference 을 사용하면 되지만, Double에 막혀서 못 구현했다.