@SqsListener(value = "${cloud.aws.sqs.queue.name}", deletionPolicy = SqsMessageDeletionPolicy.NEVER)
public void listen(@Payload SqsMessage message, @Headers Map<String, String> headers, Acknowledgment ack) {
log.info("header ===> {}", headers);
log.info("message ===> {}", message);
ack.acknowledge();
}
@SqsListener 에서 @Payload 값을 SqsMessage 타입으로 받을 때 에러가 발생했다.
org.springframework.messaging.converter.MessageConversionException: Cannot convert from [java.lang.String] to [com.example.sqs.dto.SqsMessage] for GenericMessage
바인딩 받을 객체의 예시
@Getter
@Setter
@ToString
public class SqsMessage {
private String message;
private User user;
@Getter
@Setter
@ToString
public static class User {
private String userId;
private String email;
}
}
PayloadMethodArgumentResolver
에서 @Payload 어노테이션을 resolve 한다.MappingJackson2MessageConverter
이다.MappingJackson2MessageConverter
는 초기값이 세팅될 때 옵션은 다음과 같다.private MappingJackson2MessageConverter getDefaultMappingJackson2MessageConverter() {
MappingJackson2MessageConverter jacksonMessageConverter = new MappingJackson2MessageConverter();
jacksonMessageConverter.setSerializedPayloadClass(String.class);
jacksonMessageConverter.setStrictContentTypeMatch(true);
return jacksonMessageConverter;
}
jacksonMessageConverter.setStrictContentTypeMatch(true)
이다. 이 옵션은 content type을 엄격하게 검사한다.MappingJackson2MessageConverter
는 application/json 타입이 들어왔을 때 컨버팅 한다.public MappingJackson2MessageConverter() {
super(new MimeType("application", "json"));
this.objectMapper = initObjectMapper();
}
MappingJackson2MessageConverter
가 컨버팅 할때 지원가능한 MimeType을 체크하는데 헤더에 Content-Type이 없다.MappingJackson2MessageConverter
가 동작하지 않아서 에러가 발생 했다.MappingJackson2MessageConverter
를 다시 등록해 주었다.@Bean
public MappingJackson2MessageConverter mappingJackson2MessageConverter() {
MappingJackson2MessageConverter jackson2MessageConverter = new MappingJackson2MessageConverter();
jackson2MessageConverter.setStrictContentTypeMatch(false);
return jackson2MessageConverter;
}
일단 @Payload의 resolver를 찾았다.
PayloadMethodArgumentResolver
MappingJackson2MessageConverter
이다. 이 컨버터는 언제 생성이 되어 이 객체에 담길까?SqsConfiguration
가 빈으로 등록될 때 메시지를 처리하는 핸들러를 생성한다.
그때 MappingJackson2MessageConverter
를 등록한다.
MappingJackson2MessageConverter
는 SmartMessageConverter
를 상속받고 있다.
다음 메소드에서 메시지를 해석한다.
여러 컨버터들 중 찾아 실행한다.
컨버팅 가능한지 확인
헤더에서 MimeType을 찾고 해결가능한지 확인한다.
헤더에 MimeType이 지정되지 않을 경우 isStrictContentTypeMatch옵션을 확인한다.
MappingJackson2MessageConverter의 초기 옵션은 true 이므로 해결 불가능하다고 판단 하고 컨버팅을 하지 않아서 에러가 발생한다.
isStrictContentTypeMatch옵션을 false로 바꾸고 실행하여 해결~!