2011-12-15 32 views
14

Tôi có mã này, nơi tôi đọc đầu vào từ luồng đầu vào yêu cầu và sử dụng JacksonMapper để chuyển đổi thành POJO. Của nó đang chạy trong một container 7 container với hỗ trợ guice.Tại sao luồng nhập liệu HttpServletRequest trống?

@Override 
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 

    try { 
     RequestType requestType = mapper.readValue(req.getInputStream(), RequestType.class); 
    } Catch(Exception ex) { 
     .... 
    } 
} 

Tuy nhiên, đôi khi tải ngoại lệ sau đây được ném. Tôi đã kiểm tra khách hàng của tôi và tôi chắc chắn nó gửi một chuỗi json hợp lệ. Chuyện gì vậy? Có phải hành vi mong đợi cho Jetty 7 đang được tải không?

java.io.EOFException: No content to map to Object due to end of input 
    at org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:2433) 
    at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2385) 
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1637) 
    at com.ea.wsop.user.LoginServlet.processRequest(LoginServlet.java:69) 
    at com.ea.wsop.user.LoginServlet.doPost(LoginServlet.java:63) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.CGLIB$doPost$0(<generated>) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd$$FastClassByGuice$$c6f479ee.invoke(<generated>) 
    at com.google.inject.internal.cglib.proxy.$MethodProxy.invokeSuper(MethodProxy.java:228) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.ea.monitor.MethodExecutionTimer.invoke(MethodExecutionTimer.java:130) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:52) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.doPost(<generated>) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.CGLIB$service$8(<generated>) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd$$FastClassByGuice$$c6f479ee.invoke(<generated>) 
    at com.google.inject.internal.cglib.proxy.$MethodProxy.invokeSuper(MethodProxy.java:228) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.ea.monitor.MethodExecutionTimer.invoke(MethodExecutionTimer.java:130) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:52) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.service(<generated>) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.CGLIB$service$9(<generated>) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd$$FastClassByGuice$$c6f479ee.invoke(<generated>) 
    at com.google.inject.internal.cglib.proxy.$MethodProxy.invokeSuper(MethodProxy.java:228) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.ea.monitor.MethodExecutionTimer.invoke(MethodExecutionTimer.java:130) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:52) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.service(<generated>) 
    at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:263) 

Trả lời

12

Nó sẽ trống nếu đã được sử dụng trước đó. Điều này sẽ được thực hiện hoàn toàn bất cứ khi nào bạn gọi getParameter(), getParameterValues(), getParameterMap(), getReader(), v.v ... trên HttpServletRequest. Hãy chắc chắn rằng bạn không gọi bất kỳ loại phương pháp nào mà bản thân họ cần thu thập thông tin từ cơ quan yêu cầu trước khi gọi số getInputStream(). Nếu servlet của bạn không làm điều đó, hãy bắt đầu kiểm tra các bộ lọc servlet được ánh xạ trên cùng một mẫu URL.


Cập nhật: này có vẻ là GAE 1.5 cụ thể. Xem thêm

Tôi sợ rằng không có giải pháp/cách giải quyết cho đến khi họ nhận được nó cố định. Bạn có thể thử để kiểm tra xem nó có sẵn trong một Filter và nếu có, sau đó sao chép và lưu trữ dưới dạng thuộc tính yêu cầu. Nhưng điều này có thể ảnh hưởng đến việc xử lý thêm bởi một số servlet GAE.

+0

Không có gì trong mã của tôi tiêu thụ nó, nhưng Guice có thể đang làm điều gì đó dưới mui xe. –

+0

Bạn có thể * thử * để sử dụng 'getQueryString()' thay vào đó, tôi chỉ không chắc chắn GAE hoạt động như thế nào trên chuỗi truy vấn "cú pháp không hợp lệ". – BalusC

+0

Yêu cầu đăng bài của nó và tôi đang kéo dữ liệu từ đó. –

6

Tôi gặp sự cố khi yêu cầu InputStream của tôi luôn trống rỗng với Jetty 6.1.15 và phát hiện ra rằng nguyên nhân là do tiêu đề "Loại nội dung" bị thiếu hoặc sai.

Tôi tạo các yêu cầu trong một chương trình Java khác bằng HttpUrlConnection. Khi tôi không đặt tiêu đề Kiểu nội dung một cách rõ ràng, thì InputStream được trả về bởi request.getInputStream() trong chương trình nhận luôn luôn trống. Khi tôi đặt loại nội dung thành "nhị phân/octet-stream", yêu cầu InputStream của yêu cầu chứa dữ liệu chính xác.

Phương thức duy nhất được gọi trên đối tượng yêu cầu trước getInputStream()getContentLength().

0

Tôi đã sử dụng mod_jk 1.2.39 có lỗi gây ra sự cố này. Sau khi cập nhật lên 1.2.40, nó bắt đầu hoạt động.

10

Tôi gặp sự cố tương tự khi chạy ứng dụng Khởi động mùa xuân. Ứng dụng Spring Boot của tôi là một đơn giản Dispatcher servlet đọc cơ thể yêu cầu và xử lý nó.

Trong trường hợp của tôi, khách hàng (curl) thiết lập một tiêu đề content-type của application/x-www-form-urlencoded nếu dòng lệnh curl sử dụng -d {some-data} và không thiết lập một tiêu đề content-type cụ thể qua -Hcontent-type=some-other-media-type.

Bên trong động cơ servlet Apache Catalina rằng mùa xuân Boot chạy, lớp Request khiến cho xét nghiệm sau đây trong parseParameters()

 if (!("application/x-www-form-urlencoded".equals(contentType))) { 
      success = true; 
      return; 
     } 

Đối content-type giá trị khác, Request lợi nhuận ở đây, thực hiện.

Tuy nhiên, nếu kiểu nội dung trậnapplication/x-www-form-urlencoded, Request tiếp tục:

try { 
     if (readPostBody(formData, len) != len) {   
      parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE); 
      return; 
     } 
    } catch (....) 

mà sẽ tiêu thụ cơ thể. Vì vậy, trong trường hợp của tôi, mặc dù servlet của tôi không có gì khác ngoài gọi request.getInputStream() và cố gắng read() từ nó, nó đã quá muộn - thời gian chạy Request đã đọc đầu vào và không đệm hoặc chưa đọc nó. Cách giải quyết duy nhất là đặt Content-Type khác nhau.

Thủ phạm chính là OrderedHiddenHttpMethodFilter(HiddenHttpMethodFilter).doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) dòng 70

mà là tìm kiếm các thông số "_method" truy vấn.

tôi đã có thể vô hiệu hóa bộ lọc bằng cách thêm

@Bean 
public FilterRegistrationBean registration(HiddenHttpMethodFilter filter) { 
    FilterRegistrationBean registration = new FilterRegistrationBean(filter); 
    registration.setEnabled(false); 
    return registration; 
} 

(được sử dụng để giải quyết another problem)

+1

Đây là một khám phá tuyệt vời, hoặc bằng cách khác, HttpServletRequest trong Trình xử lý bài viết của bộ điều khiển luôn trả về rỗng mà không có lý do. –

+0

Đây là một trong những khó khăn, 2 giờ cố gắng tìm hiểu lý do tại sao bài thực tế là trống rỗng. Cảm ơn rất nhiều! – emerino

0

Tôi đã có vấn đề này với một bài đăng. Tôi đã giải quyết nó bằng cách FIRST đọc inputstream và đặt nó vào cache, trước khi đọc các tham số. Điều đó dường như làm các thủ thuật

Các vấn đề liên quan