This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit de1649265c525c2a382e05bfaa2a766214addfe1 Author: James Netherton <jamesnether...@gmail.com> AuthorDate: Mon May 18 14:39:57 2020 +0100 Add REST OpenApi native support Fixes #1235 --- .github/test-categories.yaml | 1 + .../pages/list-of-camel-quarkus-extensions.adoc | 4 +- extensions-jvm/pom.xml | 1 - extensions/pom.xml | 1 + .../rest-openapi/deployment/pom.xml | 4 ++ .../openapi/deployment/RestOpenapiProcessor.java | 15 ------ .../rest-openapi/pom.xml | 1 - .../rest-openapi/runtime/pom.xml | 4 ++ .../main/resources/META-INF/quarkus-extension.yaml | 2 - integration-tests/pom.xml | 1 + .../rest-openapi}/pom.xml | 55 ++++++++++++++++++++-- .../component/rest/openapi/it/FruitResource.java | 35 +++++++++----- .../rest/openapi/it/RestOpenApiRoutes.java | 18 +++---- .../rest/openapi/it/RestOpenapiResource.java | 36 +++++++------- .../component/rest/openapi/it/model/Fruit.java | 20 +++----- .../component/rest/openapi/it/RestOpenapiIT.java | 17 ++----- .../component/rest/openapi/it/RestOpenapiTest.java | 15 ++++-- 17 files changed, 133 insertions(+), 97 deletions(-) diff --git a/.github/test-categories.yaml b/.github/test-categories.yaml index 28a8df3..67d994d 100644 --- a/.github/test-categories.yaml +++ b/.github/test-categories.yaml @@ -95,6 +95,7 @@ platform: - platform-http - platform-http-engine - reactive-streams + - rest-openapi saas: - box - github diff --git a/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc b/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc index 2cb20de..02a909d 100644 --- a/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc +++ b/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc @@ -526,8 +526,8 @@ Level | Since | Description Stable | 0.2.0 | Expose OpenAPI Specification of the REST services defined using Camel REST DSL. | link:https://camel.apache.org/components/latest/rest-openapi-component.html[REST OpenApi] (camel-quarkus-rest-openapi) + -`rest-openapi:specificationUri#operationId` | JVM + - Preview | 1.0.0-M6 | Configure REST producers based on an OpenAPI specification document delegating to a component implementing the RestProducerFactory interface. +`rest-openapi:specificationUri#operationId` | Native + + Stable | 1.0.0-M6 | Configure REST producers based on an OpenAPI specification document delegating to a component implementing the RestProducerFactory interface. | link:https://camel.apache.org/components/latest/salesforce-component.html[Salesforce] (camel-quarkus-salesforce) + `salesforce:operationName:topicName` | Native + diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml index 361b119..36ca797 100644 --- a/extensions-jvm/pom.xml +++ b/extensions-jvm/pom.xml @@ -63,7 +63,6 @@ <module>protobuf</module> <module>pubnub</module> <module>rabbitmq</module> - <module>rest-openapi</module> </modules> </project> diff --git a/extensions/pom.xml b/extensions/pom.xml index c3057c5..2f7c009 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -120,6 +120,7 @@ <module>reactive-streams</module> <module>ref</module> <module>rest</module> + <module>rest-openapi</module> <module>salesforce</module> <module>sap-netweaver</module> <module>scheduler</module> diff --git a/extensions-jvm/rest-openapi/deployment/pom.xml b/extensions/rest-openapi/deployment/pom.xml similarity index 94% rename from extensions-jvm/rest-openapi/deployment/pom.xml rename to extensions/rest-openapi/deployment/pom.xml index f7b1d24..c4e8d27 100644 --- a/extensions-jvm/rest-openapi/deployment/pom.xml +++ b/extensions/rest-openapi/deployment/pom.xml @@ -48,6 +48,10 @@ </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-rest-deployment</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-rest-openapi</artifactId> </dependency> </dependencies> diff --git a/extensions-jvm/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/RestOpenapiProcessor.java b/extensions/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/RestOpenapiProcessor.java similarity index 62% rename from extensions-jvm/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/RestOpenapiProcessor.java rename to extensions/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/RestOpenapiProcessor.java index 4206391..5f87825 100644 --- a/extensions-jvm/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/RestOpenapiProcessor.java +++ b/extensions/rest-openapi/deployment/src/main/java/org/apache/camel/quarkus/component/rest/openapi/deployment/RestOpenapiProcessor.java @@ -17,16 +17,10 @@ package org.apache.camel.quarkus.component.rest.openapi.deployment; import io.quarkus.deployment.annotations.BuildStep; -import io.quarkus.deployment.annotations.ExecutionTime; -import io.quarkus.deployment.annotations.Record; import io.quarkus.deployment.builditem.FeatureBuildItem; -import io.quarkus.deployment.pkg.steps.NativeBuild; -import org.apache.camel.quarkus.core.JvmOnlyRecorder; -import org.jboss.logging.Logger; class RestOpenapiProcessor { - private static final Logger LOG = Logger.getLogger(RestOpenapiProcessor.class); private static final String FEATURE = "camel-rest-openapi"; @BuildStep @@ -34,13 +28,4 @@ class RestOpenapiProcessor { return new FeatureBuildItem(FEATURE); } - /** - * Remove this once this extension starts supporting the native mode. - */ - @BuildStep(onlyIf = NativeBuild.class) - @Record(value = ExecutionTime.RUNTIME_INIT) - void warnJvmInNative(JvmOnlyRecorder recorder) { - JvmOnlyRecorder.warnJvmInNative(LOG, FEATURE); // warn at build time - recorder.warnJvmInNative(FEATURE); // warn at runtime - } } diff --git a/extensions-jvm/rest-openapi/pom.xml b/extensions/rest-openapi/pom.xml similarity index 97% rename from extensions-jvm/rest-openapi/pom.xml rename to extensions/rest-openapi/pom.xml index 3d6c0ee..0694d73 100644 --- a/extensions-jvm/rest-openapi/pom.xml +++ b/extensions/rest-openapi/pom.xml @@ -33,6 +33,5 @@ <modules> <module>deployment</module> <module>runtime</module> - <module>integration-test</module> </modules> </project> diff --git a/extensions-jvm/rest-openapi/runtime/pom.xml b/extensions/rest-openapi/runtime/pom.xml similarity index 95% rename from extensions-jvm/rest-openapi/runtime/pom.xml rename to extensions/rest-openapi/runtime/pom.xml index 39edd9b..fddff10 100644 --- a/extensions-jvm/rest-openapi/runtime/pom.xml +++ b/extensions/rest-openapi/runtime/pom.xml @@ -51,6 +51,10 @@ <artifactId>camel-quarkus-core</artifactId> </dependency> <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-rest</artifactId> + </dependency> + <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-rest-openapi</artifactId> </dependency> diff --git a/extensions-jvm/rest-openapi/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/rest-openapi/runtime/src/main/resources/META-INF/quarkus-extension.yaml similarity index 97% rename from extensions-jvm/rest-openapi/runtime/src/main/resources/META-INF/quarkus-extension.yaml rename to extensions/rest-openapi/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 150975f..3af3240 100644 --- a/extensions-jvm/rest-openapi/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/rest-openapi/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -24,8 +24,6 @@ name: "Camel REST OpenApi" description: "Configure REST producers based on an OpenAPI specification document delegating to a component implementing the RestProducerFactory interface" metadata: - unlisted: true guide: "https://camel.apache.org/components/latest/rest-openapi-component.html" categories: - "integration" - status: "preview" diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 05658c5..6c762fa 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -107,6 +107,7 @@ <module>reactive-streams</module> <module>ref</module> <module>rest-binding-mode-xml</module> + <module>rest-openapi</module> <module>salesforce</module> <module>sap-netweaver</module> <module>scheduler</module> diff --git a/extensions-jvm/rest-openapi/integration-test/pom.xml b/integration-tests/rest-openapi/pom.xml similarity index 60% rename from extensions-jvm/rest-openapi/integration-test/pom.xml rename to integration-tests/rest-openapi/pom.xml index 1151675..ee0a64c 100644 --- a/extensions-jvm/rest-openapi/integration-test/pom.xml +++ b/integration-tests/rest-openapi/pom.xml @@ -21,13 +21,12 @@ <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-build-parent-it</artifactId> + <artifactId>camel-quarkus-integration-tests</artifactId> <version>1.1.0-SNAPSHOT</version> - <relativePath>../../../poms/build-parent-it/pom.xml</relativePath> </parent> - <artifactId>camel-quarkus-rest-openapi-integration-test</artifactId> - <name>Camel Quarkus :: REST OpenApi :: Integration Test</name> + <artifactId>camel-quarkus-integration-test-rest-openapi</artifactId> + <name>Camel Quarkus :: Integration Tests :: REST OpenApi</name> <description>Integration tests for Camel Quarkus REST OpenApi extension</description> <properties> @@ -37,18 +36,34 @@ <!-- explicit dependencies of this module in the Maven sense, although they are required by the Quarkus Maven plugin. --> <!-- Please update rule whenever you change the dependencies of this module by running --> <!-- mvn process-resources -Pformat from the root directory --> - <mvnd.builder.rule>camel-quarkus-rest-openapi-deployment,camel-quarkus-support-policy-deployment</mvnd.builder.rule> + <mvnd.builder.rule>camel-quarkus-direct-deployment,camel-quarkus-netty-http-deployment,camel-quarkus-rest-openapi-deployment,camel-quarkus-support-policy-deployment</mvnd.builder.rule> </properties> <dependencies> <dependency> <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-netty-http</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-rest-openapi</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy-jsonb</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-smallrye-openapi</artifactId> + </dependency> <!-- test dependencies --> <dependency> @@ -78,4 +93,34 @@ </plugin> </plugins> </build> + + <profiles> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/FruitResource.java similarity index 52% copy from extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java copy to integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/FruitResource.java index 8ad554e..90ff678 100644 --- a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java +++ b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/FruitResource.java @@ -16,19 +16,32 @@ */ package org.apache.camel.quarkus.component.rest.openapi.it; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Set; -@QuarkusTest -class RestOpenapiTest { +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; - @Test - public void loadComponentRestOpenapi() { - /* A simple autogenerated test */ - RestAssured.get("/rest-openapi/load/component/rest-openapi") - .then() - .statusCode(200); +import org.apache.camel.quarkus.component.rest.openapi.it.model.Fruit; +import org.eclipse.microprofile.openapi.annotations.Operation; + +@Path("/fruits") +@Produces(MediaType.APPLICATION_JSON) +public class FruitResource { + + private Set<Fruit> fruits = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>())); + + public FruitResource() { + fruits.add(new Fruit("Apple", "Winter fruit")); + fruits.add(new Fruit("Pineapple", "Tropical fruit")); } + @Operation(operationId = "list") + @GET + public Set<Fruit> list() { + return fruits; + } } diff --git a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java similarity index 70% copy from extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java copy to integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java index 8ad554e..9327729 100644 --- a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java +++ b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenApiRoutes.java @@ -16,19 +16,13 @@ */ package org.apache.camel.quarkus.component.rest.openapi.it; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import org.apache.camel.builder.RouteBuilder; -@QuarkusTest -class RestOpenapiTest { +public class RestOpenApiRoutes extends RouteBuilder { - @Test - public void loadComponentRestOpenapi() { - /* A simple autogenerated test */ - RestAssured.get("/rest-openapi/load/component/rest-openapi") - .then() - .statusCode(200); + @Override + public void configure() throws Exception { + from("direct:start") + .toD("rest-openapi:#list?specificationUri=RAW(http://localhost:${header.test-port}/openapi?format=JSON)"); } - } diff --git a/extensions-jvm/rest-openapi/integration-test/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java similarity index 55% rename from extensions-jvm/rest-openapi/integration-test/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java rename to integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java index 792da0e..11f5727 100644 --- a/extensions-jvm/rest-openapi/integration-test/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java +++ b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiResource.java @@ -16,36 +16,38 @@ */ package org.apache.camel.quarkus.component.rest.openapi.it; -import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; +import javax.inject.Named; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.apache.camel.CamelContext; -import org.jboss.logging.Logger; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.netty.http.NettyHttpComponent; @Path("/rest-openapi") -@ApplicationScoped public class RestOpenapiResource { - - private static final Logger LOG = Logger.getLogger(RestOpenapiResource.class); - - private static final String COMPONENT_REST_OPENAPI = "rest-openapi"; @Inject - CamelContext context; + ProducerTemplate producerTemplate; - @Path("/load/component/rest-openapi") + @Path("/fruits/list") + @Produces(MediaType.APPLICATION_JSON) @GET - @Produces(MediaType.TEXT_PLAIN) - public Response loadComponentRestOpenapi() throws Exception { - /* This is an autogenerated test */ - if (context.getComponent(COMPONENT_REST_OPENAPI) != null) { - return Response.ok().build(); - } - LOG.warnf("Could not load [%s] from the Camel context", COMPONENT_REST_OPENAPI); - return Response.status(500, COMPONENT_REST_OPENAPI + " could not be loaded from the Camel context").build(); + public Response invokeListFruitsOperation(@QueryParam("port") int port) { + String response = producerTemplate.requestBodyAndHeader("direct:start", null, "test-port", port, String.class); + return Response.ok().entity(response).build(); + } + + // TODO: Remove this for Camel 3.4.0. See https://issues.apache.org/jira/browse/CAMEL-15076 + @javax.enterprise.inject.Produces + @Named("netty-http") + public NettyHttpComponent createNettyHttpComponent(CamelContext context) { + NettyHttpComponent nettyHttpComponent = new NettyHttpComponent(); + nettyHttpComponent.setCamelContext(context); + return nettyHttpComponent; } } diff --git a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/model/Fruit.java similarity index 65% copy from extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java copy to integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/model/Fruit.java index 8ad554e..8bb2c3d 100644 --- a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java +++ b/integration-tests/rest-openapi/src/main/java/org/apache/camel/quarkus/component/rest/openapi/it/model/Fruit.java @@ -14,21 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.rest.openapi.it; +package org.apache.camel.quarkus.component.rest.openapi.it.model; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +public class Fruit { -@QuarkusTest -class RestOpenapiTest { + public String name; + public String description; - @Test - public void loadComponentRestOpenapi() { - /* A simple autogenerated test */ - RestAssured.get("/rest-openapi/load/component/rest-openapi") - .then() - .statusCode(200); + public Fruit(String name, String description) { + this.name = name; + this.description = description; } - } diff --git a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java b/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiIT.java similarity index 69% copy from extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java copy to integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiIT.java index 8ad554e..1fc2ce0 100644 --- a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java +++ b/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiIT.java @@ -16,19 +16,8 @@ */ package org.apache.camel.quarkus.component.rest.openapi.it; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; - -@QuarkusTest -class RestOpenapiTest { - - @Test - public void loadComponentRestOpenapi() { - /* A simple autogenerated test */ - RestAssured.get("/rest-openapi/load/component/rest-openapi") - .then() - .statusCode(200); - } +import io.quarkus.test.junit.NativeImageTest; +@NativeImageTest +class RestOpenapiIT extends RestOpenapiTest { } diff --git a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java b/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java similarity index 67% rename from extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java rename to integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java index 8ad554e..138dfd9 100644 --- a/extensions-jvm/rest-openapi/integration-test/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java +++ b/integration-tests/rest-openapi/src/test/java/org/apache/camel/quarkus/component/rest/openapi/it/RestOpenapiTest.java @@ -18,17 +18,24 @@ package org.apache.camel.quarkus.component.rest.openapi.it; import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; +import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; +import static org.hamcrest.Matchers.containsInAnyOrder; + @QuarkusTest class RestOpenapiTest { @Test - public void loadComponentRestOpenapi() { - /* A simple autogenerated test */ - RestAssured.get("/rest-openapi/load/component/rest-openapi") + public void testInvokeApiEndpoint() { + RestAssured.given() + .queryParam("port", RestAssured.port) + .get("/rest-openapi/fruits/list") .then() - .statusCode(200); + .contentType(ContentType.JSON) + .statusCode(200) + .body("description", containsInAnyOrder("Winter fruit", "Tropical fruit"), "name", + containsInAnyOrder("Apple", "Pineapple")); } }