From 7b90887257e4500d9ced1901e98cce65d49936ce Mon Sep 17 00:00:00 2001 From: Lars Vierbergen Date: Tue, 5 Nov 2024 16:22:11 +0100 Subject: [PATCH] Make RepositoryEntityMultipartHttpMessageConverter resolve json HttpMessageConverter when it is being used. In spring-data-rest 4.3.5, the logic has changed and now the entity class is being passed to `canRead()` and `read()` instead of `PersistentEntityResource`. This means that a different converter can be triggered based on which entity is being passed, so we need to select the correct HttpMessageConverter at the point when we know the class that is being read. This also allows users to configure their own specific HttpMessageConverters for their entities. --- ...ryEntityMultipartHttpMessageConverter.java | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/spring-content-rest/src/main/java/org/springframework/data/rest/extensions/entitycontent/RepositoryEntityMultipartHttpMessageConverter.java b/spring-content-rest/src/main/java/org/springframework/data/rest/extensions/entitycontent/RepositoryEntityMultipartHttpMessageConverter.java index 644d38d5d..f3ce8131a 100644 --- a/spring-content-rest/src/main/java/org/springframework/data/rest/extensions/entitycontent/RepositoryEntityMultipartHttpMessageConverter.java +++ b/spring-content-rest/src/main/java/org/springframework/data/rest/extensions/entitycontent/RepositoryEntityMultipartHttpMessageConverter.java @@ -1,13 +1,10 @@ package org.springframework.data.rest.extensions.entitycontent; import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.InvalidPropertyException; -import org.springframework.data.rest.webmvc.PersistentEntityResource; -import org.springframework.hateoas.RepresentationModel; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; @@ -27,24 +24,28 @@ public class RepositoryEntityMultipartHttpMessageConverter implements HttpMessageConverter { - private HttpMessageConverter converter = null; + private final List> converters; public RepositoryEntityMultipartHttpMessageConverter(List> messageConverters) { - for (HttpMessageConverter converter : messageConverters) { - if (converter.canRead(RepresentationModel.class, MediaType.APPLICATION_JSON)) { - this.converter = converter; - break; + this.converters = messageConverters; + } + + private HttpMessageConverter findReadConverter(Class clazz) { + for (HttpMessageConverter converter : converters) { + if(converter.canRead(clazz, MediaType.APPLICATION_JSON)) { + return converter; } } - if (this.converter == null) { - throw new IllegalStateException("unable to resolve persistent entity resource message converter"); - } + return null; } @Override public boolean canRead(Class clazz, MediaType mediaType) { - return PersistentEntityResource.class.equals(clazz) && mediaType != null - && mediaType.includes(MediaType.MULTIPART_FORM_DATA); + if(mediaType == null || !mediaType.includes(MediaType.MULTIPART_FORM_DATA)) { + return false; + } + + return findReadConverter(clazz) != null; } @Override @@ -57,11 +58,6 @@ public List getSupportedMediaTypes() { return Collections.singletonList(MediaType.MULTIPART_FORM_DATA); } - @Override - public List getSupportedMediaTypes(Class clazz) { - return HttpMessageConverter.super.getSupportedMediaTypes(clazz); - } - @Override public Object read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { if (inputMessage instanceof ServletServerHttpRequest == false) { @@ -93,7 +89,12 @@ public Object read(Class clazz, HttpInputMessage inputMessage) throws IOExceptio HttpHeaders headers = new HttpHeaders(inputMessage.getHeaders()); headers.setContentType(MediaType.APPLICATION_JSON); - return this.converter.read(clazz, new HttpInputMessage() { + var converter = findReadConverter(clazz); + if(converter == null) { + throw new HttpMessageNotReadableException("No converter found for reading", inputMessage); + } + + return converter.read(clazz, new HttpInputMessage() { @Override public InputStream getBody() throws IOException { ObjectMapper mapper = new ObjectMapper();