Я пытаюсь реализовать конечную точку PATCH с JAX-RS в модуле Liferay OSGi. Конечные точки GET , POST и PUT работают нормально, но я застрял с конечной точкой PATCH . Поскольку я не знаю ничего лучшего, я пытаюсь использовать пример реализации Даана Ширена.
Мои (упрощенные) реализации, начиная с контроллера:
@Path("/resources")
public class ResourceController {
@PATCH
@Path("/{resourceId}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
Response patchResource(@PathParam("resourceId") long resourceId, ObjectPatch objectPatch) {
// Get the resource
Resource resource = getResource(resourceId);
// Apply the patch
objectPatch.apply(resource);
// Return the resource
return Response.ok(resource).build();
}
}
Итак, мне нужен интерфейс ObjectPatch
, который я сделал точно так же, как в примере с Daan:
public interface ObjectPatch {
<T> T apply(T target) throws ObjectPatchException;
}
Следующий шаг - реализация MessageBodyReader:
@Provider
public class PartialJsonObjectPatchReader implements MessageBodyReader<ObjectPatch> {
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return ObjectPatch.class == type && MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType);
}
@Override
public ObjectPatch readFrom(Class<ObjectPatch> type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException {
JsonNode patch = OBJECT_MAPPER.readTree(entityStream);
return new PartialJsonObjectPatch(OBJECT_MAPPER, patch);
}
}
. Отличие от примера реализации заключается в том, что я добавил аннотацию @Provider
. Насколько я понял, это автоматически регистрирует реализацию MessageBodyReader во время выполнения JAX-RS, как это описано здесь и здесь . Из последнего:
Класс, желающий предоставить такой сервис, реализует интерфейс MessageBodyReader и может быть аннотирован @Provider для автоматического обнаружения c.
Я просто создается впечатление, что этого автоматического c обнаружения не происходит.
Последний важный класс - это реализация интерфейса ObjectPatch
:
public class PartialJsonObjectPatch implements ObjectPatch {
private final ObjectMapper objectMapper;
private final JsonNode patch;
public PartialJsonObjectPatch(ObjectMapper objectMapper, JsonNode patch) {
this.objectMapper = objectMapper;
this.patch = patch;
}
@Override
public <T> T apply(T target) throws ObjectPatchException {
ObjectReader reader = objectMapper.readerForUpdating(target);
try {
return reader.readValue(patch);
} catch (IOException e) {
throw new ObjectPatchException(e);
}
}
}
Если я сейчас сделаю PATCH запрос к конечной точке, он выдает мне следующее сообщение об ошибке:
com.faster xml .jackson.databind.ex c .InvalidDefinitionException: Невозможно создать экземпляр com.example.ObjectPatch
(никаких создателей, как конструкция по умолчанию, не существует): абстрактные типы либо должны быть сопоставлены с конкретными типами, либо иметь собственный десериализатор, либо содержать дополнительную информацию о типах
Я как бы понимаю сообщение об ошибке как интерфейс не может быть создан, но я не понимаю, почему я получаю это сообщение. Не следует ли попытаться создать экземпляр PartialJsonObjectPatch
вместо ObjectPatch
? Если я изменю класс параметров метода patchResource()
на PartialJsonObjectPatch
(чего я не должен), я получу это сообщение об ошибке:
com.faster xml .jackson.databind. ex c .InvalidDefinitionException: Невозможно создать экземпляр com.example.PartialJsonObjectPatch
(не существует создателей, как конструкция по умолчанию): невозможно десериализовать из значения объекта (без создателя на основе делегатов или свойств)
The сообщения об ошибках приводят меня к this , но добавление конструктора по умолчанию не помогает.
Чего мне не хватает?