You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomee.apache.org by GitBox <gi...@apache.org> on 2022/11/24 06:57:01 UTC

[GitHub] [tomee] rzo1 commented on a diff in pull request #978: TOMEE-4117 OpenAPI model not being generated from annotations.

rzo1 commented on code in PR #978:
URL: https://github.com/apache/tomee/pull/978#discussion_r1031113569


##########
tomee/tomee-microprofile/mp-common/src/main/java/org/apache/tomee/microprofile/openapi/MicroProfileOpenApiRegistration.java:
##########
@@ -16,76 +16,202 @@
  */
 package org.apache.tomee.microprofile.openapi;
 
+import io.smallrye.config.PropertiesConfigSource;
+import io.smallrye.config.SmallRyeConfig;
+import io.smallrye.config.SmallRyeConfigBuilder;
 import io.smallrye.openapi.api.OpenApiConfig;
 import io.smallrye.openapi.api.OpenApiConfigImpl;
 import io.smallrye.openapi.api.OpenApiDocument;
 import io.smallrye.openapi.runtime.OpenApiProcessor;
 import io.smallrye.openapi.runtime.OpenApiStaticFile;
 import io.smallrye.openapi.runtime.io.Format;
+import io.smallrye.openapi.runtime.scanner.FilteredIndexView;
 import jakarta.servlet.ServletContainerInitializer;
 import jakarta.servlet.ServletContext;
 import jakarta.servlet.ServletException;
 import jakarta.servlet.ServletRegistration;
+import jakarta.servlet.annotation.HandlesTypes;
+import jakarta.ws.rs.ApplicationPath;
+import jakarta.ws.rs.Path;
+import org.apache.openejb.loader.IO;
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
+import org.apache.tomee.microprofile.health.MicroProfileHealthChecksEndpoint;
 import org.eclipse.microprofile.config.Config;
 import org.eclipse.microprofile.config.ConfigProvider;
 import org.eclipse.microprofile.openapi.models.OpenAPI;
+import org.jboss.jandex.DotName;
+import org.jboss.jandex.Index;
+import org.jboss.jandex.Indexer;
 
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Collection;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Properties;
 import java.util.Set;
 import java.util.stream.Stream;
 
+import static io.smallrye.openapi.runtime.OpenApiProcessor.getFilter;
+import static io.smallrye.openapi.runtime.OpenApiProcessor.modelFromAnnotations;
+import static io.smallrye.openapi.runtime.OpenApiProcessor.modelFromReader;
 import static io.smallrye.openapi.runtime.io.Format.JSON;
 import static io.smallrye.openapi.runtime.io.Format.YAML;
+import static java.lang.Thread.currentThread;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.Optional.ofNullable;
 
 /**
- * Responsible for adding the filter into the chain and doing all other initialization
- * <p>
- * todo do we want to be so restrictive with the HandlesTypes annotation?
  *
- * @HandlesTypes({Path.class, WebServlet.class,
- * WebFilter.class
- * })
+ * This servlet container initializer is responsible for registering the OpenAPI servlet in each application so /openapi
+ * becomes available for applications to consume.
+ *
+ * It will first try to load static openapi files in format JSON, YAML and YML. If not found, it will try to generate the
+ * model on the fly for the endpoints.
+ *
  */
+// we'll get all the classes of the application and when creating the index we'll apply the filtering
+// we could have used only @Path from JAX RS because in the end, we only need those to generate the OpenAPI Model
+@HandlesTypes({
+    Path.class,
+    ApplicationPath.class
+})
 public class MicroProfileOpenApiRegistration implements ServletContainerInitializer {
 
+    private static final Logger LOGGER = Logger.getInstance(LogCategory.MICROPROFILE, MicroProfileOpenApiRegistration.class);
+
     @Override
     public void onStartup(final Set<Class<?>> classes, final ServletContext ctx) throws ServletException {
+
+        LOGGER.info("Registering OpenAPI servlet on /openapi for application " + ctx.getContextPath());
         final ServletRegistration.Dynamic servletRegistration =
             ctx.addServlet("mp-openapi-servlet", MicroProfileOpenApiEndpoint.class);
         servletRegistration.addMapping("/openapi/*");
 
-        openApi(ctx);
+        // generate the OpenAPI document from static file or model reader or from annotations
+        final Optional<OpenAPI> openAPI = generateOpenAPI(classes, ctx);
+        openAPI.ifPresent(openApi -> setOpenApi(ctx, openAPI.get()));
+    }
+
+    /**
+     * Builds the OpenAPI file and copies it to the deployed application.
+     *
+     * @return The generated OpenAPI model wrapped into an Optional
+     */
+    private Optional<OpenAPI> generateOpenAPI(final Set<Class<?>> classes, final ServletContext servletContext) {
+        final OpenApiConfig openApiConfig = config(servletContext);
+        final Index index = index(classes, servletContext, openApiConfig);
+        final ClassLoader contextClassLoader = currentThread().getContextClassLoader();
+
+        Optional<OpenAPI> annotationModel = ofNullable(modelFromAnnotations(openApiConfig, contextClassLoader, index));
+        Optional<OpenAPI> readerModel = ofNullable(modelFromReader(openApiConfig, contextClassLoader));
+        Optional<OpenAPI> staticFileModel = openApiFromStaticFile(servletContext);
+
+        final OpenApiDocument document = OpenApiDocument.INSTANCE;
+        try {
+            document.reset();
+            document.config(openApiConfig);
+            annotationModel.ifPresent(document::modelFromAnnotations);
+            readerModel.ifPresent(document::modelFromReader);
+            staticFileModel.ifPresent(document::modelFromStaticFile);
+            document.filter(getFilter(openApiConfig, contextClassLoader));
+            document.initialize();
+            return Optional.ofNullable(document.get());
+
+        } finally {
+            document.reset();
+        }
+    }
+
+    /**
+     * Provides the Jandex index.
+     */
+    private static Index index(final Set<Class<?>> classes, final ServletContext servletContext, final OpenApiConfig config) {
+        FilteredIndexView filteredIndexView = new FilteredIndexView(null, config);
+        Indexer indexer = new Indexer();
+
+        // todo load all classes and build up an index with the content

Review Comment:
   still an todo?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscribe@tomee.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org