Topic binding failed because 2 ApplicationStartedEvents are fired

Hello,

I’m making a POC to integrate Camunda into our application and see what is possible from a technical standpoint.
I’m aiming for a setup with an external Camunda (currently just docker) and adding @ExternalTaskSubscriptions to our existing spring boot backend.

I’m getting an error “TASK/CLIENT-03006 Topic name ‘demoTask’ has already been subscribed”.

Looking into this I see this is because the spring boot starter starts initialization as reaction on a ApplicationStartedEvent (org.camunda.bpm.client.spring.impl.subscription.SpringTopicSubscriptionImpl#start) and during initialization, an error is thrown (org.camunda.bpm.client.topic.impl.TopicSubscriptionManager#subscribe) if there is already a subscription.

Our backend uses multiple spring boot starters, one of which is spring cloud stream (3.1.1 is our version), which sets up a new SpringApplication for their bindings: spring-cloud-stream/DefaultBinderFactory.java at 803c253810105066cb985bc4d7a3ac7d5773fc7f · spring-cloud/spring-cloud-stream · GitHub

Not sure what the reasoning behind the spring-cloud-stream set up is, but it seems deliberate and and of course the additional ApplicationStartedEvent conflicts directly with the Camunda “is topic already subscribed” check.

Currently, I’m a bit stuck trying to achieve my desired setup with the @ExternalTaskSubscriptions embedded into our backend and I’ll switch to another one.

Any feedback on this problem is appreciated. I don’t think I can resolve this in our application configuration…

Many thanks,
Glen

1 Like

Hi @Glever

Welcome to the forum!

I’m interested in more details about your setup.
Can you describe the architecture a little more how many workers have you created - how many are using the same topic Id and can you also let me know what setting you’re using for the worker.

Also - are the workers and the engine independent services?

Hi Niall,

Thanks for the feedback.

Our backend is a “typical” java 11 spring boot 2.4.5 web/jpa/… application which also uses spring-cloud-stream for messaging integration.

Part of the POC is figuring out which setup would be feasible. And the endgoal is demoing “some” functionality activated by the workflow engine.
I watched your Youtube playlists on getting started with spring boot and I believe also the standard getting started vids.

The set up I’d like to achieve is

camunda (plain docker with embedded h2 and demo user) <--- REST ---> our backend with External Clients configured as demonstrated in https://docs.camunda.org/manual/7.15/user-guide/ext-client/spring-boot-starter/ 

I’m using all default values for the configuration, so translated to .properties I currently have:

#camunda config
camunda.bpm.client.base-url: http://localhost:4242/engine-rest
camunda.bpm.client.subscriptions.demoTask.process-definition-key: demo
camunda.bpm.client.subscriptions.demoTask.include-extension-properties: true
camunda.bpm.client.subscriptions.demoTask.variable-names:

The rest is all default.

The handler configuration is taken straight from External Task Client Spring Boot Starter | docs.camunda.org , neither the class-annotated nor inline lambda definitions works. Both yield same error message.

In debug mode I see that org.camunda.bpm.client.spring.impl.subscription.SpringTopicSubscriptionImpl#start (extended by PropertiesAwareSpringTopicSubscription from the autoconfiguration) is called twice at application startup, in order:

Once for the “extra” SpringApplication created by spring-cloud-stream, which has a “parent” reference to the real webapplicationcontext.
Once for the “real” SpringApplication, created by our own code in the regular way:

public static void main(String[] args) {  SpringApplication.run(OurApplication.class, args); }

So I’m guessing I’m running in a situation that’s not (yet? :slight_smile: ) anticipated by the subscription logic. And even assume I’m running into a feature that’s a safeguard for other scenario’s (multi-threading, programmatic creation of subscriptions,…)?

I tried overruling org.camunda.bpm.client.spring.boot.starter.impl.ClientAutoConfiguration by adding my own @Primary bean definitions with a custom subclass of PropertiesAwareSpringTopicSubscription that overrides the isEventThatCanStartSubscription().
But that was clearly not the way to go, got lost in the rabbit hole of conflicting bean definitions (can’t remember the errors, I gave up on that).
Next option was to remove the -starter dependency and just manually set up the spring beans. But as there is limited time to set up a POC I didn’t want to risk losing another day with setup.

What I’m currently going for is splitting off the ExternalTaskHandlers into a microservice which communicates with our backend through REST, so

camunda <--REST--> ExternalTaskHandlers microservice <--REST--> backend

This feels as it would be the most straightforward approach.

I hope this answers your questions?

1 Like