Классы конфигурации Spring Cloud Stream не загружаются - PullRequest
3 голосов
/ 05 апреля 2019

После обновления с Spring Boot 2.0.6 / Spring Cloud Finchley.RELEASE до Spring Boot 2.1.3 / Spring Cloud Greenwich.SR1 возникла очень странная проблема конфигурации / сканирования компонентов.

Приложение имеет следующую структуру:

  • основного приложения
  • сообщениями Пб
  • Обще Пб

Основное приложение помечено @SpringBootApplication(scanBasePackages = {"com.app.libs", "com.app"}), где пакеты com.app соответствуют пакетам main-application, а com.app.libs - пакеты библиотек.

Конфигурация commons-lib, которая является просто библиотекой framework-esque, имеет следующую основную точку входа в конфигурацию:

package com.app.libs.commons

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(CommonsConfiguration.class)
public @interface EnableCommons {
}

С CommonsConfiguration, имеющим:

package com.app.libs.commons.config

@Configuration
@ConditionalOnProperty(value = "com.app.config.commons", matchIfMissing = true)
@ComponentScan(basePackages = "com.app.libs.commons")
public class FrameworkConfiguration {

Таким образом, я могу в основном аннотировать один класс конфигурации в моем main-application и получать от него общие компоненты.

Конфигурация messaging-lib, которая использует Spring Cloud Stream, имеет следующие конфигурации:

@Configuration
@Import({ CustomBinding.class })
@PropertySource("classpath:kafka.properties")
@EnableBinding(Source.class)
@EnableAutoConfiguration
public class BindingConfiguration {
}

Конфигурация облачного потока выглядит следующим образом:

spring.cloud.stream.bindings.output.destination=${spring.application.name}
spring.cloud.stream.kafka.bindings.output.producer.sync=true
spring.cloud.stream.default.group=${spring.application.name}
spring.cloud.stream.default.producer.partitionCount=9
spring.cloud.stream.default.producer.partitionKeyExpression=headers.entityId
spring.cloud.stream.kafka.binder.autoAddPartitions=true
spring.cloud.stream.kafka.binder.autoCreateTopics=false

При запуске приложения выдается следующее сообщение об ошибке:

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'spring.cloud.stream.default.producer.partition-key-expression' to org.springframework.expression.Expression:

