spring - 在多模块 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
达到:
- 微服务 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})")
;
}
}
解决方案
推荐阅读
- r - 为列 R 中的每个重复值分配一个唯一的 ID 号
- projection - WinBugs 中的“此初始值不对应于随机节点”
- html - 默认值的下拉验证
- javascript - CryptoJS 和 openssl_decrypt 不产生相同的结果
- excel - 将从 VBA 创建的工作簿文件保存到 Sharepoint
- configuration - Snort 配置死胡同
- python - if 语句和 randint 的 Python 问题
- css - 如何将图像与文本并排放置?
- javascript - 使用 React ref 存储类实例?
- python - 将列表字典的值转换为浮点数