0

I have a spring context in which a we have Runnable beans started like so:

public void startChildAndWait(Class type) {
  BaseMyDispatcher child = appContext.getBean(type);
  child.initialize(this); //The child references its parent during run method
  new Thread(child).start();
  synchronized(LOCK_OBJECT) {
    LOCK_OBJECT.wait(someTime);
  }
}

The BaseMyDispatcher class is an abstract class and SampleRunnableX are implementations which are with prototype scope, the base class basically has @PostConstruct method and a @PreDestroy method (the main functionality of which is to call notify on a LOCK_OBJECT) and of course a Run method

My problem is that the PostConstruct method is called but when the Run method completes the object doesn't seem to be destroyed therefore the PreDestroy method is not called and I get stuck waiting in parent on the LOCK_OBJECT

The code is called in a function inside a parent Runnable (which is executed inside a ThreadPoolExecutor and starts (sequentially) several children with the same method startChildAndWait passing each time a different class:

startChildAndWait(SampleRunnable1.class);
if(run2IsRequired && lastExitCode == 100) {//runIsRequired are booleans
  startChildAndWait(SampleRunnable2.class);
}
if(run3IsRequired && lastExitCode == 100) {//lastExitCode is an integer
  startChildAndWait(SampleRunnable3.class);
}

So what do I do to make the PreDestroy method called upon completion of the child thread?

Alex Sayegh
  • 233
  • 4
  • 16

2 Answers2

2

From the documentation:

In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called.

If you want something to happen when the run() method completes, put that code at the end of the run() method.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

@PreDestroy callback method will be called when your application shuts down, you need to register a shutdown hook to JVM and close the application context in it when JVM exits.

//Create applicationContext
final ApplicationContext appContext = 

//register ashutdown hook on application context
Runtime.getRuntime().addShutdownHook(new Thread() {
   public void run() {
       appContext.close();
   }});

If you want to execute some code when child thread completes, better put it in end of run method(thread itself).

Prateek Kapoor
  • 947
  • 9
  • 18
  • Thanks for both answers, the reason I tried to do this is to have the destroy method called in the base class, and keep the extended class clean (i.e. without putting the finalization code call in the run method) I guess it doesn't work as I was hoping – Alex Sayegh Jul 11 '15 at 17:33
  • I've decided to do it through aspectj...I have a point-cut around the execution of the run method and can make a new annotation for it – Alex Sayegh Jul 12 '15 at 10:23