I am trying to set up a REST service with Apache Camel (v3.20.0) that, among other routes, offers a POST endpoint that receives a payload in the request body.
I am trying to document my REST interface using the camel-openapi-java package using Java DSL. However, when trying to specify the expected body parameter using .param().name("body").type(body).description("The post object that is to be published").endParam()
, the parameter is not added to the resulting OpenAPI JSON document.
This is the definition of my REST route:
rest().description(serviceConfig.getServiceName(), serviceConfig.getServiceName(), "en")
.post("/post")
.description(serviceConfig.getServiceName(), "Receives a post to be published", "en")
.type(Post.class)
.param().name("body").type(body).description("The post that is to be published.").endParam()
.to("direct:servicePipeline");
My Rest Configuration is:
restConfiguration()
.component("servlet")
.host("0.0.0.0")
.port(8080)
.bindingMode(RestBindingMode.json)
.contextPath(serviceConfig.getVersionPath() + "/" + serviceConfig.getAffordancePath())
.enableCORS(true)
.apiContextPath("docs")
.apiProperty("api.title", serviceConfig.getServiceName())
.apiProperty("api.version", "1.0")
.apiProperty("cors", "true");
The resulting Open API JSON is generated without the request body parameter and reads as:
{"openapi":"3.0.2","info":{"version":"1.0"},"servers":[{"url":"/api/v1/organicposts"}],"paths":{"/post":{"post":{"summary":"Receives a post to be published","operationId":"verb1","responses":{"200":{}}}}},"components":{"schemas":{}}}
When I try to declare RestParamType.path and RestParamType.query parameters, it works perfectly fine for those. Any parameter of type RestParamType.body
, however is ignored.
The class Post.java
that is expected as payload in the POST request body is implemented as:
@Data
@NoArgsConstructor
@Schema(description = "Post Object as expected by the service")
public class Post {
@Schema(
name="id",
description = "ID by which post is stored in local database",
example="42",
implementation = Integer.class,
required = true
)
Integer id; // as stored in the posts database
@Schema(
name="partnerId",
description = "ID of partner on behalf of which the post is to be published",
example="42",
implementation = Integer.class,
required = true
)
Integer partnerId ; // as stored in partners table
@Schema(
name="textContent",
description = "Text content of the post.",
example="This is a descriptive comment of the post",
implementation = String.class,
required = true
)
String textContent ;
@Schema(
name="type",
description = "Type of the post. Determines the expected type of media declared for the post.",
example="VIDEO",
implementation = PostType.class,
required = true
)
PostType type;
@ArraySchema
@Schema(
name="media",
description = "Media objects declared for the post. Single element expected for IMAGE, and VIDEO. More than one element expected for MULTI_IMAGE",
required = true)
SpMedia[] media ;
}
The pom.xml:
<properties>
<camel.version>3.20.0</camel.version>
<java.version>17</java.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-spring-junit5</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-rest-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-servlet-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jackson-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-http-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<!-- Swagger and OpenAPI dependencies -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-openapi-java</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-springdoc-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>
What am I missing to have the request body parameter correctly included into the OpenAPI document?
You need to supply the expected media type(s) for the body payload. You can do that in the Camel REST DSL with the .consumes()
method. For example:
rest().description(serviceConfig.getServiceName(), serviceConfig.getServiceName(), "en")
.post("/post")
.description(serviceConfig.getServiceName(), "Receives a post to be published", "en")
.type(Post.class)
.consumes("application/json")
.param().name("body").type(body).description("The post that is to be published.").endParam()
.to("direct:servicePipeline");