0

This is my controller code:

@RequestMapping(value = "/test", method = RequestMethod.POST)
    public @ResponseBody String testPost(@RequestParam(value = "testParam") int testParam, HttpServletRequest request) {    
        try {
            System.out.println("body is "+BufferUtil.getHttpRequestBody(request));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

BufferUtil.getHttpRequestBody(request) is

public static String getHttpRequestBody(HttpServletRequest request)
            throws IOException {
        Scanner s = null;
        try {
            s = new Scanner(request.getInputStream(), "UTF-8")
                    .useDelimiter("\\A");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s.hasNext() ? s.next() : "";
    }

This is the code to use to test controller:

 HTTPUtil.sendRequest("http://localhost:8081/es09android/test?testParam=1", "POST", "hello world");

sendRequest() implementation:

public static HttpResponse sendRequest(String url, String method,
                                           String data) {
        DataOutputStream wr = null;
        BufferedReader in = null;
        HttpResponse httpResponse = new HttpResponse();
        try {
            URL obj = new URL(url);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();
            con.setRequestMethod(method);
            con.setRequestProperty("User-Agent", USER_AGENT);
            con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
            con.setDoOutput(true);
            if (data != null) {
                wr = new DataOutputStream(con.getOutputStream());
                wr.write(data.getBytes(UTF8_CHARSET));
            }
            int responseCode = con.getResponseCode();
            httpResponse.setResponseCode(responseCode);
            if (httpResponse.isOk()) {
                in = new BufferedReader(new InputStreamReader(
                        con.getInputStream(), "UTF8"));
                String inputLine;
                StringBuffer response = new StringBuffer();
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                httpResponse.setData(response.toString());
            }
            return httpResponse;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            if (wr != null) {
                try {
                    wr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

If I run it and then send request, controller will not print body. But if remove @RequestParam(value = "testParam") from the controller, everything will be ok. What is wrong?

Tony
  • 3,605
  • 14
  • 52
  • 84
  • Could you elaborate on "controller will not print body"? Do you see a stack trace from your exception handling? Just an empty string? A compilation error? – DaveyDaveDave Dec 10 '15 at 11:07

1 Answers1

0

Edited after more information provided in comments below

I assume what's hapening is that s.hasNext() is returning false, because you're at the end of the request's InputStream. This is as designed, you can only read the InputStream once.

This question has a good example of a way you can cache the request to read it more than once.
This question describes a way you can use Spring to log the entire request, which seems to be what your aim is in your question.

Community
  • 1
  • 1
DaveyDaveDave
  • 9,821
  • 11
  • 64
  • 77
  • I can not see any exception. The output is "body is ". – Tony Dec 10 '15 at 11:22
  • I'm not very familiar with `Scanner`, but I guess it's swallowing the exception. The docs for `Scanner` (https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#Scanner(java.io.InputStream)) say, " If an invocation of the underlying readable's Readable.read(java.nio.CharBuffer) method throws an IOException then the scanner assumes that the end of the input has been reached. The most recent IOException thrown by the underlying readable can be retrieved via the ioException() method." What do you see if you add `System.out.println(s.ioException())? – DaveyDaveDave Dec 10 '15 at 11:27
  • I did it, but still no exception. – Tony Dec 10 '15 at 11:32
  • Sorry - I looked again at your code, I assume it's that `s.hasNext()` is returning `false`, because you're at the end of the request's `InputStream`. This is as designed, you can only read the InputStream once. These two questions might help achieve what you're trying to do: http://stackoverflow.com/questions/28158826/how-to-read-a-servletinputstream-more-than-once-when-you-dont-have-control-of-t and http://stackoverflow.com/questions/32763922/spring-reading-request-body-twice – DaveyDaveDave Dec 10 '15 at 11:39