UI를 구현하기 전에 코드 정리를 좀 하고 진행한다. Food 클래스의 유통기한 변수타입을 String에서
Food 클래스부터 수정한다.
Food 클래스의 멤버변수 expiryDate의 타입을 Date로 변경하면서, Getter, Constructor도 변경한다.
DB 스키마 생성 SQL문이 있는
FoodTests 테스트 클래스는 DateFormat 클래스를 이용하기 위한
SimpleDateFormat 은 생성자 파라미터로 format pattern을 "yyyy-MM-dd" 문자열로 전달한다. 문자열로 해당 패턴에 맞게 넘겨서 parse를 호출하면 Date타입으로 파싱한다.
파싱하는 부분은 setUp() 메서드의 milk, cola 객체 할당부분을 참고한다.
createFood 테스트 메서드에서 유통기한 멤버변수의 접근자를 호출하여 Date 타입의 expiryDate 지역변수에 할당하는 부분을 수정했다.
Github에서 소스코드를 확인할 수 있다.
대대적으로 수정이 끝나면 전체 테스트를 수행해서 이상이 없는지 확인한다.
fridge-web 프로젝트에 Application 클래스에
RestTemplate은 HTTP통신에서 boilerplate 코드를 추상화해서 간략하게 서버간 통신을 도와준다.
WebFoodController 클래스는 다음과 같이 RestTemplate 을 사용한다.
Autowired 애너테이션으로 RestTemplate 클래스에 DI 하고, processRegistrationFood 메서드의 리턴 직전에 api 서버를 호출해서 등록하고 있다.
restTemplate의 postForEntity 메서드를 호출하면 첫번째 파라미터로 주어진 URL에 POST 방식으로 통신하며, 두번째 파라미터로 전달한 Object 객체는 requestBody에 담는다. 세번째 파라미터는 ResponseType 클래스타입이다.
리턴타입은 ResponseEntity 이며, 제네릭은 파라미터 세번째로 전달한 FoodCommand ResponseType 이다.
response의 Response HTTP Status 코드가 2xx 대일 경우 flash Attribute 를 추가한다.
응답본문인 FoodCommand를 가져오려면 response의 getBody 메서드를 호출하면 된다.
이전글: 냉장고 가계부 프로젝트 11
다음글: 냉장고 가계부 프로젝트 13
java.util.Date
로 변경하고, 학습용도로 쓰인 Memory, Jdbc 퍼시스턴트 컴포넌트들은 삭제한다. JPA만으로도 충분할 것이라 판단했다.Food 클래스부터 수정한다.
@Temporal(TemporalType.DATE) private Date expiryDate; public Food(String name, int quantity, Date expiryDate) { this.name = name; this.quantity = quantity; this.expiryDate = expiryDate; } public Date getExpiryDate() { return expiryDate; }
Food 클래스의 멤버변수 expiryDate의 타입을 Date로 변경하면서, Getter, Constructor도 변경한다.
@Temporal
애너테이션은 DB의 Date 컬럼 타입과 java.util.Date
타입을 설정하기 위한 애너테이션이다.FoodResource
클래스의 멤버변수 expiryDate의 타입도 Food 클래스와 동일하게 Date로 변경한다.DB 스키마 생성 SQL문이 있는
schema.sql
파일에서 expiry_date 컬럼을 VARCHAR에서 Date 로 변경한다.FoodTests 테스트 클래스는 DateFormat 클래스를 이용하기 위한
java.text.SimpleDateFormat
객체를 선언하고, 테스트 데이터인 Food 인스턴스들을 수정한다. assert 부분에서도 약간의 변화가 있다.private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); private Food milk; private Food cola; @Before public void setUp() throws ParseException { milk = new Food("파스퇴르 우유 1.8L", 1, sdf.parse("2018-09-28")); cola = new Food("코카콜라 500mL", 2, sdf.parse("2018-10-30")); } @Test public void createFood() { String name = milk.getName(); int quantity = milk.getQuantity(); Date expiryDate = milk.getExpiryDate(); assertThat(name, equalTo("파스퇴르 우유 1.8L")); assertThat(quantity, equalTo(1)); assertThat(sdf.format(expiryDate), equalTo("2018-09-28")); assertThat(cola.getName(), equalTo("코카콜라 500mL")); assertThat(cola.getQuantity(), equalTo(2)); assertThat(sdf.format(cola.getExpiryDate()), equalTo("2018-10-30")); }
SimpleDateFormat 은 생성자 파라미터로 format pattern을 "yyyy-MM-dd" 문자열로 전달한다. 문자열로 해당 패턴에 맞게 넘겨서 parse를 호출하면 Date타입으로 파싱한다.
파싱하는 부분은 setUp() 메서드의 milk, cola 객체 할당부분을 참고한다.
createFood 테스트 메서드에서 유통기한 멤버변수의 접근자를 호출하여 Date 타입의 expiryDate 지역변수에 할당하는 부분을 수정했다.
assertThat(sdf.format(expiryDate), equalTo("2018-09-28"));
이런식으로 날짜유형을 문자열로 변환하여 검증하였다.JPAFoodRepositoryTests
테스트 클래스에서도 FoodTests 클래스와 동일하게 expiryDate 부분을 위한 SimpleDateFormat 객체와 Date 타입 변경관련 부분이 수정되었다.FoodControllerTests
테스트 클래스도 마찬가지이다.Github에서 소스코드를 확인할 수 있다.
application.properties
파일에 환경변수를 추가한다. api 서버는 8081 포트로 실행되도록 server.port
프로퍼티를 추가하고, 디버깅을 위한 debug 프로퍼티를 추가한다.server.port=8081 debug=true
대대적으로 수정이 끝나면 전체 테스트를 수행해서 이상이 없는지 확인한다.
fridge-web 프로젝트에 Application 클래스에
org.springframework.web.client.RestTemplate
빈을 등록한다.@Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.build(); }
RestTemplate은 HTTP통신에서 boilerplate 코드를 추상화해서 간략하게 서버간 통신을 도와준다.
WebFoodController 클래스는 다음과 같이 RestTemplate 을 사용한다.
@Autowired private RestTemplate restTemplate; @PostMapping("/add") public String processRegistrationFood(@Valid FoodCommand foodCommand, Errors errors, RedirectAttributes ra) { if(errors.hasErrors()) { return "food/registerFoodForm"; } ResponseEntity<FoodCommand> response = restTemplate.postForEntity("http://localhost:8081/foods", foodCommand, FoodCommand.class); if(response.getStatusCode().is2xxSuccessful()) { ra.addFlashAttribute("registerFoodMessage", "식품을 저장했습니다."); } return "redirect:/web/foods"; }
Autowired 애너테이션으로 RestTemplate 클래스에 DI 하고, processRegistrationFood 메서드의 리턴 직전에 api 서버를 호출해서 등록하고 있다.
restTemplate의 postForEntity 메서드를 호출하면 첫번째 파라미터로 주어진 URL에 POST 방식으로 통신하며, 두번째 파라미터로 전달한 Object 객체는 requestBody에 담는다. 세번째 파라미터는 ResponseType 클래스타입이다.
리턴타입은 ResponseEntity 이며, 제네릭은 파라미터 세번째로 전달한 FoodCommand ResponseType 이다.
response의 Response HTTP Status 코드가 2xx 대일 경우 flash Attribute 를 추가한다.
응답본문인 FoodCommand를 가져오려면 response의 getBody 메서드를 호출하면 된다.
이전글: 냉장고 가계부 프로젝트 11
다음글: 냉장고 가계부 프로젝트 13