Question

running an xml-rcp server and client. trying to log the requests to the server. But get Premature end of file error. Can anyone see what I am doing wrong?

 public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException

 ServletInputStream sis = req.getInputStream();
 int len = req.getContentLength();
 byte[] bytes = new byte[len]; 

 int offset = 0;  
 int numRead = 0;  
 while ((offset < bytes.length) && (numRead=sis.read(bytes, offset, bytes.length-offset)) >= 0) {  
       offset += numRead;  
   }  

   if (offset < bytes.length) {  
       throw new IOException("Could not complete reading request body");  
   }  

   sis.close();  

   FileOutputStream f = new FileOutputStream(new File("C:\\Users\\test\\file.log"), true);
   f.write(bytes);  
   f.flush();
   f.close();

   super.doPost(req, res);
 }

[Fatal Error] :1:1: Premature end of file.

redstone.xmlrpc.XmlRpcException: A problem occured during parsing at redstone.xmlrpc.XmlRpcParser.parse(Unknown Source) at redstone.xmlrpc.XmlRpcDispatcher.dispatch(Unknown Source) at redstone.xmlrpc.XmlRpcServer.execute(Unknown Source) at redstone.xmlrpc.XmlRpcServlet.doPost(Unknown Source) at com.devices.test.servlet.MyXmlRpcServlet.doPost(MyXmlRpcServlet.java:93) at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:565) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:479) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1031) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:406) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:965) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111) at org.eclipse.jetty.server.Server.handle(Server.java:349) at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:452) at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:894) at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:948) at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:857) at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235) at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77) at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:609) at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:45) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534) at java.lang.Thread.run(Thread.java:722) Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Premature end of file at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1236) ... 26 more

solution:

 import javax.servlet.ServletException;
 import javax.servlet.ServletInputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;

 public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
 {
 CustomHttpServletRequestWrapper wrapper = new CustomHttpServletRequestWrapper((HttpServletRequest) req);

 ServletInputStream sis = wrapper.getInputStream();
 String StringFromInputStream = IOUtils.toString(sis, "UTF-8");
 LOG.info( "request:");
 LOG.info( StringFromInputStream );
 super.doPost(wrapper, res);
 }


 public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper
 {

  private final String body;
  private final Logger LOG = LoggerFactory.getLogger( CustomHttpServletRequestWrapper.class );

  public CustomHttpServletRequestWrapper( final HttpServletRequest request )
  {
     super( request );

     final StringBuilder stringBuilder = new StringBuilder();
     BufferedReader bufferedReader = null;

     try
     {
        final InputStream inputStream = request.getInputStream();

        if (inputStream != null)
        {
           bufferedReader = new BufferedReader( new InputStreamReader( inputStream ) );

           final char[] charBuffer = new char[128];
           int bytesRead = -1;

           while (( bytesRead = bufferedReader.read( charBuffer ) ) > 0)
           {
              stringBuilder.append( charBuffer, 0, bytesRead );
           }
        }
        else
        {
           stringBuilder.append( "" );
        }
     }
     catch (final IOException ex)
     {
        LOG.error( "Error reading the request body..." );
     }
     finally
     {
        if (bufferedReader != null)
        {
           try
           {
              bufferedReader.close();
           }
           catch (final IOException ex)
           {
              LOG.error( "Error closing bufferedReader..." );
           }
        }
     }

     body = stringBuilder.toString();
     LOG.info( "body:" );
     LOG.info( body );
  }

  @Override
  public ServletInputStream getInputStream() throws IOException
  {
     final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( body.getBytes() );

     final ServletInputStream inputStream = new ServletInputStream()
     {
        @Override
        public int read() throws IOException
        {
           return byteArrayInputStream.read();
        }
     };

     return inputStream;
  }

}

Was it helpful?

Solution

You already consumed all data sent with the request, so there's nothing left for the super.doPost(...) method!

You could instead pass a HttpServletRequestWrapper to super.doPost(...). It should wrap the original request but returns a different InputStream that is backed by the bytes array you've already read in this method. Also note that it will be necessary to also wrap the reader that can be obtained from the request (HttpServletRequest#getReader()).

See also How to log response content from a java web server, there you can find a complete code sample about the opposite side of logging. I think it can easily be adopted to what you need.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top