Я разрабатываю RESTful API с использованием JAX-RS. Один из его интерфейсов служит для добавления новых сущностей в базу данных; сущности представлены как JSON объектов. Теперь JAX-RS поддерживает десериализацию этих объектов «на лету» перед вызовом метода, обрабатывающего запрос API, что позволяет получить объект фактического класса Java, которому должен быть сопоставлен объект JSON:
@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public City createCity(City city) {
// persist city in some fashion and return it
}
City
имеет атрибут, содержащий его имя. Имя по произвольным причинам не должно быть длиннее 32 символов. Установщик для этого атрибута проверяет это условие и выдает исключение, если условие не выполняется.
public void setName(String name) {
if (name == null || name.length() > 32)
throw new IllegalCityNameException();
// set city name
}
Это исключение, в свою очередь, отображается на ответ через ExceptionMapper
:
@Provider
public class InvalidCityNameExceptionMapper implements ExceptionMapper<InvalidCityNameException> {
@Override
public Response toResponse(final InvalidCityNameException e) {
// create and return appropriate response
}
}
Я бы хотел, чтобы в случае, если объект JSON, предоставленный клиентом, нарушает ограничение длины названия города, выброшенное InvalidCityNameException
обрабатывается InvalidCityNameExceptionMapper
. Это отлично работает, если исключение возникает при создании экземпляра City
«вручную» (например, после получения атрибутов в запросе APPLICATION_FORM_URLENCODED
), но с вышеупомянутым подходом принятия JSON InvalidCityNameException
упаковывается в дальнейшие исключения:
org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage An unexpected error occurred during error handling. No further error processing will occur.
org.apache.cxf.interceptor.Fault
<snip>
Caused by: javax.json.bind.JsonbException
<snip>
Caused by: org.apache.johnzon.mapper.MapperException
<snip>
Caused by: java.lang.reflect.InvocationTargetException
<snip>
Caused by: com.example.City$InvalidCityNameException: City name is too long (max. 32 characters)
<snip>
Я понимаю, почему это происходит (вызов метода через отражение работает так, как он работает), однако я хотел бы знать, есть ли способы обойти это более элегантно, чем явное копирование каждого индивидуальный атрибут из объекта generi c JSON в экземпляр City
.