This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 083de439bfd CAMEL-21478: [REST-OpenAPI] Enabling class binding using
schema title (#16564)
083de439bfd is described below
commit 083de439bfd9dbaebbdaecaff40ec6168ddb0e7a
Author: Chamodya Dias <[email protected]>
AuthorDate: Mon Dec 16 08:42:24 2024 +0000
CAMEL-21478: [REST-OpenAPI] Enabling class binding using schema title
(#16564)
* Enabling class binding using schema title
* Updated documentation
* build command output
---
.../camel/component/rest/openapi/OpenApiUtils.java | 3 +-
.../component/rest/openapi/OpenApiUtilsTest.java | 124 +++++++++++++++++++++
.../component/rest/openapi/TagRequestDto.java | 39 +++++++
.../component/rest/openapi/TagResponseDto.java | 39 +++++++
.../modules/ROOT/pages/rest-dsl-openapi.adoc | 19 ++++
5 files changed, 223 insertions(+), 1 deletion(-)
diff --git
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/OpenApiUtils.java
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/OpenApiUtils.java
index 77c860f19d9..099050aef0c 100644
---
a/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/OpenApiUtils.java
+++
b/components/camel-rest-openapi/src/main/java/org/apache/camel/component/rest/openapi/OpenApiUtils.java
@@ -190,6 +190,7 @@ public class OpenApiUtils {
return primitiveType;
}
}
+ String schemaTitle = schema.getTitle();
Pattern classNamePattern = Pattern.compile(".*\\/(.*)");
schemaName = Optional.ofNullable(schemaName)
.orElse(Optional.ofNullable(schema.get$ref()).orElse(schema.getType()));
@@ -199,7 +200,7 @@ public class OpenApiUtils {
: schemaName;
return scannedClasses.stream()
- .filter(aClass ->
aClass.getSimpleName().equals(classToFind))
+ .filter(aClass ->
aClass.getSimpleName().equals(classToFind) ||
aClass.getSimpleName().equals(schemaTitle)) //use either the name or title of
schema to find the class
.findFirst()
.orElse(null);
}
diff --git
a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/OpenApiUtilsTest.java
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/OpenApiUtilsTest.java
index ee302af3825..c5a44a31150 100644
---
a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/OpenApiUtilsTest.java
+++
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/OpenApiUtilsTest.java
@@ -16,14 +16,24 @@
*/
package org.apache.camel.component.rest.openapi;
+import java.util.Map;
+
+import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Content;
+import io.swagger.v3.oas.models.media.IntegerSchema;
import io.swagger.v3.oas.models.media.MediaType;
+import io.swagger.v3.oas.models.media.ObjectSchema;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.media.StringSchema;
+import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
+import org.apache.camel.impl.DefaultCamelContext;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
public class OpenApiUtilsTest {
@Test
@@ -40,6 +50,82 @@ public class OpenApiUtilsTest {
assertThat(utils.getProduces(operation)).isEqualTo("application/json,application/problem+json,application/xml");
}
+ @Test
+ public void shouldReturnCorrectRequestClassNameForSchemaName() {
+ //When the class name is provided in the schema name
+ String schemaName = "Tag";
+ String bindingPackagePath = OpenApiUtils.class.getPackage().getName();
+
+ Operation operation = new Operation();
+ Schema<Object> tagSchema = createTagSchema();
+ RequestBody requestBody = createRequestBody(tagSchema);
+ operation.requestBody(requestBody);
+
+ Components components = new Components();
+ components.addSchemas(schemaName, tagSchema);
+
+ OpenApiUtils utils = new OpenApiUtils(new DefaultCamelContext(),
bindingPackagePath, components);
+ assertEquals(Tag.class.getName(), utils.manageRequestBody(operation));
+ }
+
+ @Test
+ public void shouldReturnCorrectRequestClassNameForSchemaTitle() {
+ String schemaName = "TagSchema";
+ //When the class name is provided in the schema title instead of
schema name
+ String schemaTitle = "TagRequestDto";
+ String bindingPackagePath = OpenApiUtils.class.getPackage().getName();
+
+ Operation operation = new Operation();
+ Schema<Object> tagSchema = createTagSchema(schemaTitle);
+ RequestBody requestBody = createRequestBody(tagSchema);
+ operation.requestBody(requestBody);
+
+ Components components = new Components();
+ components.addSchemas(schemaName, tagSchema);
+
+ OpenApiUtils utils = new OpenApiUtils(new DefaultCamelContext(),
bindingPackagePath, components);
+ assertEquals(TagRequestDto.class.getName(),
utils.manageRequestBody(operation));
+ }
+
+ @Test
+ public void shouldReturnCorrectResponseClassNameForSchemaName() {
+ //When the class name is provided in the schema name
+ String schemaName = "Tag";
+ String bindingPackagePath = OpenApiUtils.class.getPackage().getName();
+ Schema<Object> tagSchema = createTagSchema();
+
+ Operation operation = new Operation();
+ ApiResponses responses = new ApiResponses();
+ responses.addApiResponse("200", createResponse(tagSchema));
+ operation.setResponses(responses);
+
+ Components components = new Components();
+ components.addSchemas(schemaName, tagSchema);
+
+ OpenApiUtils utils = new OpenApiUtils(new DefaultCamelContext(),
bindingPackagePath, components);
+ assertEquals(Tag.class.getName(), utils.manageResponseBody(operation));
+ }
+
+ @Test
+ public void shouldReturnCorrectResponseClassNameForSchemaTitle() {
+ String schemaName = "TagSchema";
+ //When the class name is provided in the schema title instead of
schema name
+ String schemaTitle = "TagResponseDto";
+ String bindingPackagePath = OpenApiUtils.class.getPackage().getName();
+
+ Operation operation = new Operation();
+ Schema<Object> tagSchema = createTagSchema(schemaTitle);
+ ApiResponses responses = new ApiResponses();
+ responses.addApiResponse("200", createResponse(tagSchema));
+ operation.setResponses(responses);
+
+ Components components = new Components();
+ components.addSchemas(schemaName, tagSchema);
+
+ OpenApiUtils utils = new OpenApiUtils(new DefaultCamelContext(),
bindingPackagePath, components);
+ assertEquals(TagResponseDto.class.getName(),
utils.manageResponseBody(operation));
+ }
+
private ApiResponse createResponse(String... contentTypes) {
ApiResponse response = new ApiResponse();
@@ -51,4 +137,42 @@ public class OpenApiUtilsTest {
return response;
}
+
+ private ApiResponse createResponse(Schema<?> schema) {
+ ApiResponse response = new ApiResponse();
+ Content content = new Content();
+ MediaType mediaType = new MediaType();
+ mediaType.setSchema(schema);
+ content.addMediaType("application/json", mediaType);
+ response.setContent(content);
+
+ return response;
+ }
+
+ private RequestBody createRequestBody(Schema<?> schema) {
+ RequestBody requestBody = new RequestBody();
+ Content content = new Content();
+ MediaType mediaType = new MediaType();
+ mediaType.setSchema(schema);
+ content.addMediaType("application/json", mediaType);
+ requestBody.setContent(content);
+ return requestBody;
+ }
+
+ private static Schema<Object> createTagSchema() {
+ Schema<Object> tagSchema = new ObjectSchema();
+ Schema<Number> idSchema = new IntegerSchema();
+ Schema<String> nameSchema = new StringSchema();
+ tagSchema.setProperties(Map.of(
+ "id", idSchema,
+ "name", nameSchema));
+ tagSchema.setDescription("Schema representing the Tag class");
+ return tagSchema;
+ }
+
+ private static Schema<Object> createTagSchema(String title) {
+ Schema<Object> tagSchema = createTagSchema();
+ tagSchema.setTitle(title);
+ return tagSchema;
+ }
}
diff --git
a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/TagRequestDto.java
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/TagRequestDto.java
new file mode 100644
index 00000000000..35a857728cc
--- /dev/null
+++
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/TagRequestDto.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.rest.openapi;
+
+//Sample class used for testing
+public class TagRequestDto {
+ private Long id;
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git
a/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/TagResponseDto.java
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/TagResponseDto.java
new file mode 100644
index 00000000000..fb07435cb36
--- /dev/null
+++
b/components/camel-rest-openapi/src/test/java/org/apache/camel/component/rest/openapi/TagResponseDto.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.rest.openapi;
+
+//Sample class used for testing
+public class TagResponseDto {
+ private Long id;
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
b/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
index b68be20880c..d5300db69d1 100644
--- a/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
+++ b/docs/user-manual/modules/ROOT/pages/rest-dsl-openapi.adoc
@@ -292,6 +292,25 @@ Here Camel will detect the `schema` part:
And compute the class name as `Pet` and attempt to discover this class from
classpath scanning specified via the `bindingPackageScan` option.
+You can also use `title` attribute of the Schema to provide the name of the
POJO class. This is helpful when you need to use one name for the Schema in the
OpenAPI contract and use another name for the actual POJO class in the
implementation.
+
+[source,json]
+----
+"components": {
+ "schemas": {
+ "Pet": {
+ "type": "object",
+ "title": "PetResponseDto",
+ "properties": {
+ ...
+ }
+ }
+ }
+ },
+----
+
+Here Camel will detect the class name as `PetResponseDto` and try to discover
it from the classpath. This can be used for both Responses and RequestBodies.
+
You can source code generate Java POJO classes from an OpenAPI specification
via tooling such as the `swagger-codegen-maven-plugin` Maven plugin.
For more details, see this
https://github.com/apache/camel-spring-boot-examples/tree/main/openapi-contract-first[Spring
Boot example].