Java 如何在 REST 客户端上捕获异常?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23766789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:06:57  来源:igfitidea点击:

How to capture exceptions on a REST client?

javaweb-servicesrest

提问by Mateus Viccari

i have implemented rest webservices using Jersey, and whenever some exception occur on the server side, the client gets a generic HTTP 500 Internal Server Error, with no more info of the real exception. I found that people usually catch any exception on the server side, then throws a WebApplicationException, but even this way the client keeps getting the generic HTTP 500 Internal Server Error.

我已经使用 Jersey 实现了 rest web 服务,每当服务器端发生一些异常时,客户端都会收到一个通用的 HTTP 500 内部服务器错误,没有更多关于真正异常的信息。我发现人们通常会在服务器端捕获任何异常,然后抛出 WebApplicationException,但即使这样,客户端也会不断收到通用的 HTTP 500 内部服务器错误。

This is my webservice:

这是我的网络服务:

@PUT
@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_XML)
@Path("/transmitir")
public WrapperTransmissaoRetorno receber(WrapperTransmissao wrapperRecepcao) {
    WrapperTransmissaoRetorno retorno = new WrapperTransmissaoRetorno();
    retorno.setCodigoMaster(new Random().nextInt());
    retorno.setDataRetorno(new Date());
    if(true){
        throw new WebApplicationException("Este pau eh bem graudo");
    }
    return retorno;
}

This is the code that calls the client:

这是调用客户端的代码:

try {
    WsTransmissaoCliente client = new WsTransmissaoCliente();
    WrapperTransmissao wrapperRecepcao = new WrapperTransmissao();

    Transferencia transferencia = new Transferencia();
    transferencia.setCodigoTabela(23);
    transferencia.setCodigoTransferencia(56);
    transferencia.setDataRetorno(new Date());
    transferencia.setDataTransmissao(new Date(System.currentTimeMillis()+3000000));
    transferencia.setNomeTabela("CUPOM");
    transferencia.setTipoOperacao(TipoOperacao.UPDATE);
    wrapperRecepcao.setTransferencia(transferencia);

    Jumento jumento = new Jumento();
    jumento.setIdade(24);
    jumento.setNome("José");
    wrapperRecepcao.setObjeto(jumento);
//        Cabrito cabrito = new Cabrito();
//        cabrito.setAltura(56);
//        cabrito.setPeso(120.0);
//        wrapperRecepcao.setObjeto(cabrito);
    WrapperTransmissaoRetorno retorno = client.transmitir(wrapperRecepcao);
    System.out.println("Retorno do WS: "+retorno);
} catch (Exception e) {
    WebApplicationException exx = (WebApplicationException) e;
    exx.printStackTrace();
}

How to avoid this and get the real exception? Or at least the message?

如何避免这种情况并获得真正的例外?或者至少是消息?

UPDATEHere is the object i am sending as a response:

更新这是我作为响应发送的对象:

package br.atualy.integracaocheckout.wrappers;

import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class WrapperTransmissaoRetorno {
    private Date dataRetorno;
    private Integer codigoMaster;

    public Date getDataRetorno() {
        return dataRetorno;
    }

    public void setDataRetorno(Date dataRetorno) {
        this.dataRetorno = dataRetorno;
    }

    public Integer getCodigoMaster() {
        return codigoMaster;
    }

    public void setCodigoMaster(Integer codigoMaster) {
        this.codigoMaster = codigoMaster;
    }

    @Override
    public String toString() {
        return "WrapperRecepcaoRetorno{" + "dataRetorno=" + dataRetorno + ", codigoMaster=" + codigoMaster + '}';
    }
}

UPDATE 2And here is the client:

更新 2这是客户端:

import br.atualy.integracaocheckout.wrappers.WrapperTransmissao;
import br.atualy.integracaocheckout.wrappers.WrapperTransmissaoRetorno;
import javax.ws.rs.ClientErrorException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.WebTarget;

public class WsTransmissaoCliente {
    private final WebTarget webTarget;
    private final Client client;
    private static final String BASE_URI = "http://localhost:8080/IntegracaoCheckout/webresources";

    public WsTransmissaoCliente() {
        client = javax.ws.rs.client.ClientBuilder.newClient();
        webTarget = client.target(BASE_URI).path("transmissao");
    }

//    public String receber() throws ClientErrorException {
//        WebTarget resource = webTarget;
//        resource = resource.path("receber");
//        return resource.request(javax.ws.rs.core.MediaType.APPLICATION_XML).get(String.class);
//    }

