Spring Boot下Apache Camel加载多OpenAPI文件报错咨询
问题描述
SpringBoot集成Apache Camel时,采用契约优先的OpenAPI方式配置路由,单个OpenAPI文件加载正常,加载多个独立文件时启动失败,错误信息:
org.apache.camel.FailedToStartRouteException: Failed to start route route2 because of Multiple consumers for the same endpoint is not allowed: platform-http:///?matchOnUriPrefix=true
相关配置
路由配置文件
foo.camel.yaml
- rest: openApi: specification: "openapi/foo.yml" missingOperation: "ignore" - route: id: "foo" from: uri: "direct:foo" steps: - log: message: "Foo works"
foobar.camel.yaml
- rest: openApi: specification: "openapi/foobar.yml" missingOperation: "ignore" - route: id: "foobar" from: uri: "direct:foobar" steps: - log: message: "foobar works"
OpenAPI文件
openapi/foo.yml
openapi: "3.0.3" info: title: "FOO" tags: - name: "foo" description: "Foo Test Openapi file" paths: /foo: post: tags: - "foo" summary: "Interface for foo operation" operationId: "foo" requestBody: content: application/json: schema: type: "object" responses: "200": description: "Successful operation foo"
openapi/foobar.yml
openapi: "3.0.3" info: title: "FOOBAR" tags: - name: "foobar" description: "Foobar Test Openapi file" paths: /foobar: post: tags: - "foobar" summary: "Interface for foobar operation" operationId: "foobar" requestBody: content: application/json: schema: type: "object" responses: "200": description: "Successful operation foobar"
pom.xml依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.3.5</version> <relativePath/> </parent> <groupId>com.test</groupId> <artifactId>camel-rest-dsl</artifactId> <version>0.0.1-SNAPSHOT</version> <name>camel-rest-dsl</name> <description>Demo project for Camel Rest DSL</description> <properties> <java.version>17</java.version> <camel-springboot.version>4.8.2</camel-springboot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-yaml-dsl-starter</artifactId> <version>${camel-springboot.version}</version> </dependency> <dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-http-starter</artifactId> <version>${camel-springboot.version}</version> </dependency> <dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-rest-openapi-starter</artifactId> <version>${camel-springboot.version}</version> </dependency> <dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-platform-http-starter</artifactId> <version>${camel-springboot.version}</version> </dependency> <dependency> <groupId>org.apache.camel.springboot</groupId> <artifactId>camel-direct-starter</artifactId> <version>${camel-springboot.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
报错原因
每个rest节点配置OpenAPI时,默认会自动创建一个绑定到platform-http:///?matchOnUriPrefix=true的消费者端点。多个rest节点重复创建同一端点的消费者,违反了Apache Camel中同一端点仅允许一个消费者的规则,导致启动失败。
解决方案
方案1:合并OpenAPI文件
将多个OpenAPI文件的paths、tags等内容合并到单个文件中,然后通过一个rest节点引用该合并文件,避免重复创建端点消费者。
例如创建openapi/combined.yml:
openapi: "3.0.3" info: title: "Combined API" tags: - name: "foo" description: "Foo Test Openapi file" - name: "foobar" description: "Foobar Test Openapi file" paths: /foo: post: tags: - "foo" summary: "Interface for foo operation" operationId: "foo" requestBody: content: application/json: schema: type: "object" responses: "200": description: "Successful operation foo" /foobar: post: tags: - "foobar" summary: "Interface for foobar operation" operationId: "foobar" requestBody: content: application/json: schema: type: "object" responses: "200": description: "Successful operation foobar"
然后修改路由配置为单个rest节点:
- rest: openApi: specification: "openapi/combined.yml" missingOperation: "ignore" - route: id: "foo" from: uri: "direct:foo" steps: - log: message: "Foo works" - route: id: "foobar" from: uri: "direct:foobar" steps: - log: message: "foobar works"
方案2:为每个OpenAPI配置独立Base Path
在每个OpenAPI文件中指定专属的base path,同时在Camel的rest节点中绑定对应路径,让每个rest节点关联不同的platform-http端点。
- 修改OpenAPI文件添加
servers配置:
openapi/foo.yml新增:
servers: - url: /foo-api
openapi/foobar.yml新增:
servers: - url: /foobar-api
- 修改路由配置的
rest节点,指定basePath:
foo.camel.yaml:
- rest: openApi: specification: "openapi/foo.yml" missingOperation: "ignore" component: "platform-http" basePath: "/foo-api" - route: id: "foo" from: uri: "direct:foo" steps: - log: message: "Foo works"
foobar.camel.yaml:
- rest: openApi: specification: "openapi/foobar.yml" missingOperation: "ignore" component: "platform-http" basePath: "/foobar-api" - route: id: "foobar" from: uri: "direct:foobar" steps: - log: message: "foobar works"
此时两个rest节点分别绑定platform-http:///foo-api?matchOnUriPrefix=true和platform-http:///foobar-api?matchOnUriPrefix=true,不存在端点重复问题。
方案3:通过全局RestConfiguration加载多文件
在Camel 4.x及以上版本中,支持通过全局restConfiguration的openApi.specification配置逗号分隔的多个文件路径,仅创建一个platform-http消费者端点,统一加载所有OpenAPI文件。
创建统一的路由配置文件(如combined-routes.camel.yaml):
- restConfiguration: component: "platform-http" bindingMode: "auto" openApi: specification: "openapi/foo.yml,openapi/foobar.yml" missingOperation: "ignore" - route: id: "foo" from: uri: "direct:foo" steps: - log: message: "Foo works" - route: id: "foobar" from: uri: "direct:foobar" steps: - log: message: "foobar works"
同时删除原有的foo.camel.yaml和foobar.camel.yaml中的rest节点,避免重复配置。
内容的提问来源于stack exchange,提问作者Malfestio

