Archer
Archer

Reputation: 5147

How to delay spring beans startup?

Having spring application (actually grails app) that runs apache-activemq server as spring bean and couple of apache-camel routes. Application use hibernate to work with database. The problem is simple. Activemq+Camel starts up BEFORE grails injects special methods into hibernate domain objects (actually save/update methods etc). So, if activemq already has some data on startup - camel starts processing messages w/o having grails DAO methods injected. This fails with grails.lang.MissingMethodException. Must delay activemq/camel startup before Grails injects special methods into domain objects.

Upvotes: 7

Views: 6908

Answers (4)

codewandler
codewandler

Reputation: 557

I know this question is pretty old, but I am now facing the same problem in the year 2015 - and this thread does not offer a solution for me.

I came up with a custom processor bean having a CountDownLatch, which I count down after bootstrapping the application. So the messages will be idled until the app has started fully and its working for me.

/**
 * bootstrap latch processor
 */
 @Log4j
 class BootstrapLatchProcessor implements Processor {
     private final CountDownLatch latch = new CountDownLatch(1)

     @Override
     void process(Exchange exchange) throws Exception {

         if(latch.count > 0){
            log.info "waiting for bootstrapped @ ${exchange.fromEndpoint}"
            latch.await()
         }

         exchange.out = exchange.in
     }

     /**
      * mark the application as bootstrapped
      */
     public void setBootstrapped(){
         latch.countDown()
     }
 }

Then use it as a bean in your application and call the method setBootstrapped in your Bootstrap.groovy

Then in your RouteBuilder you put the processor between your endpoint and destination for all routes you expect messages coming in before the app has started:

from("activemq:a.in ").processRef('bootstrapProcessor').to("bean:handlerService?method=handle")

Upvotes: 0

Bozho
Bozho

Reputation: 597096

If all these are defined as spring bean, you can use

<bean id="activeMqBean" depends-on="anotherBean" />

This will make sure anotherBean is initialized before activeMqBean

Upvotes: 5

Gopi
Gopi

Reputation: 10293

I am not sure in your case but lazy loading may also help e.g.

<bean id="lazybean" class="com.xxx.YourBean" lazy-init="true">

A lazily-initialized bean indicates to the IoC container to create bean instance when it is first requested. This can help you delay the loading of beans you want.

Upvotes: 3

Sammyrulez
Sammyrulez

Reputation: 1066

can you move MQ managment into a plugin? It would increase modularity and if you declare in plugin-descriptor

def loadAfter = ['hibernate']

you should have the desired behavior. Works for JBPM plugin

Upvotes: 4

Related Questions