    public WrapperTransmissaoRetorno transmitir(WrapperTransmissao requestEntity) throws ClientErrorException {
        return webTarget.path("transmitir")
                .request(javax.ws.rs.core.MediaType.APPLICATION_XML)
                .put(javax.ws.rs.client.Entity.entity(requestEntity, javax.ws.rs.core.MediaType.APPLICATION_XML), WrapperTransmissaoRetorno.class);
    }

    public void close() {
        client.close();
    }

}

采纳答案by Dish

If using jawax.ws.rs.core.Responseobject.

如果使用jawax.ws.rs.core.Response对象。

SERVER ::In case of exception/failure set it as :

SERVER ::在异常/失败的情况下将其设置为:

// do stuff 
// here e.getMessage() can be custom failure message too
response = Response.serverError().entity(e.getMessage()).build();

// return response object
return response;

CLIENT ::On the client side check following :

客户 ::在客户端检查以下内容:

if(response != null && reponse.getStatus() == Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) {
   String serverErrorMsg = response.readEntity(String.class);
   throw new Exception(serverErrorMsg);
}

回答by Raghu Venmarathoor

Use response object in webapplication excemption. It should work.

在 Web 应用程序例外中使用响应对象。它应该工作。

From java docs:

从java文档:

WebApplicationException(String message) Construct a new instance with a blank message and default HTTP status code of 500.

WebApplicationException(String message) 构造一个带有空白消息和默认 HTTP 状态代码 500 的新实例。

Its a blank message. I haven't tried it myself. I guess this is the problem.

它是一条空白消息。我自己没试过。我想这就是问题所在。

https://jersey.java.net/apidocs/2.6/jersey/javax/ws/rs/WebApplicationException.html

https://jersey.java.net/apidocs/2.6/jersey/javax/ws/rs/WebApplicationException.html

回答by azurefrog

Generally it's better to declare your method as returning a Responseobject instead of a user-defined type, and set the data as the entity. Then if you want to indicate that an exception has happened, you can just pass that exception as the entity of the Responseyou are returning.

通常最好将您的方法声明为返回Response对象而不是用户定义的类型,并将数据设置为实体。然后,如果您想表明发生了异常,您可以将该异常作为Response您要返回的实体传递。

e.g.

例如

@GET
@Path("/foo")
public Response getFoo() {
    try {
        // do stuff
        return Response.ok(someData).build();
    } catch (Exception e) {
        return Response.serverError().entity(e).build();
    }
}

You'll notice that this way you don't ever end up actually throwing an exception out of your method, but rather return an explicit 500 response with an exception as the entity. This way you can still throw exceptions out of your code, but they'll be handled nicely.

您会注意到,通过这种方式,您实际上永远不会从您的方法中抛出异常,而是返回显式 500 响应,并将异常作为实体。这样你仍然可以从你的代码中抛出异常,但它们会得到很好的处理。

EDIT

编辑

I'm not sure what your client wrapper code is doing, but you can pass the expected response data type into your call with the normal REST client:

我不确定您的客户端包装器代码在做什么,但是您可以使用普通 REST 客户端将预期的响应数据类型传递到您的调用中:

    Client client = ClientBuilder.newClient();
    WebTarget target = client.target("http://foo.com/foo");
    String response = target.request().get(String.class);

or you can also pull it out of the Responseusing the readEntity()method:

或者您也可以Response使用以下readEntity()方法将其拉出:

    Client client = ClientBuilder.newClient();
    WebTarget target = client.target("http://foo.com/foo");
    Response response = target.request().get();
    String entity = response.readEntity(String.class);

It sounds like what you need to do is check the return code, and then parse the entity as a either a WrapperTransmissaoRetornoor a WebApplicationExceptiondepending on what code was returned:

听起来您需要做的是检查返回代码,然后根据返回的代码将实体解析为 aWrapperTransmissaoRetorno或 a WebApplicationException

    Response response = client.transmitir(wrapperRecepcao);

    if (response.getStatus() == Response.Status.OK.getStatusCode()) { // 200
        WrapperTransmissaoRetorno retorno = response.readEntity(WrapperTransmissaoRetorno.class);
        // do stuff
    } else  if (response.getStatus() == Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) { // 500
        WebApplicationException e = response.readEntity(WebApplicationException.class);
        // do stuff
    } // etc for other response codes

回答by Mateus Viccari

Even after all the suggestions i could not manage to throw the exception to the client. So what i did was to put a String property inside my returning class, so when an exception occurs on the server side, this String will contain the exception message and i can get it on the client.

即使在所有建议之后,我也无法向客户抛出异常。所以我所做的是在我返回的类中放置一个 String 属性,这样当服务器端发生异常时,这个 String 将包含异常消息,我可以在客户端上获取它。