首页 > 解决方案 > 在多模块 Gradle 项目中为独立 Camel 微服务配置 Camel-Spring

问题描述

目标:将 Claus Ibsen 的 Camel in Action 第 7 章中的 Prototype 微服务示例改编为 Gradle 多模块项目。在其他资源中,我遵循了 Spring Guide to ' Creating a Multi Module Project '。

项目结构:

+ main-mm-build
  |--+ src 
        |--+ main
              |--+ java // Spring Boot microservice (A) in this tree
  |--+ build.gradle
  |--+ settings.gradle
  |--+ contact-manager // standalone-camel-spring microservice (B)
        |--+ src 
              |--+ main
                    |--+ java // standalone-camel-spring microservice (B) here
        |--+ build.gradle

达到:

  1. 微服务 A(Spring Boot Rest 控制器)可以调用微服务 B(独立 Camel 在码头上公开 rest(),无需 Spring DI)。

但我真正想要的是在微服务 B 中使用 Spring DI(没有 Spring Boot)。在对 camel-spring 进行更改后,我得到一个错误。

它可能弄乱了 Gradle 配置,但我可以使用一些帮助。

main-mm-build/contact-manager$ ../gradlew build
main-mm-build/contact-manager$ java -jar build/libs/contact-manager-1.0.jar
.
.
.
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: rest://get:/contact-manager?consumerComponentName=jetty&consumes=application%2Fjson&outType=...dto.ContactDto%5B%5D&produces=application%2Fjson&routeId=route2 due to: null
        at ...impl.engine.AbstractCamelContext.getEndpoint(AbstractCamelContext.java:801)
Caused by: java.lang.NullPointerException
        at ...camel.spring.spi.ApplicationContextBeanRepository.lookupByNameAndType(Ap..j:45)

根项目 Gradle 文件:

plugins {
    id 'org.springframework.boot' version '2.3.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
    id 'java'
}
sourceCompatibility = '11'

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-tomcat'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
    useJUnitPlatform()
}

allprojects {
    group = 'el.cam'
    repositories {
        jcenter()
    }
}

subprojects {
    version = '1.0'
}

设置.gradle:

    rootProject.name = 'main-mm-build'
    include 'contact-manager'

微服务 B(联系人管理器)build.gradle:

plugins {
    id 'org.springframework.boot'
    id 'io.spring.dependency-management'
    id 'java'
    id 'application'
}

sourceCompatibility = '11'

mainClassName = 'el.cam.contacts.ContactManagerApplication'

task fatJar(type: Jar) {
    manifest {
        attributes (
                'Main-Class': mainClassName
        )
    }
    baseName = 'contact-manager' + '-all'
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
}

dependencies {
    implementation(platform("org.springframework.boot:spring-boot-dependencies:2.3.1.RELEASE"))
    implementation( platform("org.apache.camel:camel-spring-boot-dependencies:3.0.0-RC3") )

    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.apache.camel:camel-spring-boot-starter'
    implementation 'org.apache.camel:camel-rest-starter'
    implementation 'org.apache.camel:camel-jetty-starter'
    implementation 'org.apache.camel:camel-jackson-starter'
    implementation 'org.apache.camel:camel-swagger-java-starter'//  '3.0.0-RC3'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'


    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
    useJUnitPlatform()
}

ContactManagerApplication.java (我想知道我是否在这里错误地配置了 Spring Camel。我找到的所有示例都是基于 Spring Boot 自动配置的,所以我只是边走边想。)

import el.cam.contacts.configuration.ContactManagerConfiguration;
import org.apache.camel.spring.Main;

public class ContactManagerApplication {

    private static final Logger LOG = LoggerFactory.getLogger(ContactManagerApplication.class);

    public static void main(String[] args) throws Exception {
        Main main = new Main();
        main.setApplicationContext(createSpringApplicationContext());
//        main.addRoutesBuilder(contactManagerController); // DI using Spring Autowiring 
        main.run();
    }

    private static AbstractApplicationContext createSpringApplicationContext() {
        AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext();
        appContext.register(ContactManagerConfiguration.class);
        appContext.refresh();
        return appContext;
    }
}

配置类:


@Configuration
@ComponentScan(basePackages = "el.cam.contacts")
public class ContactManagerConfiguration {

    @Autowired
    ContactManagerController contactManagerController;

    @Bean
    public CamelContext camelContext() throws Exception {
        SpringCamelContext camelContext = new SpringCamelContext();
        camelContext.addRoutes(contactManagerController);
        camelContext.setPropertiesComponent(properties());
        camelContext.addComponent("rest", rest());
        camelContext.addComponent("rest-api", restApi());
        camelContext.addComponent("jetty", jetty());
        return camelContext;
    }


    @Bean
    public PropertiesComponent properties() throws Exception {
        PropertiesComponent properties = new PropertiesComponent();
        properties.setLocation("classpath:application.properties");
        return properties;
    }


    @Bean
    public RestComponent rest() {
        RestComponent rest = new RestComponent();
        return rest;
    }

    @Bean
    public RestApiComponent restApi() {
        RestApiComponent restApi = new RestApiComponent();
        return restApi;
    }

    @Bean
    public JettyHttpComponent jetty() {
        JettyHttpComponent jettyHttpComponent = new JettyHttpComponent9();
        return jettyHttpComponent;
    }

控制器类:


@Component
public class ContactManagerController extends RouteBuilder {
    @Autowired
    ContactManagerService contactManagerService;

    @Override
    public void configure() throws Exception {
        // before Camel-Spring, was using this to bind serviceBean in camel registry
//        getContext().getRegistry().bind("contactManagerService", new ContactManagerService());

        // TODO using default. camel property sources not picking up application.properties!
         restConfiguration("jetty").port("{{port:8282}}").contextPath("api")
                .bindingMode(RestBindingMode.json)
                .dataFormatProperty("disableFeatures", "FAIL_ON_EMPTY_BEANS")
                .apiContextPath("api-doc")
                .enableCORS(true);

        // define the rest service
        rest("/contact-manager").consumes("application/json").produces("application/json")
                .get().outType(ContactDto[].class)
                .to("bean:contactManagerService?method=getContacts(${header.contactType})")
        ;
    }
}

标签: springgradleapache-camelmicroservicesmulti-module

解决方案


推荐阅读