在 GWT 客户端中接收来自 Restlet Framework 的自定义异常

Receive custom exceptions from Restlet Framework in GWT client

我想通过 Restlet Framework 和 GWT 客户端使用异常处理。 Restlet Framework 支持注释异常的概念,如 post;

中所述

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;

    ...
}  

这有效,在异常的情况下调用 returns 代码 409;

并在 GWT 客户端调用 onFailure();

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

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

但是参数 pCaught 只包含状态码为 409 的 ResourceException。 我的 LocationNameException 不包含在底层原因堆栈中。 我需要这个 LocationNameException 来进行适当的错误消息处理。

原因是Restlet GWT ClientProxyGenerator生成的ServerResourceProxy LocationListServerResourceProxyImpl;

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
       {

    ...

}

我想我必须重写 ClientProxyGenerator 中的 Post 方法;

响应数据中存在 LocationNameException,因此 the Basic approach using the getResponseEntity() method of the ClientResource class should be possible

这是要走的路吗?或者我可以按照 Catching annotated exceptions?

的建议在其他地方捕获 LocationNameException 异常

由于生成的代码,很难尝试不同的方法。有没有一种简单的方法可以绕过自定义 类 的代码生成器?

如前所述,响应数据中存在 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;

并在 ClientProxyGenerator 中使用 getExceptionTypes() 或 getGenericExceptionTypes();

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

当然,并非所有 REST 方法都使用自定义异常。当 getExceptionTypes() return 是一个空列表时,我们只是 return 好的旧状态代码;

callback.onFailure(new ResourceException(getClientResource().getStatus()));

在 Jerome Louvel 和 Thierry Boileau 的帮助下,我创建了一个新的 ClientProxyGenerator(),它支持针对 GWT 客户端的自定义异常;

只要在ServerResourceProxy(ClientProxy)接口中指定异常即可

瞧瞧

可以立即在您的项目中使用此自定义 ClientProxyGenerator()。

Download custom ClientProxyGenerator

并将其放在服务器上的一个包中(例如包 com.ludus.server.util)

在 GWT 模块中 XML 将 ClientProxyGenerator 更改为服务器上的新版本;

并且您已准备好使用自定义异常,但如果此扩展能集成到 Restlet 框架中,那就太好了。