[英]Jersey server JSON response throwing MalformedChunkCodingException: Chunked stream ended unexpectedly
I have a basic java webserver for persisting payment history of users. 我有一个用于保留用户付款历史记录的基本Java Web服务器。 I am trying to write a method to return a list of payments by querying a database, but for some reason the client keeps throwing an exception.
我正在尝试编写一种通过查询数据库来返回付款清单的方法,但是由于某些原因,客户端不断抛出异常。
Here is my resource method for the server: 这是服务器的资源方法:
@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();
}
This produces the following log : 这将产生以下日志:
DEBUG cbspresource.PaymentResource - payment service found 3 payments for user: c832f8c2-f5ff-4e5c-a1b9-7e5a3f26a359
DEBUG cbspresource.PaymentResource-付款服务找到了3个用户付款:c832f8c2-f5ff-4e5c-a1b9-7e5a3f26a359
Therefore the list is definitely populated with the 3 payments the user has made previously. 因此,该列表肯定填充了用户之前进行的3次付款。 I added the list to an XML root element as I thought it may be the cause of the exception:
我将列表添加到XML根元素中,因为我认为这可能是导致异常的原因:
@XmlRootElement
public class PaymentListResponse {
private List<Payment> payments = new ArrayList<Payment>();
public PaymentListResponse(){}
//getter & setter ..
}
Here is my client code: 这是我的客户代码:
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;
This produces the following log: 这将产生以下日志:
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)
I cant figure out why my JSON is causing errors, I have responses from the same Resource being sent back without errors. 我无法弄清楚为什么JSON会导致错误,我收到了来自同一资源的响应,没有错误地被发回。 this happens only when i try to send a populated list.
仅当我尝试发送填充列表时,才会发生这种情况。 If the list is empty the response from the server is
如果列表为空,则服务器的响应为
{"payments":[]}
{“付款”:[]}
Update 更新资料
I used the following code as suggested in the answers: 我按照答案中的建议使用了以下代码:
return Response.ok().entity(response.toArray()).build();
Class annotations are as follows: 类注释如下:
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
with the same exception being thrown. 抛出相同的异常。 For clarity, I have used this type of response before in another part of the server.
为了清楚起见,我之前在服务器的另一部分中使用了这种类型的响应。 The response from that is also a JSON list and is handled by the same client code.
该响应也是一个JSON列表,并由相同的客户端代码处理。
Here is another method which works: 这是另一种有效的方法:
@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();
}
This exception is thrown whenever there is a problem in the header with the HTTP request. 只要HTTP请求的标头中有问题,就会引发此异常。 If I had to guess, your specific problem may be due to the fact that you are sending a list, so the header doesn't end properly.
如果我不得不猜测,您的特定问题可能是由于您正在发送列表而导致的,因此标题没有正确结束。 Try to call the toArray() method of the list to convert it into an array before sending it.
尝试在发送列表之前调用列表的toArray()方法将其转换为数组。
I realised that the Object I was returning, Payment, contained a linked JPA object. 我意识到我要返回的对象Payment包含一个链接的JPA对象。 So my response contained the whole DB object, with all relationships.
因此,我的响应包含整个DB对象以及所有关系。 The client was still receiving data while I attempted to extract the String, therefore the exception was thrown.
当我尝试提取String时,客户端仍在接收数据,因此引发了异常。 I used a different method to extract the String from HttpEntity, here it is:
我使用了另一种方法从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();
}
This allowed me to see the full string. 这使我可以看到完整的字符串。
Also duplicate of this issue: used some code from there link to stackoverflow question 也是该问题的重复:使用了那里的一些代码来链接到stackoverflow问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.