Получение пользовательских исключений из Restlet Framework в клиенте GWT

Я хочу использовать обработку исключений с клиентами Restlet Framework и GWT. Restlet Framework поддерживает концепцию аннотированных исключений, как описано в этом посте;

http://restlet.com/company/blog/2015/12/21/exception-handling-with-restlet-framework/

В моем проекте я создал LocationNameException

@Status(value = 409)
public class LocationNameException extends Exception
{
    ...

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public LocationNameException(String pMessage, Throwable pCause)
    {
        super(pMessage, pCause);
    }
}

И используйте это в моем ServerResource;

   @Override
    @Transactional(rollbackOn = LocationNameException.class)
    public LocationDto postLocation(LocationDto pLocationDto) throws LocationNameException
    {
        ...

        Location lLocation = new Location(pLocationDto);

        try
        {
            LocationDao lLocationDao = getLocationDao();
            lLocationDao.persist(lLocation);
        }
        catch (PersistenceException pPersistenceException)
        {
            throw new LocationNameException("Location requires unique Name", pPersistenceException);
        }

        ...

        return lLocationDto;
    }

С интерфейсом

public interface LocationListServerResourceInt
{
    ...

    @Post
    LocationDto postLocation(LocationDto pLocationDto) throws LocationNameException;

    ...
}  

Это работает, в случае исключения вызов возвращает код 409;

введите здесь описание изображения

И на стороне клиента GWT вызывается onFailure();

private class PostLocationCallback implements AsyncCallback<LocationDto>
{
    ...

    @Override
    public void onFailure(Throwable pCaught)
    {
        mCallback.onFailure(pCaught, mLocationDto);
    }
}

Но параметр pCaught содержит только ResourceException с кодом состояния 409. Мое LocationNameException не включено в основной стек причин. Мне нужно это LocationNameException для соответствующей обработки сообщений об ошибках.

Причиной является сгенерированный ServerResourceProxy LocationListServerResourceProxyImpl с помощью Restlet GWT ClientProxyGenerator;

public void postLocation(LocationDto param1, final LocationDto> callback)
{       
    ...

    public void handle(Request request, Response response)
    {
       if (getClientResource().getStatus().isError())
       {       
          callback.onFailure(new ResourceException(getClientResource().getStatus()));
       }
       else
       {

    ...

}

Я думаю, что мне нужно переписать метод Post в ClientProxyGenerator;

введите здесь описание изображения

Исключение LocationNameException присутствует в данных ответа, поэтому Базовый подход с использованием метода getResponseEntity() класса ClientResource должен быть возможен.

Это путь? Или я могу перехватить исключение LocationNameException в другом месте, как это было предложено Перехват аннотированных исключений?

Очень сложно попробовать другой подход из-за сгенерированного кода. Есть ли простой способ обойти генератор кода с помощью пользовательских классов?


person Roland Beuker    schedule 04.08.2017    source источник
comment
Вокруг этого вопроса по-прежнему неловко тихо... Жив ли еще Restlet/GWT? Кто-нибудь когда-нибудь использовал исключения сервера в клиентах GWT с Restlet?   -  person Roland Beuker    schedule 07.08.2017
comment
Привет, Роланд, поддержка аннотированных исключений в Restlet/GWT еще не разработана, но это должно быть технически осуществимо. Как вы думаете, вы могли бы внести свой вклад? Рад поддержать вас в этом процессе.   -  person Jerome Louvel    schedule 08.08.2017
comment
Привет, Джером, да, я думаю, что могу внести свой вклад. Проблема заключается не в аннотированном исключении (я могу просто использовать описанный базовый подход), а в ClientProxyGenerator (таким образом, компилятор GWT...). Я попытался использовать сгенерированный исходный код в своем проекте, но возникли проблемы с ServerResourceProxy_TypeSerializer... У вас есть рабочий/компилируемый пример ServerResourceProxyImpl/ServerResourceProxy_TypeSerializer, с которым я могу поиграть?   -  person Roland Beuker    schedule 08.08.2017


Ответы (2)


Как уже упоминалось, LocationNameException присутствует в данных ответа. Поэтому мы можем получить его, как обычное существо;

...

       public void handle(Request request, Response response)
        {
            if (getClientResource().getStatus().isError())
            {
                LocationNameException lLocationNameException = null;
                boolean serializationError = false;

                try
                {
                    if (response.isEntityAvailable())
                    {
                        if (MediaType.APPLICATION_JAVA_OBJECT_GWT.equals(response.getEntity().getMediaType()))
                        {
                            lLocationNameException = new ObjectRepresentation<LocationNameException>(
                                    response.getEntity().getText(),
                                    (SerializationStreamFactory) MyLocationListServerResourceProxyImpl.this, false)
                                    .getObject();
                        }
                        else
                        {
                            throw new IOException("Can't parse the enclosed LocationNameException.");
                        }
                    }
                }
                catch (Throwable e)
                {
                    serializationError = true;
                    callback.onFailure(new ResourceException(e));
                }

                if (!serializationError)
                {
                    callback.onFailure(lLocationNameException);
                }
            }
            else
            {

...

Генератору ClientProxyGenerator необходимо знать тип исключения (в данном случае LocationNameException). Поэтому мы указываем исключение в интерфейсе ClientProxy;

    @Post
    void postLocation(LocationDto pLocationDto, AsyncCallback<LocationDto> pResult) throws LocationNameException;

И используйте getExceptionTypes() или getGenericExceptionTypes() в ClientProxyGenerator;

    Class<?>[] exceptionTypes = method.getExceptionTypes();
    java.lang.reflect.Type[] genericExceptionTypes = method.getGenericExceptionTypes();

Конечно, не все методы REST используют пользовательское исключение. Когда getExceptionTypes() возвращает пустой список, мы просто возвращаем старый добрый код состояния;

callback.onFailure(new ResourceException(getClientResource().getStatus()));
person Roland Beuker    schedule 09.08.2017

С помощью Jerome Louvel и Thierry Boileau я создал новый ClientProxyGenerator(), который поддерживает пользовательские исключения для клиента GWT;

введите здесь описание изображения

Просто укажите исключение из интерфейса в ServerResourceProxy (ClientProxy)

введите здесь описание изображения

и вуаля

введите здесь описание изображения

введите здесь описание изображения

Вы можете сразу же использовать этот пользовательский ClientProxyGenerator() в своем проекте.

Загрузить собственный ClientProxyGenerator

И поместите его в пакет на сервере (например пакет com.ludus.server.util)

введите здесь описание изображения

В XML модуля GWT измените ClientProxyGenerator на новую версию на сервере;

введите здесь описание изображения

И вы готовы использовать свои собственные исключения, но было бы неплохо, если бы это расширение было интегрировано в структуру Restlet.

person Roland Beuker    schedule 10.11.2017