title: How do I get a request body from HttpServerExchange?
body: <p>I created an Undertow server and a Handler to Log requests.
  I'm having problems to retrieve the request body of <code>HttpServerExchange</code>.</p>
  
  <p>At <code>LoggingHandler</code> class, I'm getting the body without problems. But at <code>TestEndpoint</code> the body is coming empty.</p>
  
  <p>If I remove the line that retrieve the request body at <code>LoggingHandler</code>, the body gets populated at <code>TestEndpoint</code>.</p>
  
  <p>Does anyone know a way to do this?</p>
  
  <p>My Server class:</p>
  
  <pre><code>package com.undertow.server;
  
  import com.undertow.server.endpoints.TestEndpoint;
  
  import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
  import org.jboss.resteasy.spi.ResteasyDeployment;
  
  import io.undertow.Undertow;
  import io.undertow.Undertow.Builder;
  import io.undertow.server.HandlerWrapper;
  import io.undertow.server.HttpHandler;
  import io.undertow.server.handlers.BlockingHandler;
  import io.undertow.servlet.api.DeploymentInfo;
  
  public class UndertowServer {
  
      private UndertowJaxrsServer server;
  
      public UndertowServer() {
          this.server = new UndertowJaxrsServer();
      }
  
      public void start() {
          Builder builder = Undertow.builder().addHttpListener(8000, "0.0.0.0");
          this.server.start(builder);
          this.configureEndpoints();
      }
  
      private void configureEndpoints() {
          ResteasyDeployment deployment = new ResteasyDeployment();
          deployment.getActualResourceClasses().add(TestEndpoint.class);
  
          DeploymentInfo deploymentInfo = this.server.undertowDeployment(deployment) //
                  .setClassLoader(ClassLoader.getSystemClassLoader()).setContextPath("/gateway/") //
                  .setDeploymentName("gateway.war");
  
          deploymentInfo.addInitialHandlerChainWrapper(new HandlerWrapper() {
              @Override
              public HttpHandler wrap(HttpHandler handler) {
                  return new BlockingHandler(new LoggingHandler(handler));
              }
          });
  
          this.server.deploy(deploymentInfo);
      }
  
      public static void main(String[] args) {
          new UndertowServer().start();
      }
  
  }
  </code></pre>
  
  <p>My LoggingHandler class:</p>
  
  <pre><code>package com.undertow.server;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.nio.charset.StandardCharsets;
  import java.util.stream.Collectors;
  
  import org.apache.log4j.Logger;
  
  import io.undertow.server.HttpHandler;
  import io.undertow.server.HttpServerExchange;
  
  public class LoggingHandler implements HttpHandler {
  
      private static Logger LOGGER = Logger.getLogger(LoggingHandler.class);
  
      private final HttpHandler next;
  
      public LoggingHandler(final HttpHandler next) {
          this.next = next;
      }
  
      @Override
      public void handleRequest(HttpServerExchange exchange) throws Exception {
          LOGGER.info(toString(exchange.getInputStream()).trim());
          this.next.handleRequest(exchange);
      }
  
      private String toString(InputStream is) throws IOException {
          try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
              return br.lines().collect(Collectors.joining(System.lineSeparator()));
          }
      }
  
  }
  </code></pre>
  
  <p>My TestEndpoint class:</p>
  
  <pre><code>package com.undertow.server.endpoints;
  
  import javax.ws.rs.Consumes;
  import javax.ws.rs.POST;
  import javax.ws.rs.Path;
  import javax.ws.rs.Produces;
  import javax.ws.rs.container.AsyncResponse;
  import javax.ws.rs.container.Suspended;
  import javax.ws.rs.core.MediaType;
  import javax.ws.rs.core.Response;
  
  import org.apache.log4j.Logger;
  
  @Path("/person")
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  public class TestEndpoint {
  
      private static Logger LOGGER = Logger.getLogger(TestEndpoint.class);
  
      @POST
      @Path("/add")
      public void listar(@Suspended AsyncResponse response, String body) {
          LOGGER.info(body.trim());
          response.resume(Response.ok().build());
      }
  
  }
  </code></pre>
  
  <p>Thanks a lot!</p>