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

Java 如何捕获REST客户端上的异常?,java,web-services,rest,Java,Web Services,Rest,我已经使用Jersey实现了restwebservices,每当服务器端发生异常时,客户机就会收到一个通用的htp500内部服务器错误,而没有关于真正异常的更多信息。我发现人们通常会在服务器端捕获任何异常,然后抛出一个WebApplicationException,但即使这样,客户机也会不断收到一般的HTTP 500内部服务器错误 这是我的Web服务: @PUT @Produces(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATIO

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

这是我的Web服务:

@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;
}
这是调用客户端的代码:

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();
}
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();
    }

}
如何避免这种情况并获得真正的异常?或者至少是信息

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

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 + '}';
    }
}
更新2 这是客户:

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();
}
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();
    }

}

在webapplication excemption中使用响应对象。它应该会起作用

来自java文档:

WebApplicationException(字符串消息) 使用一条空白消息和默认HTTP状态代码500构造一个新实例

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


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

e、 g

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

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

    Client client = ClientBuilder.newClient();
    WebTarget target = client.target("http://foo.com/foo");
    String response = target.request().get(String.class);
或者也可以使用
readEntity()
方法将其从
响应中拉出:

    Client client = ClientBuilder.newClient();
    WebTarget target = client.target("http://foo.com/foo");
    Response response = target.request().get();
    String entity = response.readEntity(String.class);
听起来您需要做的是检查返回代码,然后根据返回的代码将实体解析为
WrapperTransmissaoRetorno
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

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

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

服务器::如果出现异常/故障,请将其设置为:

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

// return response object
return response;
客户端::在客户端检查以下内容:

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

好的,但是在客户机上,如果我尝试获取响应实体,它既不会返回异常(发生时),也不会返回实际的方法返回。它只是返回了一个HttpUrlConnector实例…其中的一个部分,我猜错误在服务器端,但可能是WsTransmissaoCliente类的客户端中的部分做错了什么如果您看到的是
HttpUrlConnector
类型的实体,您看到的是原始响应对象,您需要解析它以获得您真正想要的类型。我已经用几种方法更新了答案。别忘了在put中指定实体类型<代码>WebTarget wt=c.target(“http://localhost:8084/simple-服务/webapi/myresource”);响应r=wt.path(“test1”).request().put(Entity.Entity(w,MediaType.APPLICATION_XML))
为其输入所需的编码,否则您可能会收到作为消息正文读取器的异常..我已尝试在服务器上再次返回响应,但现在在客户端,当我尝试使用
Response.readEntity(WebApplicationException.class)读取实体时
,它表示
MessageBodyProviderNotFoundException
-这与返回或参数类中没有
@XmlRootElement
时发生的错误相同。请发布WrapperTransmissaoRetorno的代码,是否已注释?在tomcat中没有任何messagebody编写器异常吗?什么都没有?我已经把包装放在描述中了,请看我关于这个问题的更新。请发布WsTransmissaoCliente的代码。请再看一下更新。应该可以了,看一下@azurefrog的答案