1

I have a parent context which i have bootstrapped to my servlet in the web.xml:

<servlet>
    <servlet-name>Outflow</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>com.fmr.bpo.asyncprocessingframework.invocator.wiring.configuration.pojo.common.RootConfig</param-value>
    </init-param>
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
</servlet>

Since i can only like initialize the child context after loading and setting it's parent context, i'm listening on this parent context by implementing ApplicationListener<ContextRefreshedEvent>.

Once the parent context loads, my listener's onApplicationEvent triggers, and i hook up different environments to child contexts and load them:

public void onApplicationEvent(ContextRefreshedEvent event) {
    for(String infoKey : clientConfig.getPairs().keySet()) {
        PairInfo info = clientConfig.getPairs().get(infoKey);
        createChildContext(info);
    }
}

private void createChildContext(ListenerInfo info) {
    Properties properties = info.getProperties();
    StandardEnvironment environment = new StandardEnvironment();
    environment.getPropertySources().addLast(new PropertiesPropertySource("infoprops", properties));
    AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
    child.register(InboundFlow.class);
    child.setId(properties.getProperty("id"));
    child.setParent(context);
    child.setEnvironment(environment);
    child.refresh();
}

The problem is that every time this child context refreshes, this same listener is called again (since it implements the ApplicationListener<ContextRefreshedEvent>). It becomes an infinite loop coz every time a context loads, the onApplicationEvent is creates another child context which calls the event method again.

How do i avoid this by listening in on just the parent context and not all contexts? Or is there any other way for me to initialize my child contexts?

Thanks in advance for the help.

alokraop
  • 853
  • 1
  • 11
  • 29
  • Why do you need this? Isn't there an easier way to load the `InboundFlow` based configuration? Why not simply set a boolean in your listener which indicates that it is already processing (or processed) that way you can skip other events (or check if the `source` is a `WebApplicationContext` if not ignore the event). – M. Deinum Jan 05 '16 at 14:37
  • Hey ya i could use a boolean or check the source and filter it accordingly, but that wouldn't be very clean would it? i mean, i don't need to be notified when the child contexts refresh at all. Having this one blanket listener would be like having just the one event handler for all buttons in a screen; only here most of the buttons don't even have any handling logic. If there was some way to just listen in on one particular context, that would be nice. – alokraop Jan 07 '16 at 11:04
  • You cannot as the parent is a listener for childs and hence the events are propagated. Child always notifies the parent (not the other way around). So you would need a check or find another way of bootstrapping your code as it looks quite convoluted to me, do you really need all the child contexts? – M. Deinum Jan 07 '16 at 11:44
  • Oh so it essentially becomes one context when i make one the parent of the other? I guess i'll just go with the source check till something else turns up then thanks. And yeah, i kinda need all the child contexts :-( - http://stackoverflow.com/questions/33507361/how-to-hook-up-a-list-of-message-driven-adapters-without-actually-writing-each-o – alokraop Jan 11 '16 at 11:01
  • No it doesn't become 1 context they are separate contexts but the parent is always a listener for events of the childs. – M. Deinum Jan 11 '16 at 11:04
  • Also I don't see why you still would need to have multiple contexts for that. You could create a base method for the configuration (or helper class) then use a `BeanDefinitionRegistryPostProcessor` to add a definition for the classes needed. That way you still have a single context instead of multiple. (Or register the `@Configuration` class with the properties set). – M. Deinum Jan 11 '16 at 11:08
  • The post processor is for adding new beans into an existing context right? I have this one class with two beans (they're inbound adapters listening on queues) which need to be instantiated with different values fed to them. That's the reason i'm making one context for each value (basically the queue name) and feeding the value into the environment. Then i'm feeding in the same config class to each child context. How would i do that with the post processor though? – alokraop Jan 11 '16 at 11:19
  • No the post processor is for adding bean definitions BEFORE the context is actually initialized. If you can find a way to load your custom properties before that you can register as many of those `InboundFlow ` configuration as you want, one drawback would be that you would need to manually configure the properties instead of relying on the `@Value` you probably have now. But it saves you the additional contexts. – M. Deinum Jan 11 '16 at 11:22

0 Answers0