Мне пришлось обновить несколько пакетов для прохождения проверки безопасности белого источника, и теперь, когда обновлены зависимости, пользовательский HttpMessageConverter
, который перехватывал и формировал ответ ранее, больше не работает. Соответствующие обновления зависимостей показаны ниже.
Tomcat-embed-core 8.5.50 -> 9.0.30
Контракт Spring Cloud, выпуск 2.0.1.RELEASE-> 2.0.6.RELEASE
Версия загрузки Spring 2.0.4.RELEASE -> 2.0.6.RELEASE
Jackson-databind 2.9.6 -> 2.10.0.pr1
Jackson-core: 2.10.1 -> 2.10.0. pr1
Вот пользовательский HttpMessageConverter, который работал ранее:
private class JsonApiHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
JsonApiHttpMessageConverter() {
super(MediaType.valueOf(ResponseType.MEDIA_TYPE_JSON_API));
}
@Override
protected boolean supports(final Class<?> clazz) {
return clazz == HttpErrorResponse.class;
}
@Override
protected Object readInternal(final Class<?> clazz, final HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
protected void writeInternal(final Object o, final HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
try (OutputStreamWriter outputStream =
new OutputStreamWriter(outputMessage.getBody(), Charset.defaultCharset())) {
JsonAPIDocument document;
if (o instanceof HttpErrorResponse) {
// Build Error Document
final HttpErrorResponse errorResponse = (HttpErrorResponse) o;
final JsonApiErrorDTO errorDTO = new JsonApiErrorDTO(Integer.toString(errorResponse.getStatus()),
Integer.toString(errorResponse.getCode()), errorResponse.getMessage());
document = new JsonAPIDocument();
document.addError(errorDTO);
} else { // Build JSON API Response Document
final JsonApiDocumentBuilder documentBuilder = new JsonApiDocumentBuilder();
documentBuilder.data(o);
document = documentBuilder.build();
}
outputStream.write(new Gson().toJson(document));
outputStream.flush();
} catch (final InvalidJsonApiObjectException ijaoe) {
LOG.error("Error in converting Object to JsonAPIDocument", ijaoe);
throw new ServiceException(ijaoe);
}
}
}
он определен в классе, который регистрирует конвертеры сообщений, как показано ниже
@Configuration
public class ServiceConfiguration implements WebMvcConfigurer {
...
@Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters) {
converters.add(new JsonApiHttpMessageConverter());
converters.add(new ByteArrayHttpMessageConverter());
converters.add(new StringHttpMessageConverter());
converters.add(new ResourceHttpMessageConverter());
converters.add(new SourceHttpMessageConverter<>());
converters.add(new AllEncompassingFormHttpMessageConverter());
converters.add(new MappingJackson2HttpMessageConverter());
converters.add(new MappingJackson2CborHttpMessageConverter());
converters.add(new Jaxb2RootElementHttpMessageConverter());
}
@Override
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.valueOf(ResponseType.MEDIA_TYPE_JSON_API));
}
}
Это код ответа об ошибке:
@XmlRootElement(name = "error")
@XmlAccessorType(XmlAccessType.FIELD)
@JsonApiType(type = "error")
public class HttpErrorResponse implements Serializable {
private static final long serialVersionUID = 1321088631120274988L;
@XmlTransient
private int status;
@XmlElement(name = "code", required = true)
private int code;
@XmlElement(name = "message", required = true)
@JsonApiAttribute(name = "detail")
private String message;
@JsonApiIgnore
@XmlElement(name = "uuid", required = true)
private String uuid;
public HttpErrorResponse() {
this.uuid = UUID.randomUUID().toString();
}
public HttpErrorResponse(final int status, final int code, final String message) {
this();
this.status = status;
this.code = code;
this.message = message;
}
public int getStatus() {
return status;
}
public void setStatus(final int status) {
this.status = status;
}
public int getCode() {
return code;
}
public void setCode(final int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(final String message) {
this.message = message;
}
public String getUuid() {
return uuid;
}
public void setUuid(final String uuid) {
this.uuid = uuid;
}
}
и объект, по-видимому, является возвращаемым, но конвертер сообщений не преобразует его. Старый формат ответа с работающим конвертером:
"{\"included\":[],\"errors\":[{\"status\":\"400\",\"code\":\"990002\",\"detail\":\"Invalid subscription id: XYZ\"}]}",
, а текущий ответ:
"responseBody": "{\"status\":400,\"code\":990002,\"message\":\"Invalid subscription id: XYZ\",\"uuid\":\"018fe1e3-3936-4c53-8612-61ef778fd811\"}",
Извините, если мой вопрос неясен, пожалуйста, дайте мне знать, если есть все, что я оставляю Я запутался, почему конвертер больше не перехватывает ответ и не обновляет формат. Также вот формат, который должен формировать конвертер:
@JsonPropertyOrder({ "data", "included", "errors" })
@JsonInclude(JsonInclude.Include.NON_NULL)
public class JsonAPIDocument extends AbstractJsonAPIDocument {
@JsonInclude(JsonInclude.Include.NON_NULL)
private IJsonAPIDTO data;
@JsonInclude(JsonInclude.Include.NON_NULL)
public IJsonAPIDTO getData() {
return data;
}
public void setData(IJsonAPIDTO data) {
this.data = data;
}
}
Вот заголовки ответа:
"responseHeaders": {
"X-Origin-Ref": "microservice",
"X-Transaction-Ref": "b2e3d807-0d6f-40e7-90ad-43d5ecb455c2",
"Content-Type": "application/vnd.api+json"
}
и ResponseType.MEDIA_TYPE_JSON_API равен
public static final String MEDIA_TYPE_JSON_API = "application/vnd.api+json"
В качестве отчаянной попытки я изменил метод поддержки класса JsonApiHttpMessageConverter, чтобы он всегда возвращал значение true, и преобразователь все еще не получает ответ