抛出MalformedChunkCodingException的Jersey服务器JSON响应:Chunked流意外终止

时间:2015-09-28 08:49:59

标签: java json http jersey chunked-encoding

我有一个基本的java网络服务器,用于保存用户的付款历史记录。 我正在尝试编写一种通过查询数据库来返回付款列表的方法,但由于某种原因,客户端不断抛出异常。

这是我的服务器资源方法:

@RolesAllowed({"authenticated","administrator","superadministrator"})
@Path("getPaymentHistory/{userId}")
@GET
public Response getPaymentHistory(@Context SecurityContext sc, @PathParam("userId") String userId){
    PaymentListResponse response = paymentService.getUserPaymentHistory(userId);
    logger.debug("payment service found " +response.getPayments().size()+ " payments for user: " + userId);
    return Response.ok().entity(response).build();
}

这会产生以下日志:

  

DEBUG c.b.s.p.resource.PaymentResource - 支付服务为用户找到3笔付款:c832f8c2-f5ff-4e5c-a1b9-7e5a3f26a359

因此,该列表肯定填充了用户之前所做的3笔付款。我将列表添加到XML根元素中,因为我认为它可能是异常的原因:

@XmlRootElement
public class PaymentListResponse {

    private List<Payment> payments = new ArrayList<Payment>();

    public PaymentListResponse(){}

    //getter & setter .. 
}

这是我的客户代码:

    DefaultHttpClient httpClient = new DefaultHttpClient();
    String responseString = null;
    HttpResponse response;
    try {
        response = httpClient.execute(data);
        HttpEntity entity = response.getEntity();
        responseString = EntityUtils.toString(entity, "UTF-8");
    } catch (HttpException | IOException e) {
        e.printStackTrace();
    }
    return responseString;

这会产生以下日志:

org.apache.http.MalformedChunkCodingException: Chunked stream ended unexpectedly
at org.apache.http.impl.io.ChunkedInputStream.getChunkSize(ChunkedInputStream.java:222)
at org.apache.http.impl.io.ChunkedInputStream.nextChunk(ChunkedInputStream.java:183)
at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:155)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:159)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.Reader.read(Reader.java:140)
at org.apache.http.util.EntityUtils.toString(EntityUtils.java:135)

我无法弄清楚为什么我的JSON会导致错误,我会从同一资源发送回来而没有错误。只有当我尝试发送填充列表时才会发生这种情况。如果列表为空,则服务器的响应为

  

{ “付款”:[]}

更新

我使用了以下代码,如答案所示:

return Response.ok().entity(response.toArray()).build();

类注释如下:

@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})

抛出相同的异常。为清楚起见,我之前在服务器的另一部分中使用过这种类型的响应。该响应也是一个JSON列表,由相同的客户端代码处理。

这是另一种有效的方法:

@RolesAllowed({"administrator","superadministrator"})
@Path("get_all")
@GET
public Response getAccounts(@Context SecurityContext sc) {
    ExternalUser userMakingRequest = (ExternalUser)sc.getUserPrincipal();
    List<Account> accounts = accountService.getAllAccounts(userMakingRequest);
    return Response.ok().entity(accounts).build();
}

2 个答案:

答案 0 :(得分:1)

只要HTTP请求标头出现问题,就会抛出此异常。如果我不得不猜测,您的具体问题可能是由于您发送了一个列表,因此标题没有正确结束。尝试调用列表的toArray()方法,在发送之前将其转换为数组。

答案 1 :(得分:1)

我意识到我返回的Object,Payment,包含一个链接的JPA对象。所以我的回复包含了所有关系的整个数据库对象。 当我尝试提取String时,客户端仍然在接收数据,因此引发了异常。 我使用了一种不同的方法从HttpEntity中提取String,这里是:

public static String sendGetReqForList(HttpGet get){
    DefaultHttpClient httpClient = new DefaultHttpClient();
    StringBuilder  result = new StringBuilder();
    HttpResponse response = null;
    try {
         response = httpClient.execute(get);
    } catch (Exception e) {   
        e.printStackTrace();
    }
    InputStream input = null;
    try {
        input = new BufferedInputStream(response.getEntity().getContent());
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    byte data[] = new byte[40000];
    int currentByteReadCount = 0;
    /** read response from input stream */
    try {
        while ((currentByteReadCount = input.read(data)) != -1) {
            String readData = new String(data, 0, currentByteReadCount);
            result.append(readData);
            if (readData.indexOf("}~{") >= 0) {
                System.out.println("got json obj from data");
            }
        }   
    } catch (IOException e) {
        e.printStackTrace();
    }
    try {
        input.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    /** transform response into JSONArray */
    return result.toString();
}

这让我看到了完整的字符串。

同样重复此问题:从那里使用了一些代码 link to stackoverflow question