발생
서비스 계층과 API 계층 연동 복습을 진행하며 계층 분리를 위해 mapstruct를 이용해 mapper를 구현하고, mapper에 필요한 Dto 클래스들을 구현하여 포스트맨으로 테스트를 진행했는데 다음과 같은 에러를 만났다.
Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
Controller 클래스의 일부 코드(Post 요청에서 에러가 발생하여 Post 메서드 관련)
import com.example.spring.coffee.dto.CoffeePatchDto;
import com.example.spring.coffee.dto.CoffeePostDto;
import com.example.spring.coffee.dto.CoffeeResponseDto;
import com.example.spring.coffee.entity.Coffee;
import com.example.spring.coffee.mapper.CoffeeMapper;
import com.example.spring.coffee.service.CoffeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.Positive;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/coffees")
@Validated
public class CoffeeController {
CoffeeService coffeeService;
CoffeeMapper mapper;
@Autowired
public CoffeeController(CoffeeService coffeeService, CoffeeMapper mapper) {
this.coffeeService = coffeeService;
this.mapper = mapper;
}
@PostMapping
public ResponseEntity postCoffee(@Valid @RequestBody CoffeePostDto coffeePostDto) {
Coffee coffee = mapper.coffeePostDtoToCoffee(coffeePostDto);
Coffee response = coffeeService.createCoffee(coffee);
return new ResponseEntity(mapper.coffeeToCoffeeResponseDto(response), HttpStatus.CREATED);
}
Mapper 클래스
import com.example.spring.coffee.dto.CoffeePatchDto;
import com.example.spring.coffee.dto.CoffeePostDto;
import com.example.spring.coffee.dto.CoffeeResponseDto;
import com.example.spring.coffee.entity.Coffee;
import org.mapstruct.Mapper;
@Mapper(componentModel = "spring")
public interface CoffeeMapper {
public Coffee coffeePostDtoToCoffee(CoffeePostDto coffeePostDto);
public Coffee coffeePatchDtoToCoffee(CoffeePatchDto coffeePatchDto);
public CoffeeResponseDto coffeeToCoffeeResponseDto(Coffee coffee);
}
mapstruct를 이용한 mapper 구현 코드 (postCoffee() 메서드 관련 코드)
@Component
public class CoffeeMapperImpl implements CoffeeMapper {
public CoffeeMapperImpl() {
}
public Coffee coffeePostDtoToCoffee(CoffeePostDto coffeePostDto) {
if (coffeePostDto == null) {
return null;
} else {
String korName = null;
String engName = null;
int price = false;
korName = coffeePostDto.getKorName();
engName = coffeePostDto.getEngName();
int price = coffeePostDto.getPrice();
Coffee coffee = new Coffee(korName, engName, price);
return coffee;
}
}
public CoffeeResponseDto coffeeToCoffeeResponseDto(Coffee coffee) {
if (coffee == null) {
return null;
} else {
CoffeeResponseDto coffeeResponseDto = new CoffeeResponseDto();
return coffeeResponseDto;
}
}
}
CoffeePatchDto 클래스
import com.example.spring.validator.NotSpace;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Range;
import javax.validation.constraints.Pattern;
@Getter
@Setter
public class CoffeePatchDto {
private long coffeeId;
@NotSpace
private String korName;
@Pattern(regexp = "^([a-zA-Z]+\\s?[a-zA-Z])+$")
private String engName;
// @Max(value = 50000)
// @Min(value = 100)
@Range(min = 100, max = 50000)
private int price;
}
CoffeeResponseDto 클래스
public class CoffeeResponseDto {
private long coffeeId;
private String korName;
private String engName;
private int price;
}
원인
HttpMediaTypeNotAcceptableException 예외는 클라이언트가 요청한 것과 실제로 생성할 수 있는 것이 다를 경우 발생한다고 한다.
즉, 핸들러 메소드가 클라이언트가 요청한 Type으로 응답으로 내려줄 수 없는 것이 원인이였다.
바로 mapper를 구현한 클래스를 먼저 확인했다.(변환 과정에서 문제가 있나 생각이 들어서..)
coffeeToCoffeeResponseDto 메소드의 코드가 변환을 아예 못하고 있었고, CoffeeResponseDto 클래스를 확인하니 Getter가 없는 것을 확인할 수 있었다.
해결
에러 해결을 위해 @Getter과 @AllArgsConstructor 애너테이션을 추가하여 해결하였다.
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CoffeeResponseDto {
private long coffeeId;
private String korName;
private String engName;
private int price;
}
Reference
"Could not find acceptable representation" using spring-boot-starter-web
I am trying to use spring-boot-starter-web to create a rest service serving up JSON representations of Java objects. From what I understand this boot-starter-web jar is supposed to handle the conve...
stackoverflow.com
https://memo-the-day.tistory.com/199
Spring MVC의 HttpMediaTypeNotAcceptableException
1. 개요 이 빠른 기사에서는 HttpMediaTypeNotAcceptableException 예외를 살펴 보고이 예외가 발생할 수있는 경우를 이해합니다. 2. 문제 Spring과 API 엔드 포인트를 구현할 때, 우리는 일반적으로 소비 / 생
memo-the-day.tistory.com
'SpringBoot' 카테고리의 다른 글
[SpringBoot] AWS S3 파일(이미지) 업로드 및 삭제하기 구현 (0) | 2022.11.28 |
---|---|
[SpringBoot] MockMvc - multipart() POST외 다른 HTTPMethod 사용하기 (0) | 2022.11.26 |
[TroubleShooting] SpringBoot Controller Test - MockMvc 302 Found, 403 Forbidden (0) | 2022.11.24 |
[SpringDataJPA] 쿼리메서드 참조 객체의 필드 사용 (0) | 2022.11.17 |
[Trouble Shooting] MaxUploadSizeExceededException (0) | 2022.11.03 |