I tried my code and I found some errors in the exception handler when you read from InputStream :
Writer writer = new StringWriter(); byte[] buffer = new byte[1024]; //Reader reader2 = new BufferedReader(new InputStreamReader(request.getInputStream())); InputStream reader = request.getInputStream(); int n; while ((n = reader.read(buffer)) != -1) { writer.toString(); } String retval = writer.toString(); retval = "";
I replaced your code with the following:
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream())); String line = ""; StringBuilder stringBuilder = new StringBuilder(); while ( (line=reader.readLine()) != null ) { stringBuilder.append(line).append("\n"); } String retval = stringBuilder.toString();
Then I can read from InputStream in the exception handler, it works! If you still cannot read from InputStream , I suggest you check how your XML POST data is in the request body. You should consider that you can only consume an InputStream once per request, so I suggest you check if there is another call to getInputStream() . If you need to call him two or more times, you should write a custom HttpServletRequestWrapper like this to make a copy of the request body so that you can read it more times.
UPDATE
Your comments helped me reproduce this issue. You are using the @RequestBody annotation, so it is true that you are not calling getInputStream() , but Spring is calling it to retrieve the request body. Take a look at the org.springframework.web.bind.annotation.support.HandlerMethodInvoker class: if you use @RequestBody , this class calls the resolveRequestBody method, etc ... finally, you can no longer read InputStream from your ServletRequest . If you still want to use both @RequestBody and getInputStream() in your own method, you must wrap the request with a custom HttpServletRequestWrapper to make a copy of the request body so you can manually read it more times. This is my cover:
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper { private static final Logger logger = Logger.getLogger(CustomHttpServletRequestWrapper.class); private final String body; public CustomHttpServletRequestWrapper(HttpServletRequest request) { super(request); StringBuilder stringBuilder = new StringBuilder(); BufferedReader bufferedReader = null; try { InputStream inputStream = request.getInputStream(); if (inputStream != null) { bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line = ""; while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line).append("\n"); } } else { stringBuilder.append(""); } } catch (IOException ex) { logger.error("Error reading the request body..."); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ex) { logger.error("Error closing bufferedReader..."); } } } body = stringBuilder.toString(); } @Override public ServletInputStream getInputStream() throws IOException { final StringReader reader = new StringReader(body); ServletInputStream inputStream = new ServletInputStream() { public int read() throws IOException { return reader.read(); } }; return inputStream; } }
Then you should write a simple Filter to wrap the query:
public class MyFilter implements Filter { public void init(FilterConfig fc) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(new CustomHttpServletRequestWrapper((HttpServletRequest)request), response); } public void destroy() { } }
Finally, you need to configure your filter in the web.xml file:
<filter> <filter-name>MyFilter</filter-name> <filter-class>test.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>MyFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
You can only run your filter on the controllers that it really needs, so you should modify the url template to suit your needs.
If you need this function in only one controller, you can also make a copy of the request body in this controller when you receive it using the @RequestBody annotation.