如何实现Restlet JAX-RS处理程序,它是RESTful API的瘦代理,可能在同一个java进程中实现?

时间:2013-03-08 22:56:57

标签: jax-rs restlet

我们有两个RESTful API - 一个是内部的,另一个是公共的,两个是由不同的jar实现的。公共API类型包装内部API,执行以下步骤:

  1. 做一些工作
  2. 调用内部API
  3. 做一些工作
  4. 将回复返回给用户
  5. 两个jar可能会在同一个Java进程中运行(但不一定)。

    我们正在使用带有JAX-RS扩展的Restlet。

    以下是一个简单的公共API实现示例,它只是转发到内部API:

    @PUT
    @Path("abc")
    public MyResult method1(@Context UriInfo uriInfo, InputStream body) throws Exception {
      String url = uriInfo.getAbsolutePath().toString().replace("/api/", "/internalapi/");
      RestletClientResponse<MyResult> reply = WebClient.put(url, body, MyResult.class);
      RestletUtils.addResponseHeaders(reply.responseHeaders);
      return reply.returnObject;
    }
    

    WebClient.put的位置:

    public class WebClient {
      public static <T> RestletClientResponse<T> put(String url, Object body, Class<T> returnType) throws Exception {
        Response restletResponse = Response.getCurrent();
        ClientResource resource = new ClientResource(url);
        Representation reply = null;
        try {
          Client timeoutClient = new Client(Protocol.HTTP);
          timeoutClient.setConnectTimeout(30000);
          resource.setNext(timeoutClient);
    
          reply = resource.put(body, MediaType.APPLICATION_JSON);
          T result = new JacksonConverter().toObject(new JacksonRepresentation<T>(reply, returnType), returnType, resource);
    
          Status status = resource.getStatus();
          return new RestletClientResponse<T>(result, (Form)resource.getResponseAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS), status);
        } finally {
          if (reply != null) {
            reply.release();
          }
          resource.release();
          Response.setCurrent(restletResponse);
        }
      }
    }
    

    RestletClientResponse<T>是:

    public class RestletClientResponse<T> {
      public T returnObject = null;
      public Form responseHeaders = null;
      public Status status = null;
    
      public RestletClientResponse(T returnObject, Form responseHeaders, Status status) {
        this.returnObject = returnObject;
        this.responseHeaders = responseHeaders;
        this.status = status;
      }
    }
    

    RestletUtils.addResponseHeaders是:

    public class RestletUtils {
      public static void addResponseHeader(String key, Object value) {
        Form responseHeaders = (Form)org.restlet.Response.getCurrent().getAttributes().get(HeaderConstants.ATTRIBUTE_HEADERS);
        if (responseHeaders == null) {
          responseHeaders = new Form();
          org.restlet.Response.getCurrent().getAttributes().put(HeaderConstants.ATTRIBUTE_HEADERS, responseHeaders);
        }
        responseHeaders.add(key, value.toString());
      }
    
      public static void addResponseHeaders(Form responseHeaders) {
        for (String headerKey : responseHeaders.getNames()) {
          RestletUtils.addResponseHeader(headerKey, responseHeaders.getValues(headerKey));
        }
      }
    }
    

    问题是如果两个jar在同一个Java进程中运行,那么从内部API抛出的异常不会路由到内部API的JAX-RS异常映射器 - 异常会传播到公共API和被转换为内部服务器错误(500)。

    这意味着我做错了。所以,我的问题是如何在公共API实现中调用内部RESTful API,因为客户端和服务器都可以在同一个Java进程中运行。

    当然,还有其他问题,但我觉得修复我刚才描述的问题也会解决其他问题。

1 个答案:

答案 0 :(得分:0)

问题与内部JAR和公共JAR都在同一个JVM中的事实无关。它们由WebResource.put()方法完美分隔,后者创建了一个新的HTTP会话。因此,内部API中的异常不会传播到公共API。

公共API中的内部服务器错误是由后处理机制引起的,后者解释内部API的输出并因某些原因而崩溃。不要责怪内部API,它是完全隔离的,不会造成任何麻烦(即使它在同一个JVM中)。