This is an automated email from the ASF dual-hosted git repository. reta pushed a commit to branch CXF-7601_microProfileOpenApi in repository https://gitbox.apache.org/repos/asf/cxf.git
commit 5aa0660a9fe324e5c8f36e47e270971d0e85b6f8 Author: reta <[email protected]> AuthorDate: Sat Mar 30 18:31:26 2019 -0400 Rebased against latest master, added a sample project for OpenAPI v3.0 using microprofile implementation --- .../README.txt | 32 ++++ .../pom.xml | 100 +++++++++++++ .../java/demo/jaxrs/openapi/server/AppConfig.java | 35 +++++ .../main/java/demo/jaxrs/openapi/server/Item.java | 40 ++--- .../java/demo/jaxrs/openapi/server/Sample.java | 161 +++++++++++++++++++++ .../java/demo/jaxrs/openapi/server/Server.java | 30 ++-- .../resources/META-INF/cxf/org.apache.cxf.Logger | 1 + .../src/main/resources/logback.xml | 16 ++ distribution/src/main/release/samples/pom.xml | 1 + parent/pom.xml | 19 ++- rt/rs/description-microprofile-openapi/pom.xml | 17 ++- .../openapi}/OpenApiEndpoint.java | 2 +- .../openapi}/OpenApiFeature.java | 103 ++++++------- .../openapi}/SwaggerUi.java | 2 +- .../cxf/jaxrs/mpopenapi/SwaggerProperties.java | 69 --------- 15 files changed, 457 insertions(+), 171 deletions(-) diff --git a/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/README.txt b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/README.txt new file mode 100644 index 0000000..ac8ab9b --- /dev/null +++ b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/README.txt @@ -0,0 +1,32 @@ +JAX-RS Swagger2Feature Spring Demo +================= + +The demo shows a basic usage of OpenAPI v3.0 API documentation with REST based Web Services using +JAX-RS 2.0 (JSR-339) and Microprofile implementation. + +Building and running the demo using Maven +--------------------------------------- + +From the base directory of this sample (i.e., where this README file is +located), the Maven pom.xml file can be used to build and run the demo. + + +Using either UNIX or Windows: + + mvn install + mvn -Pserver (from one command line window) + + +After the service is started, the Swagger API documents in JSON and YAML +are available at + + http://localhost:9000/sample/openapi.json + http://localhost:9000/sample/openapi.yaml + +To remove the target dir, run mvn clean". + +To navigate to the hosted Swagger UI, please type in the browser: + + http://localhost:9000/sample/api-docs/?url=/sample/openapi.json + + diff --git a/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/pom.xml b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/pom.xml new file mode 100644 index 0000000..f44cbe6 --- /dev/null +++ b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/pom.xml @@ -0,0 +1,100 @@ +<?xml version="1.0"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>jax_rs_description_openapi_microprofile_spring</artifactId> + <name>JAX-RS OpenAPI v3.0 Microprofile Implementation and Spring Demo</name> + <description>JAX-RS OpenAPI v3.0 Microprofile Implementation and Spring Demo</description> + <parent> + <groupId>org.apache.cxf.samples</groupId> + <artifactId>cxf-samples</artifactId> + <version>3.3.2-SNAPSHOT</version> + <relativePath>../..</relativePath> + </parent> + + <properties> + <cxf.version>${project.version}</cxf.version> + </properties> + + <profiles> + <profile> + <id>server</id> + <build> + <defaultGoal>test</defaultGoal> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <executions> + <execution> + <phase>test</phase> + <goals> + <goal>java</goal> + </goals> + <configuration> + <mainClass>demo.jaxrs.openapi.server.Server</mainClass> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + + <dependencies> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-transports-http</artifactId> + </dependency> + <!-- This dependency is needed if you're using the Jetty container --> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-transports-http-jetty</artifactId> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-frontend-jaxrs</artifactId> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-service-description-microprofile-openapi</artifactId> + <version>3.3.2-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.johnzon</groupId> + <artifactId>johnzon-jsonb</artifactId> + <version>1.1.11</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + </dependency> + <dependency> + <groupId>org.webjars</groupId> + <artifactId>swagger-ui</artifactId> + <version>3.20.9</version> + </dependency> + </dependencies> +</project> diff --git a/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/AppConfig.java b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/AppConfig.java new file mode 100644 index 0000000..a5c039a --- /dev/null +++ b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/AppConfig.java @@ -0,0 +1,35 @@ +package demo.jaxrs.openapi.server; + +import java.util.Arrays; + +import org.apache.cxf.jaxrs.JAXRSServerFactoryBean; +import org.apache.cxf.jaxrs.microprofile.openapi.OpenApiFeature; +import org.apache.johnzon.jaxrs.jsonb.jaxrs.JsonbJaxrsProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AppConfig { + @Bean + OpenApiFeature openApiFeature() { + final OpenApiFeature openApiFeature = new OpenApiFeature(); + openApiFeature.setTitle("Sample REST Application"); + openApiFeature.setScan(false); + return openApiFeature; + } + + @Bean + Sample sampleResource() { + return new Sample(); + } + + @Bean + org.apache.cxf.endpoint.Server server() { + final JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean (); + factory.setFeatures(Arrays.asList(openApiFeature())); + factory.setServiceBean(sampleResource()); + factory.setAddress("http://localhost:9000/sample"); + factory.setProvider(new JsonbJaxrsProvider<>()); + return factory.create(); + } +} diff --git a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Item.java similarity index 57% copy from rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java copy to distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Item.java index 6b82611..7a32208 100644 --- a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java +++ b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Item.java @@ -16,28 +16,34 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cxf.jaxrs.mpopenapi; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; +package demo.jaxrs.openapi.server; -import org.apache.geronimo.microprofile.openapi.jaxrs.OpenAPIEndpoint; -import org.eclipse.microprofile.openapi.models.OpenAPI; +public class Item { + private String name; + private String value; -@Path("/openapi.{type:json|yaml}") -public class OpenApiEndpoint extends OpenAPIEndpoint { - private OpenAPI openApi; + public Item() { + } + + public Item(final String name, final String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } - public OpenApiEndpoint(OpenAPI openApi) { - this.openApi = openApi; + public String getValue() { + return value; } - @Override - @GET - @Produces({MediaType.APPLICATION_JSON, "application/yaml"}) - public OpenAPI get() { - return openApi; + public void setValue(String value) { + this.value = value; } } diff --git a/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Sample.java b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Sample.java new file mode 100644 index 0000000..64bd691 --- /dev/null +++ b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Sample.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 demo.jaxrs.openapi.server; + +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; + +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.ParameterIn; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.headers.Header; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; + + +@Path("/sample") +public class Sample { + private Map<String, Item> items; + + public Sample() { + items = Collections.synchronizedMap(new TreeMap<String, Item>(String.CASE_INSENSITIVE_ORDER)); + items.put("Item 1", new Item("Item 1", "Value 1")); + items.put("Item 2", new Item("Item 2", "Value 2")); + } + + @Produces({ MediaType.APPLICATION_JSON }) + @GET + @Operation( + summary = "Get all items", + description = "Get operation with Response and @Default value" + ) + @APIResponses( + @APIResponse( + content = @Content(schema = @Schema(implementation = Item.class, type = SchemaType.ARRAY)), + responseCode = "200" + ) + ) + public Response getItems(@Parameter(required = true) @QueryParam("page") @DefaultValue("1") int page) { + return Response.ok(items.values()).build(); + } + + @Produces({ MediaType.APPLICATION_JSON }) + @Path("/{name}") + @GET + @Operation( + summary = "Get item by name", + description = "Get operation with type and headers" + ) + @APIResponses({ + @APIResponse(content = @Content(schema = @Schema(implementation = Item.class)), responseCode = "200"), + @APIResponse(responseCode = "404") + }) + public Response getItem( + @Parameter(required = true) @HeaderParam("Accept-Language") final String language, + @Parameter(required = true) @PathParam("name") String name) { + return items.containsKey(name) + ? Response.ok().entity(items.get(name)).build() + : Response.status(Status.NOT_FOUND).build(); + } + + @Consumes({ MediaType.APPLICATION_JSON }) + @POST + @Operation( + summary = "Create new item", + description = "Post operation with entity in a body" + ) + @APIResponses( + @APIResponse( + content = @Content( + schema = @Schema(implementation = Item.class), + mediaType = MediaType.APPLICATION_JSON + ), + headers = @Header(name = "Location"), + responseCode = "201" + ) + ) + public Response createItem( + @Context final UriInfo uriInfo, + @Parameter(required = true) final Item item) { + items.put(item.getName(), item); + return Response + .created(uriInfo.getBaseUriBuilder().path(item.getName()).build()) + .entity(item).build(); + } + + @Produces({ MediaType.APPLICATION_JSON }) + @Path("/{name}") + @PUT + @Operation( + summary = "Update an existing new item", + description = "Put operation with form parameter" + ) + @APIResponse( + content = @Content(schema = @Schema(implementation = Item.class)), + responseCode = "200" + ) + public Item updateItem( + @Parameter(required = true) @PathParam("name") String name, + @Parameter(required = true) @FormParam("value") String value) { + Item item = new Item(name, value); + items.put(name, item); + return item; + } + + @Path("/{name}") + @DELETE + @Operation( + summary = "Delete an existing new item", + description = "Delete operation with implicit header" + ) + @Parameter( + name = "Accept-Language", + description = "language", + required = true, + schema = @Schema(implementation = String.class), + in = ParameterIn.HEADER + ) + @APIResponse(responseCode = "204", content = @Content(schema = @Schema())) + public void delete(@Parameter(required = true) @PathParam("name") String name) { + items.remove(name); + } +} diff --git a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Server.java similarity index 57% copy from rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java copy to distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Server.java index 6b82611..9365ca1 100644 --- a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java +++ b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/java/demo/jaxrs/openapi/server/Server.java @@ -16,28 +16,22 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cxf.jaxrs.mpopenapi; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; +package demo.jaxrs.openapi.server; -import org.apache.geronimo.microprofile.openapi.jaxrs.OpenAPIEndpoint; -import org.eclipse.microprofile.openapi.models.OpenAPI; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; -@Path("/openapi.{type:json|yaml}") -public class OpenApiEndpoint extends OpenAPIEndpoint { - private OpenAPI openApi; - - public OpenApiEndpoint(OpenAPI openApi) { - this.openApi = openApi; +public final class Server { + private Server() { } - @Override - @GET - @Produces({MediaType.APPLICATION_JSON, "application/yaml"}) - public OpenAPI get() { - return openApi; + public static void main(String[] args) throws Exception { + try (ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class)) { + System.out.println("Server ready..."); + Thread.sleep(5 * 6000 * 1000); + System.out.println("Server exiting"); + System.exit(0); + } } } diff --git a/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/resources/META-INF/cxf/org.apache.cxf.Logger b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/resources/META-INF/cxf/org.apache.cxf.Logger new file mode 100644 index 0000000..27dd788 --- /dev/null +++ b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/resources/META-INF/cxf/org.apache.cxf.Logger @@ -0,0 +1 @@ +org.apache.cxf.common.logging.Slf4jLogger \ No newline at end of file diff --git a/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/resources/logback.xml b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/resources/logback.xml new file mode 100644 index 0000000..59bce12 --- /dev/null +++ b/distribution/src/main/release/samples/jax_rs/description_openapi_microprofile_spring/src/main/resources/logback.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration scan="true" scanPeriod="5 seconds"> + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>[%level] %d{yyyy-MM-dd HH:mm:ss.SSS} %logger{36} - [%X] %msg%n</pattern> + </encoder> + </appender> + + <root level="INFO"> + <appender-ref ref="STDOUT" /> + </root> + + <logger category="io.swagger" name="swagger"> + <level name="DEBUG"/> + </logger> +</configuration> diff --git a/distribution/src/main/release/samples/pom.xml b/distribution/src/main/release/samples/pom.xml index 2362276..51743c0 100644 --- a/distribution/src/main/release/samples/pom.xml +++ b/distribution/src/main/release/samples/pom.xml @@ -142,6 +142,7 @@ <module>wsdl_first_rpclit</module> <module>wsdl_first_soap12</module> <module>wsdl_first_xml_wrapped</module> + <module>jax_rs/description_openapi_microprofile_spring</module> </modules> <dependencyManagement> <dependencies> diff --git a/parent/pom.xml b/parent/pom.xml index 6e657f4..b06fcc2 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -115,6 +115,7 @@ <cxf.geronimo.jta.version>1.1.1</cxf.geronimo.jta.version> <cxf.geronimo.servlet25.version>1.2</cxf.geronimo.servlet25.version> <cxf.geronimo.transaction.version>3.1.4</cxf.geronimo.transaction.version> + <cxf.geronimo.openapi.version>1.0.9</cxf.geronimo.openapi.version> <cxf.glassfish.json.version>1.0.4</cxf.glassfish.json.version> <cxf.guava.version>20.0</cxf.guava.version> <cxf.hamcrest.version>1.3</cxf.hamcrest.version> @@ -159,8 +160,9 @@ <cxf.logback.classic.version>1.2.3</cxf.logback.classic.version> <cxf.lucene.version>4.9.0</cxf.lucene.version> <cxf.maven.core.version>3.6.1</cxf.maven.core.version> - <cxf.microprofile.config.version>1.1</cxf.microprofile.config.version> + <cxf.microprofile.config.version>1.2</cxf.microprofile.config.version> <cxf.microprofile.rest.client.version>1.3.3</cxf.microprofile.rest.client.version> + <cxf.microprofile.openapi.version>1.1.2</cxf.microprofile.openapi.version> <cxf.mina.version>2.0.21</cxf.mina.version> <cxf.mockito.version>2.28.1</cxf.mockito.version> <cxf.msv.version>2013.6.1</cxf.msv.version> @@ -1609,6 +1611,16 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>org.eclipse.microprofile.openapi</groupId> + <artifactId>microprofile-openapi-api</artifactId> + <version>${cxf.microprofile.openapi.version}</version> + </dependency> + <dependency> + <groupId>org.apache.geronimo</groupId> + <artifactId>geronimo-openapi-impl</artifactId> + <version>${cxf.geronimo.openapi.version}</version> + </dependency> + <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> <version>${cxf.slf4j.version}</version> @@ -2171,6 +2183,11 @@ </dependency> <dependency> <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-jsonb_1.0_spec</artifactId> + <version>${cxf.geronimo.jsonb.version}</version> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-json_1.1_spec</artifactId> <version>${cxf.geronimo.json.version}</version> </dependency> diff --git a/rt/rs/description-microprofile-openapi/pom.xml b/rt/rs/description-microprofile-openapi/pom.xml index 1f6533e..a7e23ab 100644 --- a/rt/rs/description-microprofile-openapi/pom.xml +++ b/rt/rs/description-microprofile-openapi/pom.xml @@ -48,6 +48,10 @@ <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxrs</artifactId> + </dependency> + <dependency> + <groupId>org.apache.cxf</groupId> + <artifactId>cxf-rt-rs-service-description-common-openapi</artifactId> <version>${project.version}</version> </dependency> <dependency> @@ -58,19 +62,26 @@ <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-rs-json-basic</artifactId> - <version>${project.version}</version> <scope>provided</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.eclipse.microprofile.openapi</groupId> <artifactId>microprofile-openapi-api</artifactId> - <version>1.1.2</version> </dependency> <dependency> <groupId>org.apache.geronimo</groupId> <artifactId>geronimo-openapi-impl</artifactId> - <version>1.0.9</version> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-jsonb_1.0_spec</artifactId> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-json_1.1_spec</artifactId> + <scope>compile</scope> </dependency> <dependency> <groupId>org.osgi</groupId> diff --git a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java b/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/OpenApiEndpoint.java similarity index 96% rename from rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java rename to rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/OpenApiEndpoint.java index 6b82611..faba9fb 100644 --- a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiEndpoint.java +++ b/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/OpenApiEndpoint.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cxf.jaxrs.mpopenapi; +package org.apache.cxf.jaxrs.microprofile.openapi; import javax.ws.rs.GET; import javax.ws.rs.Path; diff --git a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiFeature.java b/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/OpenApiFeature.java similarity index 83% rename from rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiFeature.java rename to rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/OpenApiFeature.java index c65fd9b..d07ec63 100644 --- a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/OpenApiFeature.java +++ b/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/OpenApiFeature.java @@ -16,12 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.cxf.jaxrs.mpopenapi; +package org.apache.cxf.jaxrs.microprofile.openapi; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -39,9 +38,9 @@ import org.apache.cxf.common.logging.LogUtils; import org.apache.cxf.endpoint.Server; import org.apache.cxf.feature.AbstractFeature; import org.apache.cxf.jaxrs.JAXRSServiceFactoryBean; +import org.apache.cxf.jaxrs.common.openapi.DefaultApplicationFactory; +import org.apache.cxf.jaxrs.common.openapi.SwaggerProperties; import org.apache.cxf.jaxrs.model.AbstractResourceInfo; -import org.apache.cxf.jaxrs.model.ApplicationInfo; -import org.apache.cxf.jaxrs.model.ClassResourceInfo; import org.apache.cxf.jaxrs.provider.ServerProviderFactory; import org.apache.cxf.jaxrs.swagger.ui.SwaggerUiConfig; import org.apache.cxf.jaxrs.swagger.ui.SwaggerUiSupport; @@ -61,8 +60,6 @@ import org.eclipse.microprofile.openapi.models.OpenAPI; public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport, SwaggerProperties { private static final Logger LOG = LogUtils.getL7dLogger(OpenApiFeature.class); - private static final String DEFAULT_PROPS_LOCATION = "/swagger.properties"; - private String version; private String title; private String description; @@ -98,22 +95,6 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport, // Swagger UI configuration parameters (to be passed as query string). private SwaggerUiConfig swaggerUiConfig; - protected static class DefaultApplication extends Application { - - private final Set<Class<?>> serviceClasses; - - DefaultApplication(final List<ClassResourceInfo> cris, final Set<String> resourcePackages) { - this.serviceClasses = cris.stream().map(ClassResourceInfo::getServiceClass). - filter(cls -> (resourcePackages == null || resourcePackages.isEmpty()) || resourcePackages.stream(). - anyMatch(pkg -> cls.getPackage().getName().startsWith(pkg))).collect(Collectors.toSet()); - } - - @Override - public Set<Class<?>> getClasses() { - return serviceClasses; - } - } - @Override public void initialize(Server server, Bus bus) { final JAXRSServiceFactoryBean sfb = (JAXRSServiceFactoryBean)server @@ -129,35 +110,49 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport, packages.addAll(resourcePackages); } - final Application application = getApplicationOrDefault(server, factory, sfb, bus); + final Application application = DefaultApplicationFactory.createApplicationOrDefault(server, factory, + sfb, bus, resourcePackages, isScan()); final AnnotationProcessor processor = new AnnotationProcessor(GeronimoOpenAPIConfig.create(), - new NamingStrategy.Http()); + new NamingStrategy.Http()); final OpenAPIImpl api = new OpenAPIImpl(); if (isScan()) { packages.addAll(scanResourcePackages(sfb)); } + + final Set<Class<?>> resources = new HashSet<>(); if (application != null) { processor.processApplication(api, new ClassElement(application.getClass())); LOG.fine("Processed application " + application); - } - Set<Class<?>> endpointClasses = sfb - .getClassResourceInfo() + + if (application.getClasses() != null) { + resources.addAll(application.getClasses()); + } + } + + resources.addAll(sfb + .getClassResourceInfo() + .stream() + .map(AbstractResourceInfo::getServiceClass) + .filter(cls -> filterByPackage(cls, packages)) + .filter(cls -> filterByClassName(cls, resourceClasses)) + .collect(Collectors.toSet())); + + if (!resources.isEmpty()) { + final String binding = (application == null) ? "" + : processor.getApplicationBinding(application.getClass()); + + resources .stream() - .map(AbstractResourceInfo::getServiceClass) - .collect(Collectors.toSet()); - if (!endpointClasses.isEmpty()) { - final String binding = application == null ? "" : processor.getApplicationBinding(application.getClass()); - endpointClasses.stream() - .peek(c -> LOG.info("Processing class " + c.getName())) - .forEach(c -> processor.processClass( - binding, api, new ClassElement(c), - Stream.of(c.getMethods()).map(MethodElement::new))); + .peek(c -> LOG.info("Processing class " + c.getName())) + .forEach(c -> processor.processClass(binding, api, new ClassElement(c), + Stream.of(c.getMethods()).map(MethodElement::new))); } else { - LOG.warning("No <endpointClasses> registered, your OpenAPI will be empty."); + LOG.warning("No resource classes registered, the OpenAPI will not contain any endpoints."); } + Properties swaggerProps = getSwaggerProperties(propertiesLocation, bus); if (api.getInfo() == null) { api.setInfo(getInfo(swaggerProps)); @@ -410,29 +405,6 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport, } /** - * Detects the application (if present) or creates the default application (in case the scan is disabled). - */ - protected Application getApplicationOrDefault( - final Server server, - final ServerProviderFactory factory, - final JAXRSServiceFactoryBean sfb, - final Bus bus) { - - ApplicationInfo appInfo = null; - if (!isScan()) { - appInfo = factory.getApplicationProvider(); - - if (appInfo == null) { - appInfo = new ApplicationInfo( - new DefaultApplication(sfb.getClassResourceInfo(), resourcePackages), bus); - server.getEndpoint().put(Application.class.getName(), appInfo); - } - } - - return (appInfo == null) ? null : appInfo.getProvider(); - } - - /** * The info will be used only if there is no @OpenAPIDefinition annotation is present. */ private org.eclipse.microprofile.openapi.models.info.Info getInfo(final Properties properties) { @@ -470,5 +442,14 @@ public class OpenApiFeature extends AbstractFeature implements SwaggerUiSupport, .map(cri -> cri.getServiceClass().getPackage().getName()) .collect(Collectors.toSet()); } - + + private static boolean filterByPackage(final Class<?> cls, final Set<String> packages) { + return (packages == null || packages.isEmpty()) + || packages.stream().anyMatch(pkg -> cls.getPackage().getName().startsWith(pkg)); + } + + private static boolean filterByClassName(final Class<?> cls, final Set<String> classes) { + return (classes == null || classes.isEmpty()) + || classes.stream().anyMatch(cls.getName()::equalsIgnoreCase); + } } diff --git a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/SwaggerUi.java b/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/SwaggerUi.java similarity index 97% rename from rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/SwaggerUi.java rename to rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/SwaggerUi.java index f796dfb..b051030 100644 --- a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/SwaggerUi.java +++ b/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/microprofile/openapi/SwaggerUi.java @@ -17,7 +17,7 @@ * under the License. */ -package org.apache.cxf.jaxrs.mpopenapi; +package org.apache.cxf.jaxrs.microprofile.openapi; import org.apache.cxf.jaxrs.swagger.ui.SwaggerUiResolver; diff --git a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/SwaggerProperties.java b/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/SwaggerProperties.java deleted file mode 100644 index c4b4c2a..0000000 --- a/rt/rs/description-microprofile-openapi/src/main/java/org/apache/cxf/jaxrs/mpopenapi/SwaggerProperties.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * 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.cxf.jaxrs.mpopenapi; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -import org.apache.cxf.Bus; -import org.apache.cxf.jaxrs.utils.ResourceUtils; - -interface SwaggerProperties { - String RESOURCE_PACKAGE_PROPERTY = "resource.package"; - String TITLE_PROPERTY = "title"; - String VERSION_PROPERTY = "version"; - String DESCRIPTION_PROPERTY = "description"; - String CONTACT_PROPERTY = "contact"; - String LICENSE_PROPERTY = "license"; - String LICENSE_URL_PROPERTY = "license.url"; - String TERMS_URL_PROPERTY = "terms.url"; - String PRETTY_PRINT_PROPERTY = "pretty.print"; - String FILTER_CLASS_PROPERTY = "filter.class"; - - /** - * Read the Swagger-specific properties from the property file (to seamlessly - * support the migration from older Swagger features). - * @param location property file location - * @param bus bus instance - * @return the properties if available - */ - default Properties getSwaggerProperties(String location, Bus bus) { - InputStream is = ResourceUtils.getClasspathResourceStream(location, SwaggerProperties.class, bus); - Properties props = null; - - if (is != null) { - props = new Properties(); - try { - props.load(is); - } catch (IOException ex) { - props = null; - } finally { - try { - is.close(); - } catch (IOException ignore) { - // ignore - } - } - } - - return props; - } -}
