Skip to content

Commit

Permalink
Merge pull request #11638 from phillip-kruger/openapi-store-schema
Browse files Browse the repository at this point in the history
Added option to save the generated OpenAPI schema document on build.
  • Loading branch information
gsmet authored Aug 27, 2020
2 parents 078f7c5 + 14cf55e commit 516e47a
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.quarkus.smallrye.openapi.common.deployment;

import java.nio.file.Path;
import java.util.Optional;

import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigRoot;

Expand All @@ -10,4 +13,11 @@ public final class SmallRyeOpenApiConfig {
*/
@ConfigItem(defaultValue = "/openapi")
public String path;

/**
* If set, the generated OpenAPI schema documents will be stored here on build.
* Both openapi.json and openapi.yaml will be stored here if this is set.
*/
@ConfigItem
public Optional<Path> storeSchemaDirectory;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -29,6 +31,7 @@
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.Type;
import org.jboss.logging.Logger;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.BeanArchiveIndexBuildItem;
Expand Down Expand Up @@ -81,6 +84,8 @@
*/
public class SmallRyeOpenApiProcessor {

private static final Logger log = Logger.getLogger("io.quarkus.smallrye.openapi");

private static final String META_INF_OPENAPI_YAML = "META-INF/openapi.yaml";
private static final String WEB_INF_CLASSES_META_INF_OPENAPI_YAML = "WEB-INF/classes/META-INF/openapi.yaml";
private static final String META_INF_OPENAPI_YML = "META-INF/openapi.yml";
Expand All @@ -103,7 +108,7 @@ public class SmallRyeOpenApiProcessor {
private static final String SPRING = "Spring";
private static final String VERT_X = "Vert.x";

SmallRyeOpenApiConfig openapi;
SmallRyeOpenApiConfig openApiConfig;

@BuildStep
void contributeClassesToIndex(BuildProducer<AdditionalIndexedClassesBuildItem> additionalIndexedClasses) {
Expand Down Expand Up @@ -143,9 +148,9 @@ RouteBuildItem handler(LaunchModeBuildItem launch,
*/
if (launch.getLaunchMode() == LaunchMode.DEVELOPMENT) {
recorder.setupClDevMode(shutdownContext);
displayableEndpoints.produce(new NotFoundPageDisplayableEndpointBuildItem(openapi.path));
displayableEndpoints.produce(new NotFoundPageDisplayableEndpointBuildItem(openApiConfig.path));
}
return new RouteBuildItem(openapi.path, new OpenApiHandler(), HandlerType.BLOCKING);
return new RouteBuildItem(openApiConfig.path, new OpenApiHandler(), HandlerType.BLOCKING);
}

@BuildStep
Expand Down Expand Up @@ -317,11 +322,16 @@ public void build(ApplicationArchivesBuildItem archivesBuildItem,
annotationModel = null;
}
OpenApiDocument finalDocument = loadDocument(staticModel, annotationModel);
boolean shouldStore = openApiConfig.storeSchemaDirectory.isPresent();
for (Format format : Format.values()) {
String name = OpenApiHandler.BASE_NAME + format;
resourceBuildItemBuildProducer.produce(new GeneratedResourceBuildItem(name,
OpenApiSerializer.serialize(finalDocument.get(), format).getBytes(StandardCharsets.UTF_8)));
byte[] schemaDocument = OpenApiSerializer.serialize(finalDocument.get(), format).getBytes(StandardCharsets.UTF_8);
resourceBuildItemBuildProducer.produce(new GeneratedResourceBuildItem(name, schemaDocument));
nativeImageResources.produce(new NativeImageResourceBuildItem(name));

if (shouldStore) {
storeGeneratedSchema(schemaDocument, format);
}
}
}

Expand All @@ -331,6 +341,21 @@ LogCleanupFilterBuildItem logCleanup() {
"OpenAPI document initialized:");
}

private void storeGeneratedSchema(byte[] schemaDocument, Format format) throws IOException {
Path directory = openApiConfig.storeSchemaDirectory.get();
if (!Files.exists(directory)) {
Files.createDirectories(directory);
}

Path file = Paths.get(directory.toString(), "openapi." + format.toString().toLowerCase());
if (!Files.exists(file)) {
Files.createFile(file);
}
Files.write(file, schemaDocument, StandardOpenOption.WRITE);

log.info("OpenAPI " + format.toString() + " saved: " + file.toString());
}

private boolean shouldScanAnnotations(Capabilities capabilities, IndexView index) {
// Disabled via config
Config config = ConfigProvider.getConfig();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.quarkus.smallrye.openapi.test.jaxrs;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.smallrye.openapi.runtime.io.Format;

public class OpenApiStoreSchemaTestCase {

private static String directory = "target/generated/jax-rs/";
private static final String OPEN_API_DOT = "openapi.";

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(OpenApiResource.class, ResourceBean.class)
.addAsResource(new StringAsset("quarkus.smallrye-openapi.store-schema-directory=" + directory),
"application.properties"));

@Test
public void testOpenApiPathAccessResource() {
Path json = Paths.get(directory, OPEN_API_DOT + Format.JSON.toString().toLowerCase());
Assertions.assertTrue(Files.exists(json));
Path yaml = Paths.get(directory, OPEN_API_DOT + Format.YAML.toString().toLowerCase());
Assertions.assertTrue(Files.exists(yaml));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.quarkus.smallrye.openapi.test.spring;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.smallrye.openapi.runtime.io.Format;

public class OpenApiStoreSchemaTestCase {

private static String directory = "target/generated/spring/";
private static final String OPEN_API_DOT = "openapi.";

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(OpenApiController.class)
.addAsResource(new StringAsset("quarkus.smallrye-openapi.store-schema-directory=" + directory),
"application.properties"));

@Test
public void testOpenApiPathAccessResource() {
Path json = Paths.get(directory, OPEN_API_DOT + Format.JSON.toString().toLowerCase());
Assertions.assertTrue(Files.exists(json));
Path yaml = Paths.get(directory, OPEN_API_DOT + Format.YAML.toString().toLowerCase());
Assertions.assertTrue(Files.exists(yaml));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.quarkus.smallrye.openapi.test.vertx;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.smallrye.openapi.runtime.io.Format;

public class OpenApiStoreSchemaTestCase {

private static String directory = "target/generated/vertx/";
private static final String OPEN_API_DOT = "openapi.";

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(OpenApiRoute.class)
.addAsResource(new StringAsset("quarkus.smallrye-openapi.store-schema-directory=" + directory),
"application.properties"));

@Test
public void testOpenApiPathAccessResource() {
Path json = Paths.get(directory, OPEN_API_DOT + Format.JSON.toString().toLowerCase());
Assertions.assertTrue(Files.exists(json));
Path yaml = Paths.get(directory, OPEN_API_DOT + Format.YAML.toString().toLowerCase());
Assertions.assertTrue(Files.exists(yaml));
}
}

0 comments on commit 516e47a

Please sign in to comment.