Unexpected BindException in Endpoint.publish
KUBOTA Yuji
kubota.yuji at gmail.com
Wed Feb 10 01:17:19 UTC 2016
Hi Miroslav,
Thank you for your sponsor! : https://bugs.openjdk.java.net/browse/JDK-8146086
Can I ask the schedule when does this fix backport to JDK8 ?
Thanks,
Yuji
2015-12-02 22:39 GMT+09:00 Miroslav Kos <miroslav.kos at oracle.com>:
> Hi Yuji,
> thanks for the patch - it fixes the issue and looks ok to me. I'll integrate
> it to standalone JAX-WS repo and it will be integrated into openjdk during
> next syncup.
>
> Thanks
> Miran
>
>
>
>
> On 01/12/15 11:11, KUBOTA Yuji wrote:
>>
>> Hi Miroslav and all,
>>
>> Could you please review the below issue and patch?
>>
>> I got the advice by Alan at net-dev. So I want to ask you.
>> http://mail.openjdk.java.net/pipermail/net-dev/2015-December/009361.html
>>
>> ----
>> 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();
>> ---
>>
>> Thanks,
>> Yuji
>
>
More information about the core-libs-dev
mailing list