我正在使用gwtp和REST服务,使用ResourceDelegate在客户端和服务器之间共享我的接口。目前一切正常。
现在我想在客户端添加异常处理,在阅读官方文档,carstore样本,SO上的多个帖子之后,我仍然想知道框架做了什么以及留给我什么。< / p>
所以,目前,在服务器端我使用Spring和REST Easy,我的资源如下所示: 界面:
package ***.shared.rest;
@Path("books")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public interface BookResources {
@GET
BookDTO getBook(@PathParam("id") Integer bookId) throws BookKeyDecodingException;
}
实施:
package ***.server.rest;
@Component
@Transactional(readOnly = true)
public class BookResourcesImpl implements BookResources {
@Autowired
private BookService bookService;
@Autowired
private DtoFactory dtoFactory;
@Override
public BookDTO getBook(String bookKey) throws BookKeyDecodingException {
BookDTO bookDTO = BookKeyUtils.decode(supplementKey);
BookModel bookModel = dtoFactory.convertSupplementSuggestionDTO(suggestionDTO);
return bookService.getBook(bookDTO.getId());
}
}
BookKeyDecodingException
位于***。shared.exception包中,并且可序列化。
在客户端,我的演示者将使用我的resourceDelegate:
package ***.client.application.book;
public class BookPresenter {
...
private void fetch() {
clearSlot(SLOT_BOOK);
try {
bookDelegate.withCallback(new AsyncCallback<BookDTO>() {
@Override
public void onFailure(Throwable caught) {
// TODO Auto-generated catch block
**???**
}
@Override
public void onSuccess(BookDTO result) {
for (CahierDTO cahier : result.getPages()) {
...
}
}
}).getBook(bookKey);
} catch (BookKeyDecodingException e) {
**???**
}
}
}
我还在想:
答案 0 :(得分:0)
所以现在我得到了一个解决方案,但我不确定它是最好的解决方案,但我认为这可能有助于某人......
我没有找到任何大魔法(但很多小):
所有这一切都非常复杂,但现在我有一个通用系统与服务器和客户端之间的任何已知和共享异常之王一起工作,我不会这样做。依赖错误代码来获取要显示的内容,仅在异常层次结构上显示。
<强>详情
我的所有异常都在共享包中,可序列化并扩展BookException。
<强> 1。处理异常服务器端。
我使用RestEasy,所以我可以实现和ExceptionMapper:
package ***.server.rest;
@Provider
@Component
public class BookExceptionHandler implements ExceptionMapper<BookException> {
@Override
public Response toResponse(BookException exception) {
return Response.serverError().tag(exception.getClass().getName()).entity(exception).build();
}
}
异常类名称将在专用的标记中找到,因此我可以对其进行反序列化...
<强> 2。处理异常客户端。 3.触发ErrorEvent
我使用RestyGWT,所以我定义了一个通用的MethodCallback:
package ***.client.application.error;
public abstract class ErrorEventDistpacherMethodCallback<DTO> implements MethodCallback<DTO> {
@Inject
static ResourceFailureErrourEventDispatcher dispatcher;
@Override
public void onFailure(Method method, Throwable caught) {
dispatcher.onFailure(method, caught);
}
}
Method对象使我可以访问REST Response的标题和正文。调度程序中的难点:我希望它反序列化异常并触发事件。 好消息:RestyGWT附带了我可以使用的JsonEncoderDecoder接口。因此,我必须针对每个例外进行扩展,并将其与专用标记中的相应类型相关联。
package **.client.exceptions.technical.codecs;
public interface BookKeyDecodingExceptionCodec extends ExceptionCodec<BookKeyDecodingException>, JsonEncoderDecoder<BookKeyDecodingException> {
}
为什么我需要通用ExceptionCodec<BookKeyDecodingException>
?因为我想将它们放在Map<String, ExceptionCodec<?>>
。
public class ResourceFailureErrorEventDispatcher implements HasHandlers {
private static final Logger LOGGER = Logger.getLogger(ErreurEventDistpacherMethodCallback.class.getSimpleName());
private static final String EXCEPTION_CLASS_PARAM_NAME = "ETag";
private Map<String, ExceptionCodec<?>> mapExceptionCodecByClassName = new HashMap<String, ExceptionCodec<?>>();
private EventBus eventBus;
...
public BookException buildException(Method method, Throwable caught) {
String className = method.getResponse().getHeader(EXCEPTION_CLASS_PARAM_NAME);
String json = method.getResponse().getText();
BookException result = null;
if (className == null) {
result = new UnexpectedResourceException((Exception) caught);
LOGGER.severe("Unexpected technical exception :" + result.getMessage());
} else if (mapExceptionCodecByClassName.containsKey(className)) {
result = mapExceptionCodecByClassName.get(className).decode(json);
} else {
result = new MissingExceptionCodecException(className);
}
return result;
}
public void onFailure(Method method, Throwable caught) {
if (caught instanceof RequestTimeoutException) {
ErrorEvent.fire(this, new NetworkException());
} else {
ErrorEvent.fire(this, buildException(method, caught));
}
}
@Override
public void fireEvent(GwtEvent<?> event) {
eventBus.fireEventFromSource(event, this);
}
}
我可以通过注释/生成器来管理编解码器,但就目前而言,我对此很满意。 如果您对此解决方案有任何评论或建议,请不要犹豫,评论/回答!
答案 1 :(得分:0)
我遇到了与GWTP和Restlet相同的问题,并为此创建了自定义解决方案(ClientProxyGenerator);
Receive custom exceptions from Restlet Framework in GWT client