How to gracefully close the endpoint when an exception occurs?

I wrote a small JAX-WS web service that I run outside of the container with Endpoint.publish():

Endpoint endpoint = Endpoint.create(new MyServiceImpl());
endpoint.publish("http://localhost:4425/myService");

If any of my web service methods throws an exception, the endpoint will not be gracefully closed and the address will remain valid until Windows eventually releases it. This causes a classic error:

com.sun.xml.internal.ws.server.ServerRtException: Runtime server runtime error: java.net.BindException: address already in use: bind

I could wrap all my web service methods with try / catch, but this seems a bit repetitive. I also tried to set the cleanup class using Thread.setDefaultUncaughtExceptionHandler(), but it was not called when my web service method made an exception.

Is there a more elegant way to solve this issue than resorting to countless try / catch blocks?


Based on Waldheinz's answer, I tried using Jetty classes in favor of default JDK settings. The code compiles, but when it is executed, it ends immediately after publish. When using JDK classes, the main thread will remain alive until I finish the process manually. Any ideas on what's going on? I wonder if some kind of exception happens somewhere, but is swallowed, so I don't see it.

Endpoint endpoint = Endpoint.create(new MyServiceImpl());

Server s = new Server(new InetSocketAddress(HOST, PORT));
ServerConnector connector = new ServerConnector(s);
connector.setReuseAddress(true);
s.setConnectors(new Connector[] { connector });
s.setHandler(new ContextHandlerCollection());

JettyHttpServer server = new JettyHttpServer(s, false);
JettyHttpContext context = (JettyHttpContext) server.createContext(PATH);
endpoint.publish(context);
+4
source share
4 answers
+2

:

ThreadFactory factory = new ThreadFactory() {

  @Override
  public Thread newThread(Runnable target) {
    final Thread thread = new Thread(target);
    thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {

        @Override
        public void uncaughtException(Thread t, Throwable e) {
            // put error handling code here
        }

    });
    return thread;
  }


};

ExecutorService executor = Executors.newCachedThreadPool(factory);
Endpoint endpoint = Endpoint.create(new MyServiceImpl());
endpoint.setExecutor(executor);
endpoint.publish("http://localhost:4425/myService");
+3

Waldheinz, -, Jetty :

Server s = new Server(PORT);
ServerConnector connector = new ServerConnector(s);
connector.setReuseAddress(true); // avoid bind errors
s.setHandler(new ContextHandlerCollection());
s.setConnectors(new Connector[] { connector });

System.setProperty("com.sun.net.httpserver.HttpServerProvider",
        "org.eclipse.jetty.http.spi.JettyHttpServerProvider");

Endpoint.publish(HOST + ":" + PORT + PATH, new MyServiceImpl());

, , . , . Jk1 .

+1

, , , , Jetty. , , , , - Endpoint.setExecutor(Executor).

ThreadFactory, . Guava ThreadFactoryBuilder :

public class MyHandler implements Thread.UncaughtExceptionHandler {

    private final Endpoint endpoint;

    public MyHandler(Endpoint endpoint) {
        this.endpoint = endpoint;
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        // ...
    }
}

Endpoint endpoint = Endpoint.create(new MyServiceImpl());
Thread.UncaughtExceptionHandler handler = new MyHandler(endpoint);
ThreadFactory factory = new ThreadFactoryBuilder().setUncaughtExceptionHandler(handler).build();
Executor executor = Executors.newSingleThreadExecutor(factory);
endpoint.setExecutor(executor);
endpoint.publish("http://localhost:4425/myService");

ThreadPoolExecutor afterExecute(Runnable, Throwable).

public class ServiceExecutor extends ThreadPoolExecutor {

    private final Endpoint endpoint;

    // ThreadPoolExecutor has four ctors
    public ServiceExecutor(Endpoint endpoint, ...) {
        this.endpoint = endpoint;
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if (t != null) {
            // ...
        }
    }
}

Endpoint endpoint = Endpoint.create(new MyServiceImpl());
Executor executor = new ServiceExecutor(endpoint, ...);
endpoint.setExecutor(executor);
endpoint.publish("http://localhost:4425/myService");
0

Source: https://habr.com/ru/post/1540227/


All Articles