SpringBoot

[에러해결] HttpMediaTypeNotAcceptableException: Could not find acceptable representation

강잇 2022. 9. 4. 21:40

발생

서비스 계층과 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

https://stackoverflow.com/questions/28466207/could-not-find-acceptable-representation-using-spring-boot-starter-web

 

"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