从GWT客户端的Restlet Framework接收自定义异常

时间:2017-08-04 11:11:23

标签: java gwt exception-handling restlet

我想对Restlet Framework和GWT客户端使用异常处理。 Restlet Framework支持本文所述的带注释异常的概念;

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

在我的项目中,我创建了一个LocationNameException

<!DOCTYPE html>

<html>

	<head>
		<title>A Text Editor Project</title>
		<link rel="stylesheet" type="text/css" href="CSS/style.css">
		<link href="https://fonts.googleapis.com/css?family=Roboto:300,400" rel="stylesheet">
		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet">
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
	</head>
	
	<body>
		
		<div class="text-editor">
			<iframe class="text-field" id="text-field" src="about:blank" contenteditable="true">
			
			</iframe>
		</div>
	
	</body>

</html>

并在我的ServerResource中使用它;

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

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

使用界面

   @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;
    }

这是有效的,如果是异常,则调用返回代码409;

enter image description here

在GWT客户端,onFailure()被调用;

public interface LocationListServerResourceInt
{
    ...

    @Post
    LocationDto postLocation(LocationDto pLocationDto) throws LocationNameException;

    ...
}  

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

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

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

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

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

enter image description here

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

这是要走的路吗?或者我可以按照Catching annotated exceptions建议的其他地方捕获LocationNameException异常吗?

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

2 个答案:

答案 0 :(得分:0)

如前所述,ResponseNameException存在于Response数据中。 因此,我们可以像普通实体一样获得它;

...

       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()返回一个空列表时,我们只返回旧的状态代码;

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

答案 1 :(得分:0)

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

enter image description here

只需在ServerResourceProxy(ClientProxy)

中指定接口的异常即可

enter image description here

和voilà

enter image description here

enter image description here

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

Download custom ClientProxyGenerator

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

enter image description here

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

enter image description here

您已准备好使用自定义异常,但如果将此扩展程序集成到Restlet框架中会很好。