0

2 つの RESTful API があります。1 つは内部用で、もう 1 つは公開用で、2 つは異なる jar によって実装されています。パブリック API は、次の手順を実行して内部 API をラップします。

  1. いくつかの作業を行います
  2. 内部 API を呼び出す
  3. いくつかの作業を行います
  4. ユーザーに応答を返す

2 つの 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));
    }
  }
}

問題は、2 つの jar が同じ Java プロセスで実行される場合、内部 API からスローされた例外が内部 API の JAX-RS 例外マッパーにルーティングされないことです。例外はパブリック API まで伝播し、に変換されます。内部サーバー エラー (500)。

つまり、私はそれを間違っています。したがって、私の質問は、クライアントとサーバーの両方が同じ Java プロセスで実行される可能性があるという制約を考慮して、パブリック API 実装内から内部 RESTful API を呼び出すにはどうすればよいかということです。

確かに他にも問題はありますが、今述べた問題を修正することで他の問題も修正される気がします。

4

1 に答える 1

0

この問題は、内部 JAR とパブリック JAR の両方が同じ JVM にあるという事実とは何の関係もありません。WebResource.put()これらは、新しい HTTP セッションを作成するメソッドによって完全に分離されています。そのため、内部 API の例外はパブリック API に伝播しません。

パブリック API の内部サーバー エラーは、内部 API の出力を解釈する後処理メカニズムが原因で発生し、何らかの理由でクラッシュします。内部 API を責めないでください。完全に分離されており、問題を引き起こすことはありません (同じ JVM 内にあっても)。

于 2013-03-09T08:09:33.387 に答える