簡體   English   中英

如何在REST客戶端上捕獲異常?

[英]How to capture exceptions on a REST client?

我已經使用Jersey實現了其余的web服務,並且每當服務器端發生一些異常時,客戶端就會獲得通用的HTTP 500內部服務器錯誤,而不再有真正異常的信息。 我發現人們通常在服務器端捕獲任何異常,然后拋出WebApplicationException,但即使這樣,客戶端仍然會獲得通用HTTP 500內部服務器錯誤。

這是我的網絡服務:

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

如何避免這種情況並獲得真正的例外? 或者至少是消息?

更新這是我作為回復發送的對象:

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這是客戶:

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

}

通常,最好將方法聲明為返回Response對象而不是用戶定義的類型,並將數據設置為實體。 然后,如果要指示發生了異常,則可以將該異常作為要返回的Response的實體傳遞。

例如

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

您會注意到,這樣您實際上不會從您的方法中拋出異常,而是返回顯式500響應,並將異常作為實體。 這樣你仍然可以從你的代碼中拋出異常,但它們將得到很好的處理。

編輯

我不確定您的客戶端包裝器代碼在做什么,但您可以使用正常的REST客戶端將預期的響應數據類型傳遞到您的調用中:

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

或者你也可以使用readEntity()方法將它從Response拉出來:

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

聽起來你需要做的是檢查返回代碼,然后根據返回的代碼將實體解析為WrapperTransmissaoRetornoWebApplicationException

    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

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

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 ::在客戶端檢查以下內容:

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

在webapplication excemption中使用響應對象。 它應該工作。

來自java文檔:

WebApplicationException(String message)使用空白消息和默認HTTP狀態代碼500構造新實例。

這是一個空白的消息。 我自己沒試過。 我想這就是問題所在。

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

即使在所有建議之后我也無法將異常拋給客戶端。 所以我所做的是將一個String屬性放在我的返回類中,所以當服務器端發生異常時,這個String將包含異常消息,我可以在客戶端上獲取它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM