[PING] Re: Unexpected BindException in Endpoint.publish

KUBOTA Yuji kubota.yuji at gmail.com
Tue Dec 1 05:20:22 UTC 2015


Hi all,

Please review this issue and patch.

Thanks,
Yuji

2015-10-29 3:22 GMT+09:00 KUBOTA Yuji <kubota.yuji at gmail.com>:
> Hi all,
>
> I'm at the HackerGarten @ JavaOne15, and write a patch for OpenJDK
> community. This's second times from JavaOne14. :)
>
> We find an unexpected exception in JAX-WS, so I write a patch to fix it.
> We think that this issue may block the migration to JDK9 from JDK7.
>
> If we bind 0.0.0.0 ( using as wildcard ) to publish multiple as the
> following test code, JDK9 (and JDK8) returns "java.net.BindException:
> Address already in use.” as the below. But JDK7 does NOT return the
> exception.
>
> - Test code for reproduce
> ---
> import javax.jws.*;
> import javax.xml.ws.*;
>
> public class WSTest{
>
>   @WebService
>   public static class Method1{
>     @WebMethod
>     public String getMethod1Value(){
>       return "from Method1";
>     }
>                                                              }
>
>   @WebService
>   public static class Method2{
>     @WebMethod
>     public String getMethod2Value(){
>       return "from Method2";
>     }
>   }
>
>   public static void main(String[] args) throws Exception{
>     Endpoint endPoint1 = Endpoint.publish("http://0.0.0.0:8081/method1",
>                                                                  new Method1());
>     Endpoint endPoint2 = Endpoint.publish("http://0.0.0.0:8081/method2",
>                                                                  new Method2());
>
>     System.out.println("Sleep 3 secs...");
>
> Thread.sleep(3000);
>
>     endPoint2.stop();
>     endPoint1.stop();
>   }
>
> }
> ---
>
> - StackTrace
> ---
> Exception in thread "main"
> com.sun.xml.internal.ws.server.ServerRtException: Server Runtime
> Error: java.net.BindException: Address already in use
>         at com.sun.xml.internal.ws.transport.http.server.ServerMgr.createContext(ServerMgr.java:117)
>         at com.sun.xml.internal.ws.transport.http.server.HttpEndpoint.publish(HttpEndpoint.java:64)
>         at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.publish(EndpointImpl.java:232)
>         at com.sun.xml.internal.ws.spi.ProviderImpl.createAndPublishEndpoint(ProviderImpl.java:126)
>         at javax.xml.ws.Endpoint.publish(Endpoint.java:240)
>         at wstest.WSTest.main(WSTest.java:27)
> Caused by: java.net.BindException: Address already in use
>         at sun.nio.ch.Net.bind0(Native Method)
>         at sun.nio.ch.Net.bind(Net.java:432)
>         at sun.nio.ch.Net.bind(Net.java:424)
>         at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
>         at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
>         at sun.net.httpserver.ServerImpl.<init>(ServerImpl.java:102)
>         at sun.net.httpserver.HttpServerImpl.<init>(HttpServerImpl.java:50)
>         at sun.net.httpserver.DefaultHttpServerProvider.createHttpServer(DefaultHttpServerProvider.java:35)
>         at com.sun.net.httpserver.HttpServer.create(HttpServer.java:130)
>         at com.sun.xml.internal.ws.transport.http.server.ServerMgr.createContext(ServerMgr.java:86)
>         ... 5 more
> -----
>
> To publishes the Endpoint, JAX-WS checks whether the HttpContext has
> been created by given address, then creates a HttpContext if do not
> exist.
> If we sets 0.0.0.0 as given address, JAX-WS checks by
> ServerSocket#getLocalSocketAddress() (server local address), so
> returns BindException when 0.0.0.0 has been blinded already.
>
> Why so? JAX_WS-941[1] fixes NPE in Endpoint.stop but do not think
> about above situation. And JAX_WS-941 does not back port to JDK7.
>
> So I write a patch which is based jdk9/dev/jaxws (changeset:
> 637:2d84c6f4cbba) to fix the BindException with JAX_WS-941.
> Please review this patch :)
>
> [1]: https://java.net/jira/browse/JAX_WS-941
>
> - Patch
> ---
> diff -r 2d84c6f4cbba
> src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/http/server/ServerMgr.java
> --- a/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/http/server/ServerMgr.java
> Thu Oct 22 08:47:47 2015 -0700
> +++ b/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/http/server/ServerMgr.java
> Tue Oct 27 19:48:35 2015 +0900
> @@ -38,6 +38,7 @@
>  import java.util.concurrent.ExecutorService;
>  import java.util.concurrent.Executors;
>  import java.util.logging.Logger;
> +import java.util.Optional;
>
>  /**
>   * Manages all the WebService HTTP servers created by JAXWS runtime.
> @@ -81,24 +82,38 @@
>              synchronized(servers) {
>                  state = servers.get(inetAddress);
>                  if (state == null) {
> -                    logger.fine("Creating new HTTP Server at "+inetAddress);
> -                    // Creates server with default socket backlog
> -                    server = HttpServer.create(inetAddress, 0);
> -                    server.setExecutor(Executors.newCachedThreadPool());
> -                    String path = url.toURI().getPath();
> -                    logger.fine("Creating HTTP Context at = "+path);
> -                    HttpContext context = server.createContext(path);
> -                    server.start();
> +                    final int finalPortNum = port;
> +                    Optional<ServerState> stateOpt =
> +                               servers.values()
> +                                       .stream()
> +                                       .filter(s -> s.getServer()
> +                                                     .getAddress()
> +                                                     .getPort() ==
> finalPortNum)
> +                                       .findAny();
>
> -                    // we have to get actual inetAddress from server,
> which can differ from the original in some cases.
> -                    // e.g. A port number of zero will let the system
> pick up an ephemeral port in a bind operation,
> -                    // or IP: 0.0.0.0 - which is used to monitor
> network traffic from any valid IP address
> -                    inetAddress = server.getAddress();
> +                    if (inetAddress.getAddress().isAnyLocalAddress() &&
> +                        stateOpt.isPresent()) {
> +                        state = stateOpt.get();
> +                    } else {
> +                        logger.fine("Creating new HTTP Server at
> "+inetAddress);
> +                        // Creates server with default socket backlog
> +                        server = HttpServer.create(inetAddress, 0);
> +                        server.setExecutor(Executors.newCachedThreadPool());
> +                        String path = url.toURI().getPath();
> +                        logger.fine("Creating HTTP Context at = "+path);
> +                        HttpContext context = server.createContext(path);
> +                        server.start();
>
> -                    logger.fine("HTTP server started = "+inetAddress);
> -                    state = new ServerState(server, path);
> -                    servers.put(inetAddress, state);
> -                    return context;
> +                        // we have to get actual inetAddress from
> server, which can differ from the original in some cases.
> +                        // e.g. A port number of zero will let the
> system pick up an ephemeral port in a bind operation,
> +                        // or IP: 0.0.0.0 - which is used to monitor
> network traffic from any valid IP address
> +                        inetAddress = server.getAddress();
> +
> +                        logger.fine("HTTP server started = "+inetAddress);
> +                        state = new ServerState(server, path);
> +                        servers.put(inetAddress, state);
> +                        return context;
> +                    }
>                  }
>              }
>              server = state.getServer();
> ---


More information about the jdk9-dev mailing list