Search code examples
spring-integrationspring-data-mongodbazure-aksspring-integration-dslazure-cosmosdb-mongoapi

Connectivity problem using Spring Data Mongo and Spring Integration with Azure CosmosDB (MongoDB)


I have the following setup:

  • Spring Integration with Spring Data Mongo repositories
  • Above application running as a pod on kubernetes (Azure Kubernetes Service)
  • Above application connects to Azure CosmosDB (MongoDB)
  • Above application connects to Azure SQL Server

The application should fetch information from MongoDB and start processing. It works all fine while running locally and within a docker container. The problem occurs when it's deployed to AKS as it can't establish connection to Mongo and Azure SQL while bootstrapping. The connection will be successfully opened after another 3 seconds or so which you can see here: https://gist.github.com/nadworny/c69659e65a7d6e8d96573db13d1f1095

For comparison here is bootstrapping log from localhost: https://gist.github.com/nadworny/c04d6baa571e5b7ddcbd8856cf22a390

What I also can't explain is what happens afterwards. I have a Mongo inbound adapter that looks as follow:

return IntegrationFlows.from(MongoDb.reactiveInboundChannelAdapter(mongoDbFactory,
        new Query().addCriteria(Criteria.where("status").is(ProcessingStatus.PROCESSED))
                .with(Sort.by(Sort.Direction.DESC, "modifiedDate")).limit(1))
                .collectionName("processingMetadata")
                .entityClass(ProcessingMetadata.class)
                .expectSingleResult(true),
        e -> e.poller(Pollers.fixedDelay(Duration.ofSeconds(pollingIntervalSeconds))))
        .<Mono<ProcessingMetadata>>handle((p, h) -> {
            // do something
        })

It should poll Mongo every 3 seconds but it actually never does (again it works locally without a problem).

The connectivity works fine after that as I have another process that is triggered by a file upload and it works correctly (data is written to MongoDB).

To be honest I'm a little bit confused which of the components is making troubles here so I hope you can help me narrow it down.

UPDATE1

I did some further debugging. Actually it's not a problem of mongo but the next handler after it which is Jpa Gateway:

.handle(Jpa.retrievingGateway(this.sourceEntityManagerFactory)
        .entityClass(DocumentHeader.class)
        .jpaQuery("from DocumentHeader d where d.modifiedDate > :modified")
        .parameterExpression("modified", "payload")
        .maxResults(maxResults), e -> e.id("retrieveDocumentHeader"))
.<List>handle((p, h) -> {
    if (p.isEmpty())
        this.advices.waitUntilCompletedAdvice().setWait(false);
    return p;
})
.channel(Channels.DOCUMENT_HEADER.name())

For some reason, while executing on AKS, the Jpa Handler won't be invoked and Spring Integration jumps directly to the next step:

2020-09-25 08:35:07.771 DEBUG 1 --- [ask-scheduler-3] o.s.d.m.core.ReactiveMongoTemplate       : find using query: { "status" : "PROCESSED"} fields: Document{{}} for class: class com.zurich.ccmc.data.orchestrator.domain.targetdb.ProcessingMetadata in collection: processingMetadata
2020-09-25 08:35:07.771 DEBUG 1 --- [ask-scheduler-3] o.s.i.e.SourcePollingChannelAdapter      : Poll resulted in Message: GenericMessage [payload=MonoNext, headers={mongo_collectionName=processingMetadata, id=4a26e221-deb9-f1af-1c35-7ba0d47042b1, timestamp=1601022907771}]
2020-09-25 08:35:07.778 DEBUG 1 --- [ask-scheduler-3] o.s.i.splitter.DefaultMessageSplitter    : handler 'bean 'setProcessingStatusToOpen.splitter#0' for component 'setProcessingStatusToOpen.org.springframework.integration.config.ConsumerEndpointFactoryBean#0'; defined in: 'class path resource [xxx/processing/ProcessingMetadataFlow.class]'; from source: 'bean method setProcessingStatusToOpen'' produced no reply for request Message: GenericMessage [payload=[], headers={mongo_collectionName=processingMetadata, id=0a446b4c-12fc-d72d-d4ad-8453eb51227c, timestamp=1601022907778}]

Solution

  • Found the problem. The spring.datasource.jdbc-url parameter was wrong (jdbc:sqlserver:// was missing at the beginning when deployed to AKS). I would expect some kind of a proper exception but there is only this warning:

    2020-09-24 14:33:04.710  WARN 1 --- [         task-1] o.h.e.j.e.i.JdbcEnvironmentInitiator     : HHH000342: Could not obtain connection to query metadata : Driver com.microsoft.sqlserver.jdbc.SQLServerDriver 
    accept jdbcUrl, xxx.database.windows.net
    

    What I also don't understand is why the Jpa.retrievingGateway didn't throw any exception and jump over to the next handler...