Jersey 服务器 JSON 响应抛出 MalformedChunkCodingException:分块流意外结束
Jersey server JSON response throwing MalformedChunkCodingException: Chunked stream ended unexpectedly
我有一个基本的 java 网络服务器,用于保存用户的付款历史记录。
我正在尝试通过查询数据库为 return 付款列表编写一个方法,但由于某种原因,客户端不断抛出异常。
这是我的服务器资源方法:
@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 - payment service found 3 payments for user: 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 会导致错误,我收到了来自同一资源的响应,没有错误地发回。只有当我尝试发送填充列表时才会发生这种情况。如果列表为空,则服务器的响应为
{"payments":[]}
更新
我按照答案中的建议使用了以下代码:
return Response.ok().entity(response.toArray()).build();
Class注释如下:
@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();
}
只要 HTTP 请求 header 出现问题,就会抛出此异常。如果我不得不猜测,您的具体问题可能是由于您正在发送列表,所以 header 没有正确结束。发送前尝试调用list的toArray()方法将其转化为数组
我意识到我返回的对象 Payment 包含一个链接的 JPA 对象。所以我的响应包含了整个数据库对象,以及所有关系。
当我试图提取字符串时,客户端仍在接收数据,因此抛出了异常。
我使用不同的方法从 HttpEntity 中提取字符串,这里是:
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 Whosebug question
我有一个基本的 java 网络服务器,用于保存用户的付款历史记录。 我正在尝试通过查询数据库为 return 付款列表编写一个方法,但由于某种原因,客户端不断抛出异常。
这是我的服务器资源方法:
@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 - payment service found 3 payments for user: 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 会导致错误,我收到了来自同一资源的响应,没有错误地发回。只有当我尝试发送填充列表时才会发生这种情况。如果列表为空,则服务器的响应为
{"payments":[]}
更新
我按照答案中的建议使用了以下代码:
return Response.ok().entity(response.toArray()).build();
Class注释如下:
@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();
}
只要 HTTP 请求 header 出现问题,就会抛出此异常。如果我不得不猜测,您的具体问题可能是由于您正在发送列表,所以 header 没有正确结束。发送前尝试调用list的toArray()方法将其转化为数组
我意识到我返回的对象 Payment 包含一个链接的 JPA 对象。所以我的响应包含了整个数据库对象,以及所有关系。 当我试图提取字符串时,客户端仍在接收数据,因此抛出了异常。 我使用不同的方法从 HttpEntity 中提取字符串,这里是:
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 Whosebug question