1

Hey this is a follow up on a previous question i had posted about hooking up message driven channel adapters to multiple queues without writing each one out.

How to hook up a list of message driven adapters without actually writing each one out?

I tried to follow the suggested approach:

Spring multiple imapAdapter

Now i have this one config (the child) which takes properties from it's environment (like the queue name) and creates the message driven adapter accordingly.

@Autowired
private ApplicationContext context;

@Value("${id}")
private String id;

@Value("${primaryConnection}")
private String primaryConnection;

@Value("${queueName}")
private String queueName;   

@Bean
public IntegrationFlow primaryInitiationListenerFlow() {
    return IntegrationFlows.from(Jms
                .messageDriverChannelAdapter(context.getBean(primaryConnection, ConnectionFactory.class))
                .autoStartup(false)
                .destination(queueName)
                .configureListenerContainer(listenerContainerSpec())
                .id(id + "PrimaryIn")
                .get())
            .channel("initiationChannel")
            .get();
}

On application startup i iterate over a list of queue names i have and for each of them instantiate the above context with the my main context as the parent and pass in the appropriate environment.

public void onApplicationEvent(ContextRefreshedEvent event) {
    for(String infoKey : clientConfig.getPairs().keySet()) {
        PairInfo info = clientConfig.getPairs().get(infoKey);
        Properties properties = info.getProperties();
        StandardEnvironment environment = new StandardEnvironment();
        environment.getPropertySources().addLast(new PropertiesPropertySource("connectionProps", properties));
        AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
        child.register(InboundFlow.class);
        child.setId(properties.getProperty("id"));
        child.setParent(context);
        child.setEnvironment(environment);
        child.refresh();
    }
}

All these instances of the child context are now feeding into different queues and putting the messages into a common channel (the initiationChannel) which is listened in by the parent.

@Bean
public IntegrationFlow initiationAndDataFlow() {
    return IntegrationFlows
            .from("initiationChannel")
            .handle(//doStuff)
            .get();
}

I've defined the initiationChannel in the parent and set things up just like the one Gary did in the example.

But i'm getting this error saying initiationChannel has no publishers when i start the spring context:

Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: >Failed to instantiate [org.springframework.integration.dsl.IntegrationFlow]: >Factory method 'initiationAndDataFlow' threw exception; nested exception is >java.lang.NoClassDefFoundError: org.reactivestreams.Publisher

I kinda need to load the parent context (with the subscriber) first and then assign it to each child, so when there parent loads there won't be anyone publishing to the channel.

I don't know what i'm doing wrong. Thanks for the help.

Community
  • 1
  • 1
alokraop
  • 853
  • 1
  • 11
  • 29

1 Answers1

1

java.lang.NoClassDefFoundError: org.reactivestreams.Publisher

You are missing the reactive-streams-1.0.0.jar from your classpath.

You should use maven or gradle for your project to make sure all the dependencies are resolved.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Oh I totally misunderstood that error message sorry. I do have maven. Weird that it's not showing in my target folder. Thanks for the help. – alokraop Nov 18 '15 at 10:47