13

I need something to happen immediately after Spring's application context is loaded. As I understand it, I need to create an implementation of Lifecycle and put a bean reference inside the context. So I have something like this in my context:

<bean id="mySpringLifecycle" class="com.my.project.MySpringLifecycle" />

The class looks something like this:

public class MySpringLifecycle implements Lifecycle {

    @Override
    public void start() {
        System.out.println("The lifecycle has started.");
    }

    @Override
    public void stop() {
        return;
    }

    @Override
    public boolean isRunning() {
        return true;
    }
}

I get no errors, but MySpringLifecycle never prints out "The lifecycle has started.", and my application starts just fine.

EDIT:

This is the fixed code:

public class MySpringLifecycle implements SmartLifecycle {

    private volatile boolean isRunning = false;

    @Override
    public boolean isAutoStartup() {
        return true;
    }

    @Override
    public void stop(Runnable r) {
        System.out.println("STOPPED RUNNABLE!!!");
        isRunning = false;
    }

    @Override
    public void start() {
        System.out.println("STARTED!!!");
        isRunning = true;
    }

    @Override
    public void stop() {
        System.out.println("STOPPED!!!");
        isRunning = false;
    }

    @Override
    public boolean isRunning() {
        return isRunning;
    }

    @Override
    public int getPhase() {
        return 1;
    }
}

As a side note I also wanted to mention an alternative solution that I may use as well. I have the following in my web.xml:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

The ContextLoaderListener has a method on it called contextInitialized. So what I did was created my own implementation and added that to the web.xml instead. In my implementation I extended ContextLoaderListener, provided an override for the contextInitialized method, called super for that method first, and then executed my own functionality. This gets executed only once, and appears to work well.

  • Quoted from http://static.springsource.org/spring/docs/3.0.x/reference/beans.html#beans-factory-lifecycle-processor As you can see the stop method defined by SmartLifecycle accepts a callback. Any implementation must invoke that callback's run() method after that implementation's shutdown process is complete. – BPS Sep 06 '12 at 20:34
  • What if your class additionally extends another class. In addition the mentioned class is defined in spring . How to instantiate these parameters in your class example? – luksmir Feb 07 '14 at 07:56

4 Answers4

9

Two ways to do this:

  1. Implement SmartLifecycle instead of Lifecycle and make sure to return true from isAutoStartup().

  2. Implement ApplicationListener<ContextRefreshedEvent>. In this case there is only one method to implement instead of 6 for SmartLifecycle.

sourcedelica
  • 23,940
  • 7
  • 66
  • 74
  • Unfortunately, the ContextRefreshedEvent gets called several times during startup, not just once. I tried ContextStartedEvent, but that doesn't fire on application startup because the default life cycle doesn't appear to call start(). –  Jun 07 '11 at 00:55
  • When I implement SmartLifecycle the only thing getting called is the public void stop(Runnable r) override. There are obviously some implementation details I'm missing to make this work. –  Jun 07 '11 at 01:26
  • 4
    Make sure that `isRunning()` returns `false` until `start()` is called. `stop()` won't be called unless `isRunning()` returns true. – sourcedelica Jun 07 '11 at 01:54
  • Re: ContextRefreshedEvent being called multiple times, see http://stackoverflow.com/questions/6164573/why-is-my-spring-contextrefreshed-event-called-twice/6165557#6165557 – sourcedelica Jun 07 '11 at 01:57
  • That was it. I will post the fix above. Thanks! –  Jun 07 '11 at 02:36
  • 4
    No one seems to explain exactly why the start() method doesnt get called when implementing Lifecycle. Is this a bug? – Darth Ninja Aug 04 '14 at 18:31
1

If you modify MySpringLifecycle to implement SmartLifecycle instead of Lifecycle, System.outs in your snippet will be printed as you expect them to be.

Amol Katdare
  • 6,740
  • 2
  • 33
  • 36
0

I'm not sure, but you might need a LifecycleProcessor in addition to one-or-more Lifecycle objects.

Darien
  • 3,482
  • 19
  • 35
0

Depending on what you mean by 'immediately after Spring's application context is loaded.', an implementation of InitializingBean might be what you are looking for. LifeCycle might be too much low-level.

mkro
  • 1,902
  • 14
  • 15
  • `InitializingBean#afterPropertiesSet()` is called before the context is fully constructed, so bad things can happen if you depend on another bean. – sourcedelica Jun 07 '11 at 00:13