Akka Tomcat issue

Viewed 352

I have a similar problem as described in post below:

https://groups.google.com/d/msg/akka-user/Lp2hn4FfhU8/6a1EZVCmJpQJ

When shutting down Tomcat, I got:

10-Nov-2017 09:47:56.517 SEVERE [main] 

org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [akka.actor.ActorCell$$anon$1] (value [akka.actor.ActorCell$$anon$1@1f9e9475]) and a value of type [scala.collection.immutable.Nil$] (value [List()]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
10-Nov-2017 09:47:56.517 SEVERE [main] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [akka.actor.ActorCell$$anon$1] (value [akka.actor.ActorCell$$anon$1@1f9e9475]) and a value of type [scala.collection.immutable.Nil$] (value [List()]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
10-Nov-2017 09:47:56.535 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-8080"]
10-Nov-2017 09:47:56.538 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-8009"]
10-Nov-2017 09:47:56.540 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-8080"]
10-Nov-2017 09:47:56.541 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-8009"]

And Tomcat is stuck - to shut it down completely I have to kill its process. I tried similar solution as mentioned in the post above (I use Akka 2.5.6, so there is no shutdown() and awaitTermination() methods anymore):

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    ActorSystem actorSystem = (ActorSystem) WebApplicationContextUtils.getRequiredWebApplicationContext(servletContextEvent.getServletContext()).getBean("my-actor-system");
    try {
        Await.result((Awaitable) actorSystem.terminate(), Duration.create(10, TimeUnit.SECONDS));
    } catch (Exception e) {
        logger.warning(e.getMessage());
    }
}

But it doesn't help at all. The Bean is created in a simple way:

@Bean
public ActorSystem actorSystem() {
    return ActorSystem.create("my-actor-system");
}

Any ideas?

Versions specification:
Tomcat 9.0.1
Akka 2.5.6
Spring 4.2.3

1 Answers

I have managed to figure out the workaround, which someone may find useful. Although I know, it is not a proper solution, so all "cleaner" solutions are still welcome.

When I create and destroy ActorSystem in ServletContextListener it works fine. So finally I overrode the default listener with this:

private static ActorSystem actorSystem;

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    actorSystem = ActorSystem.create("my-actor-system");
}

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    try {
        Await.result((Awaitable) actorSystem.terminate(), Duration.create(10, TimeUnit.SECONDS));
    } catch (Exception e) {
        logger.warning(e.getMessage());
    }
}

public static ActorSystem getActorSystem() {
    return actorSystem;
}

Then in config I just create ActorSystem Bean, that calls the getter method above:

@Bean
public ActorSystem actorSystem() {
    return MyServletContextListener.getActorSystem();
}

Please note, that I use Akka 2.5.6. In older versions you should terminate ActorSystem in different way (you will notice, that there will be no actorSystem.terminate() method if so).

Related