Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8288109

HttpExchangeImpl.setAttribute does not allow null value after JDK-8266897

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 21
    • None
    • core-libs
    • 17
    • b17
    • generic
    • generic
    • Verified

      The code of the HTTPServer was changed in Java 17, among the change a ConcurrentHashMap is now used to store the attributes of the HttpExchange.
      The problem is that ConcurrentHashMap.put() does not allow the value to be null while the spec does not say that the value of an attribute can not be null.

      To reproduce, this code works with Java 8 up to Java 16 but fails with Java 17+.
      import com.sun.net.httpserver.HttpServer;

      import java.io.IOException;
      import java.io.OutputStream;
      import java.net.InetSocketAddress;
      import java.nio.charset.StandardCharsets;

      public class HttpServerRegression {
        public static void main(String[] args) throws IOException {
          HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);
          server.createContext("/", exchange -> {
            System.err.println("request " + exchange.getRequestMethod() + " " + exchange.getRequestURI());
            try {
              exchange.setAttribute("status", null); // throw a NPE if Java version >= 17

              byte[] bytes = "<h2>Hello</h2>".getBytes(StandardCharsets.UTF_8);
              exchange.sendResponseHeaders(200, bytes.length);
              try(OutputStream body = exchange.getResponseBody()) {
                body.write(bytes);
              }
            } catch(Exception e) {
              e.printStackTrace();
              throw e;
            }
          });
          server.setExecutor(null);
          server.start();
        }
      }

      Here is the error message:
      java.lang.NullPointerException
              at java.base/java.util.concurrent.ConcurrentHashMap.putVal(ConcurrentHashMap.java:1011)
              at java.base/java.util.concurrent.ConcurrentHashMap.put(ConcurrentHashMap.java:1006)
              at jdk.httpserver/sun.net.httpserver.ExchangeImpl.setAttribute(ExchangeImpl.java:381)
              at jdk.httpserver/sun.net.httpserver.HttpExchangeImpl.setAttribute(HttpExchangeImpl.java:105)
              at HttpServerRegression.lambda$main$0(HttpServerRegression.java:14)
              at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:95)
              at jdk.httpserver/sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:82)
              at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:98)
              at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:728)
              at jdk.httpserver/com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:95)
              at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:695)
              at jdk.httpserver/sun.net.httpserver.ServerImpl$DefaultExecutor.execute(ServerImpl.java:159)
              at jdk.httpserver/sun.net.httpserver.ServerImpl$Dispatcher.handle(ServerImpl.java:447)
              at jdk.httpserver/sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:413)
              at java.base/java.lang.Thread.run(Thread.java:833)

            djelinski Daniel Jelinski
            forax RĂ©mi Forax
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: