6

I have a Grails service class that needs to do some cleanup when my Tomcat application server is shut down.

I don't see anything in the Grails docs about a service.stop() or destroy() method, or a way to implement any sort of application lifecycle listener.

What's the best way to do this?

Thanks!

Dónal
  • 185,044
  • 174
  • 569
  • 824
Dean Moses
  • 2,372
  • 2
  • 24
  • 36

4 Answers4

8

You have a couple of options

Make your service implement org.springframework.beans.factory.DisposableBean

class MyService implements org.springframework.beans.factory.DisposableBean {

    void destroy() throws Exception {

    }
}

Or use an annotation

class MyService {

    @PreDestroy
    private void cleanUp() throws Exception {

    }
 }

IMO, the annotation option is preferable, because you can give your destructor method a more meaningful name than destroy and your classes public API doesn't expose the Spring dependency

Dónal
  • 185,044
  • 174
  • 569
  • 824
  • Thanks, that's great! Agree that I prefer @PreDestroy so as not to expose the Spring dependency, and it's just that much clearer what's going on. – Dean Moses Apr 06 '11 at 22:07
6

The grails-app/conf/BootStrap.groovy can be used when the app starts and stops.

def init = {
  println 'Hello World!'
}

def destroy = {
  println 'Goodnight World!'
}

Note: When using development mode grails run-app on some OS's CTL+C will kill the JVM without the chance for a clean shutdown and the destroy closure may not get called. Also, if your JVM gets the kill -9 the closure wont run either.

Derek Slife
  • 20,750
  • 1
  • 18
  • 22
  • This answer is not appropriate for the question, question specifically asks for service to be notified in case of application shutdown. Although if only requirement is to do something on application shutdown then its good enough. @Maricel's answer is much more closer to the answer if one wants to inject the service bean to Bootstrap. – Aditya T May 11 '18 at 10:48
1

I would try injecting the service into the Bootstrap and then calling the method from the destroy block, since the destroy block is executed when the application is terminated, something like this:

class BootStrap {

    def myService

    def init = {servletContext ->
    }

    def destroy = {
       myService.cleanUp()
    }
}
Maricel
  • 2,089
  • 13
  • 17
  • Good to know, Maricel. Though in this case I like being able to use @PreDestroy as Don suggests because it so cleanly and simply ties the cleanup to the service that needs cleaning up. – Dean Moses Apr 06 '11 at 22:14
0

It's not quite the same as a service disposal method, but what I ended up doing is registering a Spring Bean with a shutdown method that gets called when the app is stopped.

First, create a bean class, like grails-app/utils/MyShutdownBean.groovy that looks like the following (there's nothing sacred about the class name or the method name, use whatever you want):

class MyShutdownBean {
    public void cleanup() {
        // Do cleanup stuff
    }
}

Then register the bean in grails-app/conf/spring/resources.groovy like this:

beans = {
    myShutdownHook(MyShutdownBean) { bean ->
        bean.destroyMethod='cleanup'
    }
}

If you want to only do the cleanup in production, you can register it like this instead:

beans = {
    if (!grails.util.GrailsUtil.isDevelopmentEnv()) {
        myShutdownHook(MyShutdownBean) { bean ->
            bean.destroyMethod='cleanup'
        }
    }
}
Dean Moses
  • 2,372
  • 2
  • 24
  • 36
  • How does that ensure that it runs when Tomcat dies? What if the bean was never instantiated? What if it was garbage collected? Wouldn't it then run your cleanup before you want it to? – Gregg Apr 06 '11 at 03:49