You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/03/15 13:04:30 UTC

[camel-spring-boot] branch main updated: [CAMEL-17791]add tests in camel-openapi-starter (#465)

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-spring-boot.git


The following commit(s) were added to refs/heads/main by this push:
     new f167f45  [CAMEL-17791]add tests in camel-openapi-starter (#465)
f167f45 is described below

commit f167f458464a244bab5fcbc465212e3bbbcad0e7
Author: Federico Mariani <34...@users.noreply.github.com>
AuthorDate: Tue Mar 15 14:04:25 2022 +0100

    [CAMEL-17791]add tests in camel-openapi-starter (#465)
---
 .../camel-openapi-java-starter/pom.xml             |  16 ++
 .../java/org/apache/camel/openapi/BookOrder.java   |  41 ++++
 .../org/apache/camel/openapi/ComplexTypesTest.java | 206 +++++++++++++++++++++
 .../java/org/apache/camel/openapi/DayResponse.java |  30 +++
 .../org/apache/camel/openapi/DummyBookService.java |  18 ++
 .../camel/openapi/DummyRestConsumerFactory.java    |  50 +++++
 .../org/apache/camel/openapi/DummyUserService.java |  18 ++
 .../java/org/apache/camel/openapi/LineItem.java    |  39 ++++
 ...estOpenApiModelApiSecurityRequirementsTest.java | 156 ++++++++++++++++
 .../RestOpenApiReaderApiDocsOverrideTest.java      | 149 +++++++++++++++
 .../openapi/RestOpenApiReaderApiDocsTest.java      | 154 +++++++++++++++
 .../openapi/RestOpenApiReaderContextPathTest.java  | 181 ++++++++++++++++++
 .../openapi/RestOpenApiReaderDayOfWeekTest.java    | 161 ++++++++++++++++
 ...RestOpenApiReaderEnableVendorExtensionTest.java | 173 +++++++++++++++++
 .../RestOpenApiReaderFileResponseModelTest.java    | 140 ++++++++++++++
 .../RestOpenApiReaderModelApiSecurityTest.java     | 198 ++++++++++++++++++++
 .../RestOpenApiReaderModelBookOrderTest.java       | 178 ++++++++++++++++++
 .../camel/openapi/RestOpenApiReaderModelTest.java  | 172 +++++++++++++++++
 .../RestOpenApiReaderOverrideHostApiDocsTest.java  | 107 +++++++++++
 .../RestOpenApiReaderPropertyPlaceholderTest.java  | 136 ++++++++++++++
 .../camel/openapi/RestOpenApiReaderTest.java       | 176 ++++++++++++++++++
 .../openapi/RestOpenApiV2SecuritySchemesTest.java  | 133 +++++++++++++
 .../openapi/RestOpenApiV3SecuritySchemesTest.java  | 163 ++++++++++++++++
 ...pringRestOpenApiReaderModelApiSecurityTest.java | 151 +++++++++++++++
 .../test/java/org/apache/camel/openapi/User.java   |  47 +++++
 .../org/apache/camel/openapi/model/CustomData.java |  26 +++
 .../openapi/model/GenericComplexRequestType.java   |  52 ++++++
 .../apache/camel/openapi/model/GenericData.java    |  23 +++
 .../openapi/model/SampleComplexRequestType.java    |  71 +++++++
 .../openapi/model/SampleComplexResponseType.java   |  59 ++++++
 .../openapi/producer/DummyRestProducerFactory.java |  62 +++++++
 .../camel/openapi/producer/RestOpenApiGetTest.java |  86 +++++++++
 .../producer/RestOpenApiGetUriParamTest.java       |  86 +++++++++
 .../src/test/resources/hello-api.json              |  41 ++++
 .../src/test/resources/log4j2.properties           |  28 +++
 ...SpringRestOpenApiReaderModelApiSecurityTest.xml |  49 +++++
 .../openapi/V2SchemaForComplexTypesRequest.json    | 158 ++++++++++++++++
 .../openapi/V2SchemaForComplexTypesResponse.json   | 101 ++++++++++
 .../openapi/V3SchemaForComplexTypesRequest.json    | 168 +++++++++++++++++
 .../openapi/V3SchemaForComplexTypesResponse.json   | 111 +++++++++++
 .../src/test/resources/petstore-v3.json            |   1 +
 .../src/test/resources/petstore.json               |   1 +
 42 files changed, 4116 insertions(+)

diff --git a/components-starter/camel-openapi-java-starter/pom.xml b/components-starter/camel-openapi-java-starter/pom.xml
index 81fbaaf..1eb9106 100644
--- a/components-starter/camel-openapi-java-starter/pom.xml
+++ b/components-starter/camel-openapi-java-starter/pom.xml
@@ -44,6 +44,22 @@
       <artifactId>swagger-parser-v3</artifactId>
       <version>${swagger-parser-v3-version}</version>
     </dependency>
+    <!-- test dependencies -->
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-slf4j-impl</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <scope>test</scope>
+    </dependency>
     <!--START OF GENERATED CODE-->
     <dependency>
       <groupId>org.apache.camel.springboot</groupId>
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/BookOrder.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/BookOrder.java
new file mode 100644
index 0000000..56c6b60
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/BookOrder.java
@@ -0,0 +1,41 @@
+/*
+ * 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.openapi;
+
+import java.util.List;
+
+public class BookOrder {
+
+	private String id;
+	private List<LineItem> items;
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public List<LineItem> getItems() {
+		return items;
+	}
+
+	public void setItems(List<LineItem> items) {
+		this.items = items;
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/ComplexTypesTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/ComplexTypesTest.java
new file mode 100644
index 0000000..399ffcd
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/ComplexTypesTest.java
@@ -0,0 +1,206 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestBindingMode;
+import org.apache.camel.model.rest.RestDefinition;
+import org.apache.camel.openapi.model.SampleComplexRequestType;
+import org.apache.camel.openapi.model.SampleComplexResponseType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				ComplexTypesTest.class,
+				ComplexTypesTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class
+		}
+)
+public class ComplexTypesTest {
+	private static final Logger LOG = LoggerFactory.getLogger(ComplexTypesTest.class);
+
+	@SuppressWarnings("unused")
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@Autowired
+	CamelContext context;
+
+	// *************************************
+	// Config
+	// *************************************
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest().securityDefinitions()
+							.oauth2("global")
+							.accessCode("https://AUTHORIZATION_URL", "https://TOKEN_URL")
+							.withScope("groups", "Required scopes for Camel REST APIs");
+
+					rest().post("/complexRequest")
+							.description("Demo complex request type")
+							.type(SampleComplexRequestType.class)
+							.consumes("application/json")
+							.produces("text/plain")
+							.bindingMode(RestBindingMode.json)
+							.responseMessage()
+							.code(200)
+							.message("Receives a complex object as parameter")
+							.endResponseMessage()
+							.outType(SampleComplexResponseType.InnerClass.class)
+							.to("direct:request");
+					from("direct:request")
+							.routeId("complex request type")
+							.log("/complex request invoked");
+
+					rest().get("/complexResponse")
+							.description("Demo complex response type")
+							.type(SampleComplexRequestType.InnerClass.class)
+							.consumes("application/json")
+							.outType(SampleComplexResponseType.class)
+							.produces("application/json")
+							.bindingMode(RestBindingMode.json)
+							.responseMessage()
+							.code(200)
+							.message("Returns a complex object")
+							.endResponseMessage()
+							.to("direct:response");
+
+					from("direct:response")
+							.routeId("complex response type")
+							.log("/complex invoked")
+							.setBody(constant(new SampleComplexResponseType()));
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testV3SchemaForComplexTypesRequest() throws Exception {
+		checkSchemaGeneration("/complexRequest", "3.0", "V3SchemaForComplexTypesRequest.json");
+	}
+
+	@Test
+	public void testV2SchemaForComplexTypesRequest() throws Exception {
+		checkSchemaGeneration("/complexRequest", "2.0", "V2SchemaForComplexTypesRequest.json");
+	}
+
+	@Test
+	public void testV3SchemaForComplexTypesResponse() throws Exception {
+		checkSchemaGeneration("/complexResponse", "3.0", "V3SchemaForComplexTypesResponse.json");
+	}
+
+	@Test
+	public void testV2SchemaForComplexTypesResponse() throws Exception {
+		checkSchemaGeneration("/complexResponse", "2.0", "V2SchemaForComplexTypesResponse.json");
+	}
+
+	private void checkSchemaGeneration(String uri, String apiVersion, String schemaResource) throws Exception {
+		BeanConfig config = getBeanConfig(apiVersion);
+
+		List<RestDefinition> rests = ((ModelCamelContext) context).getRestDefinitions().stream()
+				// So we get the security schema and the route schema
+				.filter(def -> def.getVerbs().isEmpty() || def.getVerbs().get(0).getPath().equals(uri))
+				.collect(Collectors.toList());
+
+		RestOpenApiReader reader = new RestOpenApiReader();
+		OasDocument openApi = reader.read(context, rests, config, context.getName(), new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		LOG.info(json);
+
+		json = generify(json);
+
+		InputStream is = getClass().getClassLoader().getResourceAsStream("org/apache/camel/openapi/" + schemaResource);
+		assertNotNull(is);
+		String expected = new BufferedReader(
+				new InputStreamReader(is, StandardCharsets.UTF_8))
+				.lines()
+				.collect(Collectors.joining("\n"));
+		is.close();
+
+		assertEquals(expected, json);
+	}
+
+	private BeanConfig getBeanConfig(String apiVersion) {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html");
+		config.setVersion(apiVersion);
+		return config;
+	}
+
+	private String generify(String input) {
+		input = input.replaceAll("\"openapi\" : \"3\\..*\",", "\"openapi\" : \"3.x\",");
+		input = input.replaceAll("\"swagger\" : \"2\\..*\",", "\"swagger\" : \"2.x\",");
+		input = input.replaceAll("\"operationId\" : \"verb.*\",", "\"operationId\" : \"verb\",");
+		input = input.replaceAll("\"x-camelContextId\" : \"camel.*\"", "\"x-camelContextId\" : \"camel\"");
+		return input;
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DayResponse.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DayResponse.java
new file mode 100644
index 0000000..b2c5af1
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DayResponse.java
@@ -0,0 +1,30 @@
+/*
+ * 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.openapi;
+
+public class DayResponse {
+
+	private String day;
+
+	public String getDay() {
+		return day;
+	}
+
+	public void setDay(String day) {
+		this.day = day;
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyBookService.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyBookService.java
new file mode 100644
index 0000000..cd3fb57
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyBookService.java
@@ -0,0 +1,18 @@
+package org.apache.camel.openapi;
+
+import org.springframework.stereotype.Component;
+
+@Component("bookService")
+public class DummyBookService {
+	public void getOrder(Integer id) {
+		// Mock
+	}
+
+	public void updateOrder() {
+		// Mock
+	}
+
+	public void listOrders() {
+		// Mock
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyRestConsumerFactory.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyRestConsumerFactory.java
new file mode 100644
index 0000000..8936b5a
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyRestConsumerFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.openapi;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
+import org.apache.camel.Processor;
+import org.apache.camel.component.seda.SedaEndpoint;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.spi.RestConsumerFactory;
+import org.apache.camel.support.ClassicUuidGenerator;
+
+import java.util.Map;
+
+public class DummyRestConsumerFactory implements RestConsumerFactory {
+
+	@Override
+	public Consumer createConsumer(
+			CamelContext camelContext, Processor processor, String verb, String basePath, String uriTemplate,
+			String consumes, String produces, RestConfiguration configuration, Map<String, Object> parameters)
+			throws Exception {
+		// just use a seda endpoint for testing purpose
+		String id;
+		if (uriTemplate != null) {
+			id = ClassicUuidGenerator.generateSanitizedId(basePath + uriTemplate);
+		} else {
+			id = ClassicUuidGenerator.generateSanitizedId(basePath);
+		}
+		// remove leading dash as we add that ourselves
+		if (id.startsWith("-")) {
+			id = id.substring(1);
+		}
+		SedaEndpoint seda = camelContext.getEndpoint("seda:" + verb + "-" + id, SedaEndpoint.class);
+		return seda.createConsumer(processor);
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyUserService.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyUserService.java
new file mode 100644
index 0000000..cde0356
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/DummyUserService.java
@@ -0,0 +1,18 @@
+package org.apache.camel.openapi;
+
+import org.springframework.stereotype.Component;
+
+@Component("userService")
+public class DummyUserService {
+	public void getUser(Integer id) {
+		// Mock
+	}
+
+	public void updateUser() {
+		// Mock
+	}
+
+	public void listUsers() {
+		// Mock
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/LineItem.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/LineItem.java
new file mode 100644
index 0000000..4d99eba
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/LineItem.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.openapi;
+
+public class LineItem {
+
+	private String isbn;
+	private String name;
+
+	public String getIsbn() {
+		return isbn;
+	}
+
+	public void setIsbn(String isbn) {
+		this.isbn = isbn;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiModelApiSecurityRequirementsTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiModelApiSecurityRequirementsTest.java
new file mode 100644
index 0000000..e5d438e
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiModelApiSecurityRequirementsTest.java
@@ -0,0 +1,156 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiModelApiSecurityRequirementsTest.class,
+				RestOpenApiModelApiSecurityRequirementsTest.TestConfiguration.class
+		}
+)
+public class RestOpenApiModelApiSecurityRequirementsTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@Autowired
+	CamelContext context;
+
+	// *************************************
+	// Config
+	// *************************************
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest()
+							.securityDefinitions()
+							.oauth2("petstore_auth")
+							.authorizationUrl("https://petstore.swagger.io/oauth/dialog")
+							.end()
+							.apiKey("api_key")
+							.withHeader("myHeader").end()
+							.end()
+							.security("petstore_auth", "read, write")
+							.security("api_key");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html");
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"securityDefinitions\" : {"));
+		assertTrue(json.contains("\"type\" : \"oauth2\""));
+		assertTrue(json.contains("\"authorizationUrl\" : \"https://petstore.swagger.io/oauth/dialog\""));
+		assertTrue(json.contains("\"flow\" : \"implicit\""));
+		assertTrue(json.contains("\"type\" : \"apiKey\","));
+		assertTrue(json.contains("\"security\" : [ {"));
+		assertTrue(json.contains("\"petstore_auth\" : [ \"read\", \"write\" ]"));
+		assertTrue(json.contains("\"api_key\" : [ ]"));
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("securitySchemes"));
+		assertTrue(json.contains("\"type\" : \"oauth2\""));
+		assertTrue(json.contains("\"authorizationUrl\" : \"https://petstore.swagger.io/oauth/dialog\""));
+		assertTrue(json.contains("\"flows\" : {"));
+		assertTrue(json.contains("\"implicit\""));
+		assertTrue(json.contains("\"security\" : [ {"));
+		assertTrue(json.contains("\"petstore_auth\" : [ \"read\", \"write\" ]"));
+		assertTrue(json.contains("\"api_key\" : [ ]"));
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderApiDocsOverrideTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderApiDocsOverrideTest.java
new file mode 100644
index 0000000..60ce55b
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderApiDocsOverrideTest.java
@@ -0,0 +1,149 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderApiDocsOverrideTest.class,
+				RestOpenApiReaderApiDocsOverrideTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class
+		}
+)
+public class RestOpenApiReaderApiDocsOverrideTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@Autowired
+	CamelContext context;
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest("/hello").apiDocs(false).consumes("application/json").produces("application/json").get("/hi/{name}")
+							.description("Saying hi").param().name("name")
+							.type(RestParamType.path).dataType("string").description("Who is it").endParam().to("log:hi")
+							.get("/bye/{name}").apiDocs(true).description("Saying bye").param()
+							.name("name").type(RestParamType.path).dataType("string").description("Who is it").endParam()
+							.responseMessage().code(200).message("A reply message")
+							.endResponseMessage().to("log:bye").post("/bye").description("To update the greeting message")
+							.consumes("application/xml").produces("application/xml").param()
+							.name("greeting").type(RestParamType.body).dataType("string").description("Message to use as greeting")
+							.endParam().to("log:bye");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+		OasDocument openApi = null;
+		openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+		log.info(json);
+
+		assertFalse(json.contains("\"/hello/bye\""));
+		assertFalse(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertTrue(json.contains("\"/hello/bye/{name}\""));
+		assertFalse(json.contains("\"/hello/hi/{name}\""));
+
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		RestOpenApiReader reader = new RestOpenApiReader();
+		OasDocument openApi = null;
+		openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+		log.info(json);
+
+		assertFalse(json.contains("\"/hello/bye\""));
+		assertFalse(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertTrue(json.contains("\"/hello/bye/{name}\""));
+		assertFalse(json.contains("\"/hello/hi/{name}\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderApiDocsTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderApiDocsTest.java
new file mode 100644
index 0000000..eb4aa7c
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderApiDocsTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderApiDocsTest.class,
+				RestOpenApiReaderApiDocsTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class
+		}
+)
+public class RestOpenApiReaderApiDocsTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@Autowired
+	CamelContext context;
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest("/hello").consumes("application/json").produces("application/json").get("/hi/{name}")
+							.description("Saying hi").param().name("name").type(RestParamType.path)
+							.dataType("string").description("Who is it").endParam().to("log:hi").get("/bye/{name}").apiDocs(false)
+							.description("Saying bye").param().name("name")
+							.type(RestParamType.path).dataType("string").description("Who is it").endParam().responseMessage()
+							.code(200).message("A reply message").endResponseMessage()
+							.to("log:bye").post("/bye").apiDocs(false).description("To update the greeting message")
+							.consumes("application/xml").produces("application/xml").param()
+							.name("greeting").type(RestParamType.body).dataType("string").description("Message to use as greeting")
+							.endParam().to("log:bye");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"basePath\" : \"/api\""));
+
+		assertFalse(json.contains("\"/hello/bye\""));
+		assertFalse(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertFalse(json.contains("\"/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+
+		assertFalse(json.contains("\"/hello/bye\""));
+		assertFalse(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertFalse(json.contains("\"/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderContextPathTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderContextPathTest.java
new file mode 100644
index 0000000..f3f5fd2
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderContextPathTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+import io.apicurio.datamodels.openapi.v2.models.Oas20Info;
+import io.apicurio.datamodels.openapi.v3.models.Oas30Info;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderContextPathTest.class,
+				RestOpenApiReaderContextPathTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class
+		}
+)
+public class RestOpenApiReaderContextPathTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest("/hello").consumes("application/json").produces("application/json").get("/hi/{name}")
+							.description("Saying hi").param().name("name").type(RestParamType.path)
+							.dataType("string").description("Who is it").example("Donald Duck").endParam()
+							.param().name("filter").description("Filters to apply to the entity.").type(RestParamType.query)
+							.dataType("array").arrayType("date-time").endParam().to("log:hi")
+							.get("/bye/{name}").description("Saying bye").param().name("name")
+							.type(RestParamType.path).dataType("string").description("Who is it").example("Donald Duck").endParam()
+							.responseMessage().code(200).message("A reply number")
+							.responseModel(float.class).example("success", "123").example("error", "-1").endResponseMessage()
+							.to("log:bye").post("/bye")
+							.description("To update the greeting message").consumes("application/xml").produces("application/xml")
+							.param().name("greeting").type(RestParamType.body)
+							.dataType("string").description("Message to use as greeting")
+							.example("application/xml", "<hello>Hi</hello>").endParam().to("log:bye");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		Oas20Info info = new Oas20Info();
+		config.setInfo(info);
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"basePath\" : \"/api\""));
+		assertTrue(json.contains("\"/hello/bye\""));
+		assertTrue(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertTrue(json.contains("\"/hello/bye/{name}\""));
+		assertFalse(json.contains("\"/api/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+		assertFalse(json.contains("\"/api/hello/hi/{name}\""));
+		assertTrue(json.contains("\"type\" : \"number\""));
+		assertTrue(json.contains("\"format\" : \"float\""));
+		assertTrue(json.contains("\"application/xml\" : \"<hello>Hi</hello>\""));
+		assertTrue(json.contains("\"x-example\" : \"Donald Duck\""));
+		assertTrue(json.contains("\"success\" : \"123\""));
+		assertTrue(json.contains("\"error\" : \"-1\""));
+		assertTrue(json.contains("\"type\" : \"array\""));
+
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		Oas30Info info = new Oas30Info();
+		config.setInfo(info);
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+		assertTrue(json.contains("\"/hello/bye\""));
+		assertTrue(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertTrue(json.contains("\"/hello/bye/{name}\""));
+		assertFalse(json.contains("\"/api/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+		assertFalse(json.contains("\"/api/hello/hi/{name}\""));
+		assertTrue(json.contains("\"type\" : \"number\""));
+		assertTrue(json.contains("\"format\" : \"float\""));
+		assertTrue(json.contains("\"application/xml\" : \"<hello>Hi</hello>\""));
+		assertTrue(json.contains("\"x-example\" : \"Donald Duck\""));
+		assertTrue(json.contains("\"success\" : \"123\""));
+		assertTrue(json.contains("\"error\" : \"-1\""));
+		assertTrue(json.contains("\"type\" : \"array\""));
+		assertTrue(json.contains("\"format\" : \"date-time\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderDayOfWeekTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderDayOfWeekTest.java
new file mode 100644
index 0000000..668cb46
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderDayOfWeekTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderDayOfWeekTest.class,
+				RestOpenApiReaderDayOfWeekTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class
+		}
+)
+public class RestOpenApiReaderDayOfWeekTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					// this user REST service is json only
+					rest("/day").tag("dude").description("Day service").consumes("application/json").produces("application/json")
+
+							.get("/week").description("Day of week").param().name("day").type(RestParamType.query)
+							.description("Day of week").defaultValue("friday").dataType("string")
+							.allowableValues("monday", "tuesday", "wednesday", "thursday", "friday").endParam().responseMessage()
+							.code(200).responseModel(DayResponse.class)
+							.header("X-Rate-Limit-Limit").description("The number of allowed requests in the current period")
+							.dataType("integer").endHeader().endResponseMessage()
+							.to("log:week");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Day");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"default\" : \"friday\""));
+		assertTrue(json.contains("\"enum\" : [ \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" ]"));
+		assertTrue(json.contains("\"$ref\" : \"#/definitions/DayResponse\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.DayResponse\""));
+		assertTrue(json.contains("\"X-Rate-Limit-Limit\" : {"));
+		assertTrue(json.contains("\"description\" : \"The number of allowed requests in the current period\""));
+
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Day");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		//config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+		assertTrue(json.contains("\"default\" : \"friday\""));
+		assertTrue(json.contains("\"enum\" : [ \"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\" ]"));
+		assertTrue(json.contains("\"$ref\" : \"#/components/schemas/DayResponse\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.DayResponse\""));
+		assertTrue(json.contains("\"X-Rate-Limit-Limit\" : {"));
+		assertTrue(json.contains("\"description\" : \"The number of allowed requests in the current period\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderEnableVendorExtensionTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderEnableVendorExtensionTest.java
new file mode 100644
index 0000000..db0ba37
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderEnableVendorExtensionTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderEnableVendorExtensionTest.class,
+				RestOpenApiReaderEnableVendorExtensionTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class,
+				DummyUserService.class
+		}
+)
+public class RestOpenApiReaderEnableVendorExtensionTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@BindToRegistry("userService")
+	private final DummyUserService userService = new DummyUserService();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					// enable vendor extensions
+					restConfiguration().apiVendorExtension(true);
+
+					// this user REST service is json only
+					rest("/user").tag("dude").description("User rest service").consumes("application/json")
+							.produces("application/json")
+
+							.get("/{id}").description("Find user by id").outType(User.class).responseMessage()
+							.message("The user returned").endResponseMessage().param().name("id")
+							.type(RestParamType.path).description("The id of the user to get").dataType("integer").endParam()
+							.to("bean:userService?method=getUser(${header.id})")
+
+							.put().description("Updates or create a user").type(User.class).param().name("body")
+							.type(RestParamType.body).description("The user to update or create")
+							.endParam().to("bean:userService?method=updateUser")
+
+							.get("/findAll").description("Find all users").outType(User[].class).responseMessage()
+							.message("All the found users").endResponseMessage()
+							.to("bean:userService?method=listUsers");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testEnableVendorExtension() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setVersion("2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		String camelId = context.getName();
+
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"description\" : \"The user returned\""));
+		assertTrue(json.contains("\"$ref\" : \"#/definitions/User\""));
+		assertFalse(json.contains("\"enum\""));
+		assertTrue(json.contains("\"x-camelContextId\" : \"" + camelId + "\""));
+		context.stop();
+	}
+
+	@Test
+	public void testEnableVendorExtensionV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		String camelId = context.getName();
+
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+		assertTrue(json.contains("\"description\" : \"The user returned\""));
+		assertTrue(json.contains("\"$ref\" : \"#/components/schemas/User\""));
+		assertFalse(json.contains("\"enum\""));
+		assertTrue(json.contains("\"x-camelContextId\" : \"" + camelId + "\""));
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderFileResponseModelTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderFileResponseModelTest.java
new file mode 100644
index 0000000..af22a35
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderFileResponseModelTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+import io.apicurio.datamodels.openapi.v2.models.Oas20Info;
+import io.apicurio.datamodels.openapi.v3.models.Oas30Info;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderFileResponseModelTest.class,
+				RestOpenApiReaderFileResponseModelTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class
+		}
+)
+public class RestOpenApiReaderFileResponseModelTest {
+
+	private static final Logger LOG = LoggerFactory.getLogger(RestOpenApiReaderFileResponseModelTest.class);
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest("/hello").consumes("application/json").produces("application/octet-stream").get("/pdf/{name}").description("Saying hi").param().name("name")
+							.type(RestParamType.path).dataType("string").description("Who is it").example("Donald Duck").endParam().responseMessage().code(200)
+							.message("A document as reply").responseModel(java.io.File.class).endResponseMessage().to("log:hi");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		Oas20Info info = new Oas20Info();
+		config.setInfo(info);
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		LOG.info(json);
+		assertTrue(json.contains("\"type\" : \"file\""));
+
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		Oas30Info info = new Oas30Info();
+		config.setInfo(info);
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		LOG.info(json);
+		assertTrue(json.contains("\"format\" : \"binary\""));
+		assertTrue(json.contains("\"type\" : \"string\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelApiSecurityTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelApiSecurityTest.java
new file mode 100644
index 0000000..e210f9c
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelApiSecurityTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderModelApiSecurityTest.class,
+				RestOpenApiReaderModelApiSecurityTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class,
+				DummyUserService.class
+		}
+)
+public class RestOpenApiReaderModelApiSecurityTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@BindToRegistry("userService")
+	private final DummyUserService dummy = new DummyUserService();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest("/user").tag("dude").description("User rest service")
+							// setup security definitions
+							.securityDefinitions().oauth2("petstore_auth")
+							.authorizationUrl("http://petstore.swagger.io/oauth/dialog").end().apiKey("api_key")
+							.withHeader("myHeader").end()
+							.end().consumes("application/json").produces("application/json")
+
+							.get("/{id}/{date}").description("Find user by id and date").outType(User.class).responseMessage()
+							.message("The user returned").endResponseMessage()
+							// setup security for this rest verb
+							.security("api_key").param().name("id").type(RestParamType.path)
+							.description("The id of the user to get").endParam().param().name("date")
+							.type(RestParamType.path).description("The date").dataFormat("date").endParam()
+							.to("bean:userService?method=getUser(${header.id})")
+
+							.put().description("Updates or create a user").type(User.class)
+							// setup security for this rest verb
+							.security("petstore_auth", "write:pets,read:pets").param().name("body").type(RestParamType.body)
+							.description("The user to update or create").endParam()
+							.to("bean:userService?method=updateUser")
+
+							.get("/findAll").description("Find all users").outType(User[].class).responseMessage()
+							.message("All the found users").endResponseMessage()
+							.to("bean:userService?method=listUsers");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"securityDefinitions\" : {"));
+		assertTrue(json.contains("\"type\" : \"oauth2\""));
+		assertTrue(json.contains("\"authorizationUrl\" : \"http://petstore.swagger.io/oauth/dialog\""));
+		assertTrue(json.contains("\"flow\" : \"implicit\""));
+		assertTrue(json.contains("\"type\" : \"apiKey\","));
+		assertTrue(json.contains("\"in\" : \"header\""));
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"security\" : [ {"));
+		assertTrue(json.contains("\"petstore_auth\" : [ \"write:pets\", \"read:pets\" ]"));
+		assertTrue(json.contains("\"api_key\" : [ ]"));
+		assertTrue(json.contains("\"description\" : \"The user returned\""));
+		assertTrue(json.contains("\"$ref\" : \"#/definitions/User\""));
+		assertTrue(json.contains("\"x-className\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.User\""));
+		assertTrue(json.contains("\"type\" : \"string\""));
+		assertTrue(json.contains("\"format\" : \"date\""));
+		assertFalse(json.contains("\"enum\""));
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("securitySchemes"));
+		assertTrue(json.contains("\"type\" : \"oauth2\""));
+		assertTrue(json.contains("\"authorizationUrl\" : \"http://petstore.swagger.io/oauth/dialog\""));
+		assertTrue(json.contains("\"flows\" : {"));
+		assertTrue(json.contains("\"implicit\""));
+		assertTrue(json.contains("\"type\" : \"apiKey\","));
+		assertTrue(json.contains("\"in\" : \"header\""));
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+		assertTrue(json.contains("\"security\" : [ {"));
+		assertTrue(json.contains("\"petstore_auth\" : [ \"write:pets\", \"read:pets\" ]"));
+		assertTrue(json.contains("\"api_key\" : [ ]"));
+		assertTrue(json.contains("\"description\" : \"The user returned\""));
+		assertTrue(json.contains("\"$ref\" : \"#/components/schemas/User\""));
+		assertTrue(json.contains("\"x-className\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.User\""));
+		assertTrue(json.contains("\"type\" : \"string\""));
+		assertTrue(json.contains("\"format\" : \"date\""));
+		assertFalse(json.contains("\"enum\""));
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelBookOrderTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelBookOrderTest.java
new file mode 100644
index 0000000..a2d5212
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelBookOrderTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderModelBookOrderTest.class,
+				RestOpenApiReaderModelBookOrderTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class,
+				DummyBookService.class
+		}
+)
+public class RestOpenApiReaderModelBookOrderTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@BindToRegistry("bookService")
+	private final DummyBookService dummy = new DummyBookService();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest()
+							.securityDefinitions()
+							.oauth2("global")
+							.accessCode(
+									"https://AUTHORIZATION_URL",
+									"https://TOKEN_URL"
+							)
+							.withScope("groups", "Required scopes for Camel REST APIs")
+							.end();
+
+					// this user REST service is json only
+					rest("/books").tag("dude").description("Book order service").consumes("application/json")
+							.produces("application/json")
+
+							.get("/{id}").description("Find order by id").outType(BookOrder.class).responseMessage()
+							.message("The order returned").endResponseMessage().param().name("id")
+							.type(RestParamType.path).description("The id of the order to get").dataType("integer").endParam()
+							.to("bean:bookService?method=getOrder(${header.id})")
+							.get("/books/{id}/line/{lineNum}").outType(LineItem.class)
+							.to("bean:bookService?method=getOrder(${header.id})");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"description\" : \"The order returned\""));
+		assertTrue(json.contains("\"BookOrder\""));
+		assertTrue(json.contains("\"LineItem\""));
+		assertTrue(json.contains("\"$ref\" : \"#/definitions/BookOrder\""));
+		assertTrue(json.contains("\"$ref\" : \"#/definitions/LineItem\""));
+		assertTrue(json.contains("\"x-className\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.BookOrder\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.LineItem\""));
+
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+		assertTrue(json.contains("\"description\" : \"The order returned\""));
+		assertTrue(json.contains("\"BookOrder\""));
+		assertTrue(json.contains("\"LineItem\""));
+		assertTrue(json.contains("\"$ref\" : \"#/components/schemas/BookOrder"));
+		assertTrue(json.contains("\"$ref\" : \"#/components/schemas/LineItem"));
+		assertTrue(json.contains("\"x-className\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.BookOrder\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.LineItem\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelTest.java
new file mode 100644
index 0000000..cb3803f
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderModelTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderModelTest.class,
+				RestOpenApiReaderModelTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class,
+				DummyUserService.class
+		}
+)
+public class RestOpenApiReaderModelTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@BindToRegistry("userService")
+	private final DummyUserService dummy = new DummyUserService();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					// this user REST service is json only
+					rest("/user").tag("dude").description("User rest service").consumes("application/json")
+							.produces("application/json")
+
+							.get("/{id}/{date}").description("Find user by id and date").outType(User.class).responseMessage()
+							.message("The user returned").endResponseMessage().param()
+							.name("id").type(RestParamType.path).description("The id of the user to get").endParam().param()
+							.name("date").type(RestParamType.path).description("The date")
+							.dataFormat("date").endParam().to("bean:userService?method=getUser(${header.id})")
+
+							.put().description("Updates or create a user").type(User.class).param().name("body")
+							.type(RestParamType.body).description("The user to update or create")
+							.endParam().to("bean:userService?method=updateUser")
+
+							.get("/findAll").description("Find all users").outType(User[].class).responseMessage()
+							.message("All the found users").endResponseMessage()
+							.to("bean:userService?method=listUsers");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setVersion("2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"description\" : \"The user returned\""));
+		assertTrue(json.contains("\"$ref\" : \"#/definitions/User\""));
+		assertTrue(json.contains("\"x-className\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.User\""));
+		assertTrue(json.contains("\"type\" : \"string\""));
+		assertTrue(json.contains("\"format\" : \"date\""));
+		assertFalse(json.contains("\"enum\""));
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+		assertTrue(json.contains("\"description\" : \"The user returned\""));
+		assertTrue(json.contains("\"$ref\" : \"#/components/schemas/User\""));
+		assertTrue(json.contains("\"x-className\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.User\""));
+		assertTrue(json.contains("\"type\" : \"string\""));
+		assertTrue(json.contains("\"format\" : \"date\""));
+		assertFalse(json.contains("\"enum\""));
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderOverrideHostApiDocsTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderOverrideHostApiDocsTest.java
new file mode 100644
index 0000000..875ae80
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderOverrideHostApiDocsTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+public class RestOpenApiReaderOverrideHostApiDocsTest extends RestOpenApiReaderApiDocsTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@Override
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setVersion("2.0");
+		config.setHost("http:mycoolserver:8888/myapi");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"host\" : \"http:mycoolserver:8888/myapi\""));
+		assertTrue(json.contains("\"basePath\" : \"/api\""));
+
+		assertFalse(json.contains("\"/hello/bye\""));
+		assertFalse(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertFalse(json.contains("\"/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+
+		context.stop();
+	}
+
+	@Override
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setHost("http:mycoolserver:8888/myapi");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"url\" : \"http://http:mycoolserver:8888/myapi/api\""));
+
+		assertFalse(json.contains("\"/hello/bye\""));
+		assertFalse(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertFalse(json.contains("\"/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderPropertyPlaceholderTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderPropertyPlaceholderTest.java
new file mode 100644
index 0000000..645c0a6
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderPropertyPlaceholderTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.rest.RestDefinition;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.openapi.producer.DummyRestProducerFactory;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import java.util.List;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderPropertyPlaceholderTest.class,
+				RestOpenApiReaderPropertyPlaceholderTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class
+		},
+		properties = {"foo=hello", "bar=bye"}
+)
+public class RestOpenApiReaderPropertyPlaceholderTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestProducerFactory factory = new DummyRestProducerFactory();
+
+	@BindToRegistry("dummy-rest-consumer")
+	private final DummyRestConsumerFactory consumerFactory = new DummyRestConsumerFactory();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					// this user REST service is json only
+					rest("/{{foo}}").consumes("application/json").produces("application/json").get("/hi/{name}")
+							.description("Saying hi").param().name("name").type(RestParamType.path)
+							.dataType("string").description("Who is it").endParam().to("log:hi").get("/{{bar}}/{name}")
+							.description("Saying bye").param().name("name")
+							.type(RestParamType.path).dataType("string").description("Who is it").endParam().responseMessage()
+							.code(200).message("A reply message").endResponseMessage()
+							.to("log:bye").post("/{{bar}}").description("To update the greeting message")
+							.consumes("application/xml").produces("application/xml").param().name("greeting")
+							.type(RestParamType.body).dataType("string").description("Message to use as greeting").endParam()
+							.to("log:bye");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		RestOpenApiSupport support = new RestOpenApiSupport();
+		List<RestDefinition> rests = support.getRestDefinitions(context);
+
+		OasDocument openApi = reader.read(context, rests, config, context.getName(), new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"basePath\" : \"/api\""));
+		assertTrue(json.contains("\"/hello/bye\""));
+		assertTrue(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertTrue(json.contains("\"/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+		assertFalse(json.contains("{foo}"));
+		assertFalse(json.contains("{bar}"));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderTest.java
new file mode 100644
index 0000000..b3d49e9
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiReaderTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+import io.apicurio.datamodels.openapi.v2.models.Oas20Info;
+import io.apicurio.datamodels.openapi.v3.models.Oas30Info;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiReaderTest.class,
+				RestOpenApiReaderTest.TestConfiguration.class,
+				DummyRestConsumerFactory.class
+		}
+)
+public class RestOpenApiReaderTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@BindToRegistry("dummy-rest")
+	private final DummyRestConsumerFactory factory = new DummyRestConsumerFactory();
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest("/hello").consumes("application/json").produces("application/json").get("/hi/{name}")
+							.description("Saying hi").param().name("name").type(RestParamType.path)
+							.dataType("string").description("Who is it").example("Donald Duck").endParam()
+							.param().name("filter").description("Filters to apply to the entity.").type(RestParamType.query)
+							.dataType("array").arrayType("date-time").endParam().to("log:hi")
+							.get("/bye/{name}").description("Saying bye").param().name("name")
+							.type(RestParamType.path).dataType("string").description("Who is it").example("Donald Duck").endParam()
+							.responseMessage().code(200).message("A reply number")
+							.responseModel(float.class).example("success", "123").example("error", "-1").endResponseMessage()
+							.to("log:bye").post("/bye")
+							.description("To update the greeting message").consumes("application/xml").produces("application/xml")
+							.param().name("greeting").type(RestParamType.body)
+							.dataType("string").description("Message to use as greeting")
+							.example("application/xml", "<hello>Hi</hello>").endParam().to("log:bye");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		Oas20Info info = new Oas20Info();
+		config.setInfo(info);
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"basePath\" : \"/api\""));
+		assertTrue(json.contains("\"/hello/bye\""));
+		assertTrue(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertTrue(json.contains("\"/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+		assertTrue(json.contains("\"type\" : \"number\""));
+		assertTrue(json.contains("\"format\" : \"float\""));
+		assertTrue(json.contains("\"application/xml\" : \"<hello>Hi</hello>\""));
+		assertTrue(json.contains("\"x-example\" : \"Donald Duck\""));
+		assertTrue(json.contains("\"success\" : \"123\""));
+		assertTrue(json.contains("\"error\" : \"-1\""));
+		assertTrue(json.contains("\"type\" : \"array\""));
+
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		Oas30Info info = new Oas30Info();
+		config.setInfo(info);
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+		assertTrue(json.contains("\"/hello/bye\""));
+		assertTrue(json.contains("\"summary\" : \"To update the greeting message\""));
+		assertTrue(json.contains("\"/hello/bye/{name}\""));
+		assertTrue(json.contains("\"/hello/hi/{name}\""));
+		assertTrue(json.contains("\"type\" : \"number\""));
+		assertTrue(json.contains("\"format\" : \"float\""));
+		assertTrue(json.contains("\"application/xml\" : \"<hello>Hi</hello>\""));
+		assertTrue(json.contains("\"x-example\" : \"Donald Duck\""));
+		assertTrue(json.contains("\"success\" : \"123\""));
+		assertTrue(json.contains("\"error\" : \"-1\""));
+		assertTrue(json.contains("\"type\" : \"array\""));
+		assertTrue(json.contains("\"format\" : \"date-time\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiV2SecuritySchemesTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiV2SecuritySchemesTest.java
new file mode 100644
index 0000000..ae9afb0
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiV2SecuritySchemesTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiV2SecuritySchemesTest.class,
+				RestOpenApiV2SecuritySchemesTest.TestConfiguration.class
+		}
+)
+public class RestOpenApiV2SecuritySchemesTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest()
+							.securityDefinitions()
+							.oauth2("petstore_auth_implicit")// OAuth implicit
+							.authorizationUrl("https://petstore.swagger.io/oauth/dialog")
+							.end()
+							.oauth2("oauth_password")
+							.flow("password")
+							.tokenUrl("https://petstore.swagger.io/oauth/token")
+							.end()
+							.oauth2("oauth2_accessCode")// OAuth access/authorization code
+							.authorizationUrl("https://petstore.swagger.io/oauth/dialog")
+							.tokenUrl("https://petstore.swagger.io/oauth/token")
+							.end()
+							.apiKey("api_key_header")
+							.withHeader("myHeader")
+							.end()
+							.apiKey("api_key_query")
+							.withQuery("myQuery")
+							.end()
+							.end();
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testSecuritySchemesV2() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html");
+		config.setVersion("2.0");
+
+		RestOpenApiReader reader = new RestOpenApiReader();
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		json = json.replace("\n", " ").replaceAll("\\s+", " ");
+
+		assertTrue(json.contains("\"petstore_auth_implicit\" : { \"flow\" : \"implicit\", \"authorizationUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/dialog\", \"type\" : \"oauth2\" }"));
+		assertTrue(json.contains("\"oauth_password\" : { \"flow\" : \"password\", \"tokenUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/token\", \"type\" : \"oauth2\" }"));
+		assertTrue(json.contains("\"oauth2_accessCode\" : { \"flow\" : \"accessCode\", \"authorizationUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/dialog\", \"tokenUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/token\", \"type\" : \"oauth2\" }"));
+		assertTrue(
+				json.contains("\"api_key_header\" : { \"type\" : \"apiKey\", \"name\" : \"myHeader\", \"in\" : \"header\" }"));
+		assertTrue(json.contains("\"api_key_query\" : { \"type\" : \"apiKey\", \"name\" : \"myQuery\", \"in\" : \"query\" }"));
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiV3SecuritySchemesTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiV3SecuritySchemesTest.java
new file mode 100644
index 0000000..50d87f6
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/RestOpenApiV3SecuritySchemesTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiV3SecuritySchemesTest.class,
+				RestOpenApiV3SecuritySchemesTest.TestConfiguration.class
+		}
+)
+public class RestOpenApiV3SecuritySchemesTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@Autowired
+	CamelContext context;
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					rest()
+							.securityDefinitions()
+							.oauth2("petstore_auth_implicit")// OAuth implicit
+							.authorizationUrl("https://petstore.swagger.io/oauth/dialog")
+							.refreshUrl("https://petstore.swagger.io/oauth/refresh")
+							.end()
+							.oauth2("oauth_password")
+							.flow("password")
+							.tokenUrl("https://petstore.swagger.io/oauth/token")
+							.end()
+							.oauth2("oauth2_accessCode")// OAuth access code
+							.authorizationUrl("https://petstore.swagger.io/oauth/dialog")
+							.tokenUrl("https://petstore.swagger.io/oauth/token")
+							.end()
+							.apiKey("api_key_header")
+							.withHeader("myHeader")
+							.end()
+							.apiKey("api_key_query")
+							.withQuery("myQuery")
+							.end()
+							.apiKey("api_key_cookie", "API Key using cookie")
+							.withCookie("myCookie")
+							.end()
+							.openIdConnect("openIdConnect_auth", "https://petstore.swagger.io/openidconnect")
+							.mutualTLS("mutualTLS_auth")
+							.end();
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testSecuritySchemesV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html");
+
+		RestOpenApiReader reader = new RestOpenApiReader();
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		json = json.replace("\n", " ").replaceAll("\\s+", " ");
+
+		assertTrue(json.contains("\"petstore_auth_implicit\" : { \"flows\" : { \"implicit\" : { \"authorizationUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/dialog\", \"refreshUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/refresh\" } }, \"type\" : \"oauth2\" }"));
+		assertTrue(json.contains("\"oauth_password\" : { \"flows\" : { \"password\" : { \"tokenUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/token\" } }, \"type\" : \"oauth2\" }"));
+		assertTrue(json.contains("\"oauth2_accessCode\" : { \"flows\" : { \"authorizationCode\" : { \"authorizationUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/dialog\", \"tokenUrl\" : " +
+				"\"https://petstore.swagger.io/oauth/token\" } }, \"type\" : \"oauth2\" }"));
+		assertTrue(
+				json.contains("\"api_key_header\" : { \"type\" : \"apiKey\", \"name\" : \"myHeader\", \"in\" : \"header\" }"));
+		assertTrue(json.contains("\"api_key_query\" : { \"type\" : \"apiKey\", \"name\" : \"myQuery\", \"in\" : \"query\" }"));
+		assertTrue(json.contains("\"api_key_cookie\" : { \"type\" : \"apiKey\", \"description\" : \"API Key using cookie\", " +
+				"\"name\" : \"myCookie\", \"in\" : \"cookie\" }"));
+		assertTrue(
+				json.contains("\"openIdConnect_auth\" : { \"openIdConnectUrl\" : " +
+						"\"https://petstore.swagger.io/openidconnect\", \"type\" : \"openIdConnect\" }"));
+		assertTrue(json.contains("\"mutualTLS_auth\" : { \"type\" : \"mutualTLS\" }"));
+	}
+
+	@Test
+	public void testSecuritySchemesV2() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("https://www.apache.org/licenses/LICENSE-2.0.html");
+		config.setVersion("2.0");
+
+		RestOpenApiReader reader = new RestOpenApiReader();
+		assertThrows(IllegalStateException.class,
+				() -> reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+						new DefaultClassResolver()));
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityTest.java
new file mode 100644
index 0000000..d077215
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.openapi;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.model.ModelCamelContext;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+
+import io.apicurio.datamodels.Library;
+import io.apicurio.datamodels.openapi.models.OasDocument;
+
+@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				SpringRestOpenApiReaderModelApiSecurityTest.class,
+				DummyUserService.class,
+				DummyRestConsumerFactory.class
+		},
+		properties = {"camel.springboot.routes-include-pattern=file:src/test/resources/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityTest.xml"}
+)
+public class SpringRestOpenApiReaderModelApiSecurityTest {
+
+	private final Logger log = LoggerFactory.getLogger(getClass());
+
+	@Autowired
+	CamelContext context;
+
+	@Test
+	public void testReaderRead() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		config.setVersion("2.0");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"securityDefinitions\" : {"));
+		assertTrue(json.contains("\"type\" : \"oauth2\""));
+		assertTrue(json.contains("\"authorizationUrl\" : \"http://petstore.swagger.io/oauth/dialog\""));
+		assertTrue(json.contains("\"flow\" : \"implicit\""));
+		assertTrue(json.contains("\"type\" : \"apiKey\","));
+		assertTrue(json.contains("\"in\" : \"header\""));
+		assertTrue(json.contains("\"host\" : \"localhost:8080\""));
+		assertTrue(json.contains("\"security\" : [ {"));
+		assertTrue(json.contains("\"petstore_auth\" : [ \"write:pets\", \"read:pets\" ]"));
+		assertTrue(json.contains("\"api_key\" : [ ]"));
+		assertTrue(json.contains("\"description\" : \"The user returned\""));
+		assertTrue(json.contains("\"$ref\" : \"#/definitions/User\""));
+		assertTrue(json.contains("\"x-className\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.User\""));
+		assertTrue(json.contains("\"type\" : \"string\""));
+		assertTrue(json.contains("\"format\" : \"date\""));
+		assertFalse(json.contains("\"enum\""));
+
+		context.stop();
+	}
+
+	@Test
+	public void testReaderReadV3() throws Exception {
+		BeanConfig config = new BeanConfig();
+		config.setHost("localhost:8080");
+		config.setSchemes(new String[] {"http"});
+		config.setBasePath("/api");
+		config.setTitle("Camel User store");
+		config.setLicense("Apache 2.0");
+		config.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
+		RestOpenApiReader reader = new RestOpenApiReader();
+
+		OasDocument openApi = reader.read(context, ((ModelCamelContext) context).getRestDefinitions(), config, context.getName(),
+				new DefaultClassResolver());
+		assertNotNull(openApi);
+
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.enable(SerializationFeature.INDENT_OUTPUT);
+		mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
+		Object dump = Library.writeNode(openApi);
+		String json = mapper.writeValueAsString(dump);
+
+		log.info(json);
+
+		assertTrue(json.contains("\"securitySchemes\" : {"));
+		assertTrue(json.contains("\"type\" : \"oauth2\""));
+		assertTrue(json.contains("\"authorizationUrl\" : \"http://petstore.swagger.io/oauth/dialog\""));
+		assertTrue(json.contains("\"flows\" : {"));
+		assertTrue(json.contains("\"implicit\" : {"));
+		assertTrue(json.contains("\"type\" : \"apiKey\","));
+		assertTrue(json.contains("\"in\" : \"header\""));
+		assertTrue(json.contains("\"url\" : \"http://localhost:8080/api\""));
+		assertTrue(json.contains("\"security\" : [ {"));
+		assertTrue(json.contains("\"petstore_auth\" : [ \"write:pets\", \"read:pets\" ]"));
+		assertTrue(json.contains("\"api_key\" : [ ]"));
+		assertTrue(json.contains("\"description\" : \"The user returned\""));
+		assertTrue(json.contains("\"$ref\" : \"#/components/schemas/User\""));
+		assertTrue(json.contains("\"x-className\""));
+		assertTrue(json.contains("\"format\" : \"org.apache.camel.openapi.User\""));
+		assertTrue(json.contains("\"type\" : \"string\""));
+		assertTrue(json.contains("\"format\" : \"date\""));
+		assertFalse(json.contains("\"enum\""));
+
+		context.stop();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/User.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/User.java
new file mode 100644
index 0000000..4572d332
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/User.java
@@ -0,0 +1,47 @@
+/*
+ * 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.openapi;
+
+public class User {
+
+	private int id;
+	private String name;
+
+	public User() {
+	}
+
+	public User(int id, String name) {
+		this.id = id;
+		this.name = name;
+	}
+
+	public int getId() {
+		return id;
+	}
+
+	public void setId(int id) {
+		this.id = id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/CustomData.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/CustomData.java
new file mode 100644
index 0000000..86788ee
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/CustomData.java
@@ -0,0 +1,26 @@
+/*
+ * 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.openapi.model;
+
+class CustomData implements GenericData {
+
+	private String customDataField;
+
+	public String getCustomDataField() {
+		return customDataField;
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/GenericComplexRequestType.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/GenericComplexRequestType.java
new file mode 100644
index 0000000..421c8b1
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/GenericComplexRequestType.java
@@ -0,0 +1,52 @@
+/*
+ * 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.openapi.model;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Sample request POJO that uses Generics.
+ */
+public class GenericComplexRequestType<T extends GenericData> {
+
+	private T data;
+	private List<T> listOfData;
+	private List<List<T>> listOfListOfData;
+	private Map<String, T> mapOfData;
+	private Map<String, Map<String, T>> mapOfMapOfData;
+
+	public T getData() {
+		return data;
+	}
+
+	public List<T> getListOfData() {
+		return listOfData;
+	}
+
+	public Map<String, T> getMapOfData() {
+		return mapOfData;
+	}
+
+	public List<List<T>> getListOfListOfData() {
+		return listOfListOfData;
+	}
+
+	public Map<String, Map<String, T>> getMapOfMapOfData() {
+		return mapOfMapOfData;
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/GenericData.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/GenericData.java
new file mode 100644
index 0000000..6e37cdf
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/GenericData.java
@@ -0,0 +1,23 @@
+/*
+ * 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.openapi.model;
+
+/**
+ * Generic interface used to validate that inheritance and generics also works with the camel open-api compoment
+ */
+interface GenericData {
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/SampleComplexRequestType.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/SampleComplexRequestType.java
new file mode 100644
index 0000000..0ea3c00
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/SampleComplexRequestType.java
@@ -0,0 +1,71 @@
+/*
+ * 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.openapi.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class SampleComplexRequestType extends GenericComplexRequestType<CustomData> {
+	@JsonProperty(required = true)
+	private String requestField1;
+	private String requestField2;
+	private List<String> listOfStrings;
+	private String[] arrayOfString;
+	private Map<String, String> mapOfStrings;
+	private TimeUnit timeUnit;
+	private InnerClass innerClass;
+
+	public String getRequestField1() {
+		return requestField1;
+	}
+
+	public String getRequestField2() {
+		return requestField2;
+	}
+
+	public List<String> getListOfStrings() {
+		return listOfStrings;
+	}
+
+	public String[] getArrayOfString() {
+		return arrayOfString;
+	}
+
+	@JsonProperty(required = true)
+	public Map<String, String> getMapOfStrings() {
+		return mapOfStrings;
+	}
+
+	public TimeUnit getTimeUnit() {
+		return timeUnit;
+	}
+
+	public InnerClass getInnerClass() {
+		return innerClass;
+	}
+
+	public static class InnerClass {
+		private long longField;
+
+		public long getLongField() {
+			return longField;
+		}
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/SampleComplexResponseType.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/SampleComplexResponseType.java
new file mode 100644
index 0000000..ca0505a
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/model/SampleComplexResponseType.java
@@ -0,0 +1,59 @@
+/*
+ * 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.openapi.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.time.Month;
+
+public class SampleComplexResponseType {
+	@JsonProperty(required = true)
+	private final String responseField1 = "Response Field 1";
+	private final String responseField2 = "Response Field 2";
+	private String[] arrayOfStrings;
+	private Month month;
+	private InnerClass innerClass;
+
+	public String getResponseField1() {
+		return responseField1;
+	}
+
+	public String getResponseField2() {
+		return responseField2;
+	}
+
+	@JsonProperty(required = true)
+	public String[] getArrayOfStrings() {
+		return arrayOfStrings;
+	}
+
+	public Month getMonth() {
+		return month;
+	}
+
+	public InnerClass getInnerClass() {
+		return innerClass;
+	}
+
+	public static class InnerClass {
+		double doubleField;
+
+		public double getDoubleField() {
+			return doubleField;
+		}
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/DummyRestProducerFactory.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/DummyRestProducerFactory.java
new file mode 100644
index 0000000..740ef73
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/DummyRestProducerFactory.java
@@ -0,0 +1,62 @@
+/*
+ * 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.openapi.producer;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Producer;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.spi.RestProducerFactory;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.StringHelper;
+
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+@Component("dummy")
+public class DummyRestProducerFactory implements RestProducerFactory {
+
+	@Override
+	public Producer createProducer(
+			CamelContext camelContext, String host,
+			String verb, String basePath, final String uriTemplate, String queryParameters,
+			String consumes, String produces, RestConfiguration configuration, Map<String, Object> parameters)
+			throws Exception {
+
+		// use a dummy endpoint
+		Endpoint endpoint = camelContext.getEndpoint("stub:dummy");
+
+		return new DefaultProducer(endpoint) {
+			@Override
+			public void process(Exchange exchange) throws Exception {
+				String query = exchange.getIn().getHeader(Exchange.REST_HTTP_QUERY, String.class);
+				if (query != null) {
+					String name = StringHelper.after(query, "name=");
+					exchange.getIn().setBody("Bye " + name);
+				}
+				String uri = exchange.getIn().getHeader(Exchange.REST_HTTP_URI, String.class);
+				if (uri != null) {
+					int pos = uri.lastIndexOf('/');
+					String name = uri.substring(pos + 1);
+					exchange.getIn().setBody("Hello " + name);
+				}
+			}
+		};
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/RestOpenApiGetTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/RestOpenApiGetTest.java
new file mode 100644
index 0000000..304ab50
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/RestOpenApiGetTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.openapi.producer;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiGetTest.class,
+				RestOpenApiGetTest.TestConfiguration.class,
+				DummyRestProducerFactory.class
+		}
+)
+public class RestOpenApiGetTest {
+
+	@BindToRegistry("dummy")
+	private final DummyRestProducerFactory factory = new DummyRestProducerFactory();
+
+	@Autowired
+	ProducerTemplate producerTemplate;
+
+	@Autowired
+	CamelContext context;
+
+	// *************************************
+	// Config
+	// *************************************
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					restConfiguration().host("camelhost").producerComponent("dummy");
+
+					from("direct:start").to("rest:get:hello/hi/{name}?apiDoc=hello-api.json").to("mock:result");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testOpenApiGet() throws Exception {
+		MockEndpoint mockEndpoint = (MockEndpoint) context.getEndpoint("mock:result");
+		mockEndpoint.expectedBodiesReceived("Hello Donald Duck");
+
+		producerTemplate.sendBodyAndHeader("direct:start", null, "name", "Donald Duck");
+
+		mockEndpoint.assertIsSatisfied();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/RestOpenApiGetUriParamTest.java b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/RestOpenApiGetUriParamTest.java
new file mode 100644
index 0000000..efe833a
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/java/org/apache/camel/openapi/producer/RestOpenApiGetUriParamTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.openapi.producer;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+		classes = {
+				CamelAutoConfiguration.class,
+				RestOpenApiGetUriParamTest.class,
+				RestOpenApiGetUriParamTest.TestConfiguration.class,
+				DummyRestProducerFactory.class
+		}
+)
+public class RestOpenApiGetUriParamTest {
+
+	@BindToRegistry("dummy")
+	private final DummyRestProducerFactory factory = new DummyRestProducerFactory();
+
+	@Autowired
+	ProducerTemplate producerTemplate;
+
+	@Autowired
+	CamelContext context;
+
+	// *************************************
+	// Config
+	// *************************************
+
+	@Configuration
+	public class TestConfiguration {
+
+		@Bean
+		public RouteBuilder routeBuilder() {
+			return new RouteBuilder() {
+
+				@Override
+				public void configure() throws Exception {
+					restConfiguration().host("camelhost").producerComponent("dummy").producerApiDoc("hello-api.json");
+
+					from("direct:start").to("rest:get:bye?name={name}").to("mock:result");
+				}
+			};
+		}
+	}
+
+	@Test
+	public void testOpenApiGet() throws Exception {
+		MockEndpoint mockEndpoint = (MockEndpoint) context.getEndpoint("mock:result");
+		mockEndpoint.expectedBodiesReceived("Bye Donald+Duck");
+
+		producerTemplate.sendBodyAndHeader("direct:start", null, "name", "Donald Duck");
+
+		mockEndpoint.assertIsSatisfied();
+	}
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/hello-api.json b/components-starter/camel-openapi-java-starter/src/test/resources/hello-api.json
new file mode 100644
index 0000000..6cc6a72
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/hello-api.json
@@ -0,0 +1,41 @@
+{
+  "swagger" : "2.0",
+  "host" : "localhost:8080",
+  "basePath" : "/api",
+  "tags" : [ {
+    "name" : "hello"
+  } ],
+  "schemes" : [ "http" ],
+  "paths" : {
+    "/hello/hi/{name}" : {
+      "get" : {
+        "tags" : [ "hello" ],
+        "summary" : "Saying hi",
+        "consumes" : [ "application/json" ],
+        "produces" : [ "application/json" ],
+        "parameters" : [ {
+          "name" : "name",
+          "in" : "path",
+          "description" : "Who is it",
+          "required" : true,
+          "type" : "string"
+        } ]
+      }
+    },
+    "/bye" : {
+      "get" : {
+        "tags" : [ "bye" ],
+        "summary" : "Saying bye",
+        "consumes" : [ "application/json" ],
+        "produces" : [ "application/json" ],
+        "parameters" : [ {
+          "name" : "name",
+          "in" : "query",
+          "description" : "Who is it",
+          "required" : true,
+          "type" : "string"
+        } ]
+      }
+    }
+  }
+}
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/log4j2.properties b/components-starter/camel-openapi-java-starter/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..7ea1cb5
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-openapi-java-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityTest.xml b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityTest.xml
new file mode 100644
index 0000000..744562c
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/SpringRestOpenApiReaderModelApiSecurityTest.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+   <rest path="/user" tag="dude" consumes="application/json" produces="application/json">
+      <description>User rest service</description>
+      <securityDefinitions>
+        <oauth2 key="petstore_auth" authorizationUrl="http://petstore.swagger.io/oauth/dialog"/>
+        <apiKey key="api_key" name="myHeader" inHeader="true"/>
+      </securityDefinitions>
+
+      <get path="/{id}/{date}" outType="org.apache.camel.openapi.User">
+        <description>Find user by id and date</description>
+        <param name="id" type="path" description="The id of the user to get"/>
+        <param name="date" type="path" dataFormat="date" description="The date"/>
+        <responseMessage message="The user returned"/>
+        <security key="api_key"/>
+        <to uri="bean:userService?method=getUser(${header.id})"/>
+      </get>
+
+      <put type="org.apache.camel.openapi.User">
+        <description>Updates or create a user</description>
+        <param name="body" type="body" description="The user to update or create"/>
+        <security key="petstore_auth" scopes="write:pets,read:pets"/>
+        <to uri="bean:userService?method=updateUser"/>
+      </put>
+
+      <get path="/findAll" outType="org.apache.camel.openapi.User[]">
+        <description>Find all users</description>
+        <responseMessage message="All the found users"/>
+        <to uri="bean:userService?method=listUsers"/>
+      </get>
+
+    </rest>
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V2SchemaForComplexTypesRequest.json b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V2SchemaForComplexTypesRequest.json
new file mode 100644
index 0000000..99276fa
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V2SchemaForComplexTypesRequest.json
@@ -0,0 +1,158 @@
+{
+  "swagger" : "2.x",
+  "host" : "localhost:8080",
+  "basePath" : "/api",
+  "schemes" : [ "http" ],
+  "paths" : {
+    "/complexRequest" : {
+      "post" : {
+        "consumes" : [ "application/json" ],
+        "produces" : [ "text/plain" ],
+        "parameters" : [ {
+          "name" : "body",
+          "schema" : {
+            "$ref" : "#/definitions/SampleComplexRequestType"
+          },
+          "in" : "body",
+          "required" : true
+        } ],
+        "responses" : {
+          "200" : {
+            "description" : "Receives a complex object as parameter",
+            "schema" : {
+              "$ref" : "#/definitions/SampleComplexResponseType_InnerClass"
+            }
+          }
+        },
+        "operationId" : "verb",
+        "summary" : "Demo complex request type",
+        "x-camelContextId" : "camel"
+      }
+    }
+  },
+  "definitions" : {
+    "CustomData" : {
+      "type" : "object",
+      "properties" : {
+        "customDataField" : {
+          "type" : "string"
+        }
+      },
+      "x-className" : {
+        "format" : "org.apache.camel.openapi.model.CustomData",
+        "type" : "string"
+      }
+    },
+    "SampleComplexRequestType" : {
+      "required" : [ "mapOfStrings", "requestField1" ],
+      "type" : "object",
+      "properties" : {
+        "data" : {
+          "$ref" : "#/definitions/CustomData"
+        },
+        "listOfData" : {
+          "type" : "array",
+          "items" : {
+            "$ref" : "#/definitions/CustomData"
+          }
+        },
+        "listOfListOfData" : {
+          "type" : "array",
+          "items" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/definitions/CustomData"
+            }
+          }
+        },
+        "mapOfData" : {
+          "type" : "object",
+          "additionalProperties" : {
+            "$ref" : "#/definitions/CustomData"
+          }
+        },
+        "mapOfMapOfData" : {
+          "type" : "object",
+          "additionalProperties" : {
+            "type" : "object",
+            "additionalProperties" : {
+              "$ref" : "#/definitions/CustomData"
+            }
+          }
+        },
+        "requestField1" : {
+          "type" : "string"
+        },
+        "requestField2" : {
+          "type" : "string"
+        },
+        "listOfStrings" : {
+          "type" : "array",
+          "items" : {
+            "type" : "string"
+          }
+        },
+        "arrayOfString" : {
+          "type" : "array",
+          "items" : {
+            "type" : "string"
+          }
+        },
+        "mapOfStrings" : {
+          "type" : "object",
+          "additionalProperties" : {
+            "type" : "string"
+          }
+        },
+        "timeUnit" : {
+          "enum" : [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ],
+          "type" : "string"
+        },
+        "innerClass" : {
+          "$ref" : "#/definitions/SampleComplexRequestType_InnerClass"
+        }
+      },
+      "x-className" : {
+        "format" : "org.apache.camel.openapi.model.SampleComplexRequestType",
+        "type" : "string"
+      }
+    },
+    "SampleComplexRequestType_InnerClass" : {
+      "type" : "object",
+      "properties" : {
+        "longField" : {
+          "format" : "int64",
+          "type" : "integer"
+        }
+      },
+      "x-className" : {
+        "format" : "org.apache.camel.openapi.model.SampleComplexRequestType$InnerClass",
+        "type" : "string"
+      }
+    },
+    "SampleComplexResponseType_InnerClass" : {
+      "type" : "object",
+      "properties" : {
+        "doubleField" : {
+          "format" : "double",
+          "type" : "number"
+        }
+      },
+      "x-className" : {
+        "format" : "org.apache.camel.openapi.model.SampleComplexResponseType$InnerClass",
+        "type" : "string"
+      }
+    }
+  },
+  "securityDefinitions" : {
+    "global" : {
+      "flow" : "accessCode",
+      "authorizationUrl" : "https://AUTHORIZATION_URL",
+      "tokenUrl" : "https://TOKEN_URL",
+      "scopes" : {
+        "groups" : "Required scopes for Camel REST APIs"
+      },
+      "type" : "oauth2"
+    }
+  }
+}
\ No newline at end of file
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V2SchemaForComplexTypesResponse.json b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V2SchemaForComplexTypesResponse.json
new file mode 100644
index 0000000..4193eab
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V2SchemaForComplexTypesResponse.json
@@ -0,0 +1,101 @@
+{
+  "swagger" : "2.x",
+  "host" : "localhost:8080",
+  "basePath" : "/api",
+  "schemes" : [ "http" ],
+  "paths" : {
+    "/complexResponse" : {
+      "get" : {
+        "consumes" : [ "application/json" ],
+        "produces" : [ "application/json" ],
+        "parameters" : [ {
+          "name" : "body",
+          "schema" : {
+            "$ref" : "#/definitions/SampleComplexRequestType_InnerClass"
+          },
+          "in" : "body",
+          "required" : true
+        } ],
+        "responses" : {
+          "200" : {
+            "description" : "Returns a complex object",
+            "schema" : {
+              "$ref" : "#/definitions/SampleComplexResponseType"
+            }
+          }
+        },
+        "operationId" : "verb",
+        "summary" : "Demo complex response type",
+        "x-camelContextId" : "camel"
+      }
+    }
+  },
+  "definitions" : {
+    "SampleComplexRequestType_InnerClass" : {
+      "type" : "object",
+      "properties" : {
+        "longField" : {
+          "format" : "int64",
+          "type" : "integer"
+        }
+      },
+      "x-className" : {
+        "format" : "org.apache.camel.openapi.model.SampleComplexRequestType$InnerClass",
+        "type" : "string"
+      }
+    },
+    "SampleComplexResponseType" : {
+      "required" : [ "arrayOfStrings", "responseField1" ],
+      "type" : "object",
+      "properties" : {
+        "responseField1" : {
+          "type" : "string"
+        },
+        "responseField2" : {
+          "type" : "string"
+        },
+        "arrayOfStrings" : {
+          "type" : "array",
+          "items" : {
+            "type" : "string"
+          }
+        },
+        "month" : {
+          "enum" : [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ],
+          "type" : "string"
+        },
+        "innerClass" : {
+          "$ref" : "#/definitions/SampleComplexResponseType_InnerClass"
+        }
+      },
+      "x-className" : {
+        "format" : "org.apache.camel.openapi.model.SampleComplexResponseType",
+        "type" : "string"
+      }
+    },
+    "SampleComplexResponseType_InnerClass" : {
+      "type" : "object",
+      "properties" : {
+        "doubleField" : {
+          "format" : "double",
+          "type" : "number"
+        }
+      },
+      "x-className" : {
+        "format" : "org.apache.camel.openapi.model.SampleComplexResponseType$InnerClass",
+        "type" : "string"
+      }
+    }
+  },
+  "securityDefinitions" : {
+    "global" : {
+      "flow" : "accessCode",
+      "authorizationUrl" : "https://AUTHORIZATION_URL",
+      "tokenUrl" : "https://TOKEN_URL",
+      "scopes" : {
+        "groups" : "Required scopes for Camel REST APIs"
+      },
+      "type" : "oauth2"
+    }
+  }
+}
\ No newline at end of file
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V3SchemaForComplexTypesRequest.json b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V3SchemaForComplexTypesRequest.json
new file mode 100644
index 0000000..7abf174
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V3SchemaForComplexTypesRequest.json
@@ -0,0 +1,168 @@
+{
+  "openapi" : "3.x",
+  "servers" : [ {
+    "url" : "http://localhost:8080/api"
+  } ],
+  "paths" : {
+    "/complexRequest" : {
+      "post" : {
+        "requestBody" : {
+          "description" : "",
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/SampleComplexRequestType"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "content" : {
+              "text/plain" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/SampleComplexResponseType_InnerClass"
+                }
+              }
+            },
+            "description" : "Receives a complex object as parameter"
+          }
+        },
+        "operationId" : "verb",
+        "summary" : "Demo complex request type",
+        "x-camelContextId" : "camel"
+      }
+    }
+  },
+  "components" : {
+    "schemas" : {
+      "CustomData" : {
+        "type" : "object",
+        "properties" : {
+          "customDataField" : {
+            "type" : "string"
+          }
+        },
+        "x-className" : {
+          "format" : "org.apache.camel.openapi.model.CustomData",
+          "type" : "string"
+        }
+      },
+      "SampleComplexRequestType" : {
+        "required" : [ "mapOfStrings", "requestField1" ],
+        "type" : "object",
+        "properties" : {
+          "data" : {
+            "$ref" : "#/components/schemas/CustomData"
+          },
+          "listOfData" : {
+            "type" : "array",
+            "items" : {
+              "$ref" : "#/components/schemas/CustomData"
+            }
+          },
+          "listOfListOfData" : {
+            "type" : "array",
+            "items" : {
+              "type" : "array",
+              "items" : {
+                "$ref" : "#/components/schemas/CustomData"
+              }
+            }
+          },
+          "mapOfData" : {
+            "type" : "object",
+            "additionalProperties" : {
+              "$ref" : "#/components/schemas/CustomData"
+            }
+          },
+          "mapOfMapOfData" : {
+            "type" : "object",
+            "additionalProperties" : {
+              "type" : "object",
+              "additionalProperties" : {
+                "$ref" : "#/components/schemas/CustomData"
+              }
+            }
+          },
+          "requestField1" : {
+            "type" : "string"
+          },
+          "requestField2" : {
+            "type" : "string"
+          },
+          "listOfStrings" : {
+            "type" : "array",
+            "items" : {
+              "type" : "string"
+            }
+          },
+          "arrayOfString" : {
+            "type" : "array",
+            "items" : {
+              "type" : "string"
+            }
+          },
+          "mapOfStrings" : {
+            "type" : "object",
+            "additionalProperties" : {
+              "type" : "string"
+            }
+          },
+          "timeUnit" : {
+            "enum" : [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ],
+            "type" : "string"
+          },
+          "innerClass" : {
+            "$ref" : "#/components/schemas/SampleComplexRequestType_InnerClass"
+          }
+        },
+        "x-className" : {
+          "format" : "org.apache.camel.openapi.model.SampleComplexRequestType",
+          "type" : "string"
+        }
+      },
+      "SampleComplexRequestType_InnerClass" : {
+        "type" : "object",
+        "properties" : {
+          "longField" : {
+            "format" : "int64",
+            "type" : "integer"
+          }
+        },
+        "x-className" : {
+          "format" : "org.apache.camel.openapi.model.SampleComplexRequestType$InnerClass",
+          "type" : "string"
+        }
+      },
+      "SampleComplexResponseType_InnerClass" : {
+        "type" : "object",
+        "properties" : {
+          "doubleField" : {
+            "format" : "double",
+            "type" : "number"
+          }
+        },
+        "x-className" : {
+          "format" : "org.apache.camel.openapi.model.SampleComplexResponseType$InnerClass",
+          "type" : "string"
+        }
+      }
+    },
+    "securitySchemes" : {
+      "global" : {
+        "flows" : {
+          "authorizationCode" : {
+            "authorizationUrl" : "https://AUTHORIZATION_URL",
+            "tokenUrl" : "https://TOKEN_URL",
+            "scopes" : {
+              "groups" : "Required scopes for Camel REST APIs"
+            }
+          }
+        },
+        "type" : "oauth2"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V3SchemaForComplexTypesResponse.json b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V3SchemaForComplexTypesResponse.json
new file mode 100644
index 0000000..88c81eb
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/org/apache/camel/openapi/V3SchemaForComplexTypesResponse.json
@@ -0,0 +1,111 @@
+{
+  "openapi" : "3.x",
+  "servers" : [ {
+    "url" : "http://localhost:8080/api"
+  } ],
+  "paths" : {
+    "/complexResponse" : {
+      "get" : {
+        "requestBody" : {
+          "description" : "",
+          "content" : {
+            "application/json" : {
+              "schema" : {
+                "$ref" : "#/components/schemas/SampleComplexRequestType_InnerClass"
+              }
+            }
+          },
+          "required" : true
+        },
+        "responses" : {
+          "200" : {
+            "content" : {
+              "application/json" : {
+                "schema" : {
+                  "$ref" : "#/components/schemas/SampleComplexResponseType"
+                }
+              }
+            },
+            "description" : "Returns a complex object"
+          }
+        },
+        "operationId" : "verb",
+        "summary" : "Demo complex response type",
+        "x-camelContextId" : "camel"
+      }
+    }
+  },
+  "components" : {
+    "schemas" : {
+      "SampleComplexRequestType_InnerClass" : {
+        "type" : "object",
+        "properties" : {
+          "longField" : {
+            "format" : "int64",
+            "type" : "integer"
+          }
+        },
+        "x-className" : {
+          "format" : "org.apache.camel.openapi.model.SampleComplexRequestType$InnerClass",
+          "type" : "string"
+        }
+      },
+      "SampleComplexResponseType" : {
+        "required" : [ "arrayOfStrings", "responseField1" ],
+        "type" : "object",
+        "properties" : {
+          "responseField1" : {
+            "type" : "string"
+          },
+          "responseField2" : {
+            "type" : "string"
+          },
+          "arrayOfStrings" : {
+            "type" : "array",
+            "items" : {
+              "type" : "string"
+            }
+          },
+          "month" : {
+            "enum" : [ "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" ],
+            "type" : "string"
+          },
+          "innerClass" : {
+            "$ref" : "#/components/schemas/SampleComplexResponseType_InnerClass"
+          }
+        },
+        "x-className" : {
+          "format" : "org.apache.camel.openapi.model.SampleComplexResponseType",
+          "type" : "string"
+        }
+      },
+      "SampleComplexResponseType_InnerClass" : {
+        "type" : "object",
+        "properties" : {
+          "doubleField" : {
+            "format" : "double",
+            "type" : "number"
+          }
+        },
+        "x-className" : {
+          "format" : "org.apache.camel.openapi.model.SampleComplexResponseType$InnerClass",
+          "type" : "string"
+        }
+      }
+    },
+    "securitySchemes" : {
+      "global" : {
+        "flows" : {
+          "authorizationCode" : {
+            "authorizationUrl" : "https://AUTHORIZATION_URL",
+            "tokenUrl" : "https://TOKEN_URL",
+            "scopes" : {
+              "groups" : "Required scopes for Camel REST APIs"
+            }
+          }
+        },
+        "type" : "oauth2"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/petstore-v3.json b/components-starter/camel-openapi-java-starter/src/test/resources/petstore-v3.json
new file mode 100644
index 0000000..f01d15e
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/petstore-v3.json
@@ -0,0 +1 @@
+{"openapi":"3.0.2","info":{"title":"Swagger Petstore - OpenAPI 3.0","description":"This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, an [...]
\ No newline at end of file
diff --git a/components-starter/camel-openapi-java-starter/src/test/resources/petstore.json b/components-starter/camel-openapi-java-starter/src/test/resources/petstore.json
new file mode 100644
index 0000000..816847f
--- /dev/null
+++ b/components-starter/camel-openapi-java-starter/src/test/resources/petstore.json
@@ -0,0 +1 @@
+{"swagger":"2.0","info":{"description":"This is a sample server Petstore server.  You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/).  For this sample, you can use the api key `special-key` to test the authorization filters.","version":"1.0.0","title":"Swagger Petstore","termsOfService":"http://swagger.io/terms/","contact":{"email":"apiteam@swagger.io"},"license":{"name":"Apache 2.0","url":"http://www.a [...]
\ No newline at end of file