    Property: spring.cloud.stream.default.producer.partitionkeyexpression
    Value: headers.entityId
    Origin: "spring.cloud.stream.default.producer.partitionKeyExpression" from property source "class path resource [kafka.properties]"
    Reason: No converter found capable of converting from type [java.lang.String] to type [@com.fasterxml.jackson.databind.annotation.JsonSerialize org.springframework.expression.Expression]

Action:

Update your application's configuration

После просмотра исходного кода я заметил, что рассматриваемый SpelConverter - это тот, который должен быть инициализирован в SpelExpressionConverterConfiguration. Действительно, если я добавлю @Import({ SpelExpressionConverterConfiguration.class }) или @Import({ BindingServiceConfiguration }) (класс @Configuration, который импортирует SpelExpressionConverterConfiguration) к моему BindingConfiguration, преобразователь, похоже, инициализируется. Однако тогда возникает другая ошибка:

***************************
APPLICATION FAILED TO START
***************************

Description:

A component required a bean of type 'org.springframework.messaging.core.DestinationResolver' that could not be found.

The following candidates were found but could not be injected:
        - Bean method 'binderAwareChannelResolver' in 'BindingServiceConfiguration' not loaded because @ConditionalOnBean (types: org.springframework.cloud.stream.binder.BinderTypeRegistry; SearchStrategy: current) did not find any beans of type org.springframework.cloud.stream.binder.BinderTypeRegistry


Action:

Consider revisiting the entries above or defining a bean of type 'org.springframework.messaging.core.DestinationResolver' in your configuration.

Я не совсем уверен, что происходит. При отладке кажется, что загружены и BindingBeansRegistrar, и BinderFactoryConfiguration (классы, импортированные с помощью @EnableBinding), но сканирование не выполняется, а сканирование остальных компонентов просто не выполняется.

Я пытался импортировать классы конфигурации и / или сканировать пакеты самостоятельно, но в обоих случаях мне все еще не хватает компонента DestinationResolver, хотя он должен был быть инициализирован.

Я заметил, что до обновления также были некоторые проблемы: мне пришлось импортировать BindingServiceConfiguration, BinderFactoryConfiguration и SpelExpressionConverterConfiguration также вручную.

У кого-нибудь есть указания относительно того, что может быть причиной этой проблемы?

РЕДАКТИРОВАТЬ : Вот файлы build.grade (некоторые из них для краткости опущены):

Заявка build.gradle

apply from: new File(project(':scripts').projectDir, '/service-impl.gradle')

dependencies {
    implementation project(':dependency-A')
    implementation project(':dependency-B')
    implementation project(':messaging-library')

    testImplementation 'org.springframework.cloud:spring-cloud-stream-test-support'
}

service-impl.gradle содержание:

buildscript {
    apply from: new File(project(':buildscripts').projectDir, '/repositories.gradle') // Repository definitions
    apply from: new File(project(':buildscripts').projectDir, '/dm-boot.gradle') // DM via spring boot plugin
    apply from: new File(project(':buildscripts').projectDir, '/dm-versions.gradle') // DM versions
}

configurations {
    all*.exclude module: 'spring-boot-starter-tomcat'
    all*.exclude group: 'org.apache.bval'
}

artifacts {
    archives bootJar
}

dependencies {
    compileOnly 'org.projectlombok:lombok'

    compile 'org.springframework.boot:spring-boot-starter'
    compile 'org.springframework.boot:spring-boot-starter-web'
    compile 'org.springframework.boot:spring-boot-starter-jetty'
    compile 'org.springframework.boot:spring-boot-starter-actuator'
    compile 'org.springframework.boot:spring-boot-starter-cache'
    compile 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'

    compile 'org.springframework.cloud:spring-cloud-starter-config'

    testCompile 'junit:junit'
    testCompile 'org.springframework.boot:spring-boot-starter-test'

    testCompileOnly 'org.projectlombok:lombok'

    compile 'net.logstash.logback:logstash-logback-encoder'
}

Библиотека общин build.gradle

apply from: new File(project(':buildscripts').projectDir, '/repositories.gradle') // Repository definitions
apply from: new File(project(':buildscripts').projectDir, '/dm-plain.gradle') // DM via spring boot plugin
apply from: new File(project(':buildscripts').projectDir, '/dm-versions.gradle') // DM versions 
dependencies {

    api 'com.restfb:restfb:2.3.0'
    api 'commons-io:commons-io'
    implementation 'com.jcraft:jsch:0.1.54'

    //lombok
    compileOnly 'org.projectlombok:lombok'

    //spring
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-jetty'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    api 'org.springframework.security:spring-security-core'
    api 'org.springframework.security:spring-security-web'
    api 'org.springframework:spring-jdbc'
    api 'org.springframework.boot:spring-boot-starter-actuator'

    //thrift modules
    compileOnly 'com.facebook.swift:swift-codec'
    compileOnly 'com.facebook.swift:swift-service'

    //db modules
    api 'org.postgresql:postgresql'
    api 'org.flywaydb:flyway-core'
    api 'com.zaxxer:HikariCP'
    api 'org.jooq:jooq'

    //embedded pg modules
    compileOnly 'com.opentable.components:otj-pg-embedded'

    api group: 'net.minidev', name: 'json-smart', version: '2.2.1'
    api group: 'org.json', name: 'json', version: '20140107'

    //tests
    testImplementation 'junit:junit'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'com.opentable.components:otj-pg-embedded'

    testImplementation 'org.springframework.security:spring-security-core'
    testImplementation 'org.springframework.security:spring-security-web'
    testImplementation 'org.springframework.security:spring-security-config'
    testImplementation 'org.springframework:spring-jdbc'
    testImplementation 'org.springframework.boot:spring-boot-starter-actuator'

    testImplementation 'org.apache.sshd:sshd-core:1.7.0' // sftpFileTransfer testing - embedded sftp server

    testCompileOnly 'org.projectlombok:lombok'
    testCompileOnly 'javax.servlet:javax.servlet-api'


}

Messaging Lib build.gradle (используется как автономная библиотека, поэтому не использует вышеуказанные .gradle файлы)

buildscript {
    ext {
        springBootVersion = '2.1.3.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply from: new File(rootDir.parentFile, 'buildscripts/publish.gradle')
apply from: new File(rootDir.parentFile, 'buildscripts/coverage.gradle')

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.app.libs.messaging'
version = '0.0.3'
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/snapshot" }
    maven { url "https://repo.spring.io/milestone" }
}

ext {
    springCloudVersion = 'Greenwich.SR1'
    jacksonVersion = '2.9.6'
    lombokVersion = '1.16.18'
    jooqVersion = '3.11.2'
    flywayVersion = '5.2.1'
}

dependencies {

    compile 'org.aspectj:aspectjweaver'
    compile 'org.springframework:spring-tx'
    compile 'org.springframework.cloud:spring-cloud-stream'
    compile 'org.springframework.cloud:spring-cloud-stream-binder-kafka'
    compile 'org.apache.commons:commons-lang3:3.5'
    compile 'org.javassist:javassist:3.22.0-GA'
    compile "org.flywaydb:flyway-core:${flywayVersion}"

    compileOnly "org.jooq:jooq:${jooqVersion}"
    compileOnly "org.projectlombok:lombok:${lombokVersion}"

    testCompileOnly "org.projectlombok:lombok:${lombokVersion}"

    testCompile 'org.springframework.boot:spring-boot-starter-test'
    testCompile 'org.springframework.boot:spring-boot-starter-json'
    testCompile 'org.springframework.cloud:spring-cloud-stream-test-support'

    testCompile "com.fasterxml.jackson.core:jackson-core:${jacksonVersion}"
    testCompile "com.fasterxml.jackson.core:jackson-databind:${jacksonVersion}"

    testCompile 'junit:junit:4.12'
    testCompile "org.jooq:jooq:${jooqVersion}"
    testCompile "org.flywaydb:flyway-core:${flywayVersion}"

    testCompile 'org.postgresql:postgresql:42.2.2'
    testCompile 'com.opentable.components:otj-pg-embedded:0.13.0'
    testCompile 'org.springframework:spring-jdbc'
}

dependencyManagement {
    // disable maven exclusion to enhance gradle import performance
    // https://github.com/spring-gradle-plugins/dependency-management-plugin/issues/153
    applyMavenExclusions = false

    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

jar.enabled = true
bootJar.enabled = false

Я пытался опустить все файлы, которые, по моему мнению, не должны быть связаны.

...