From 02b47143c3fdbabd4d4cee6c00f0110dbe30a071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Justin?= Date: Thu, 20 Aug 2020 15:21:45 +0200 Subject: [PATCH] Quarkus 1.7.0.Final + IBM api test fix (#776) * Upgrade Quarkus to 1.7.0.Final * Fix all schemas check - missing paging. * Make sure request is only used in http context. --- .../registry/rest/ArtifactsResourceImpl.java | 110 ++++++++++++------ .../registry/util/ContentTypeUtil.java | 19 ++- .../registry/ibmcompat/IBMCompatApiTest.java | 65 +++++++---- pom.xml | 2 +- .../client/hotrod/HotRodSearchClient.java | 8 +- 5 files changed, 130 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/io/apicurio/registry/rest/ArtifactsResourceImpl.java b/app/src/main/java/io/apicurio/registry/rest/ArtifactsResourceImpl.java index fddd162e7a..b73a03e7b6 100644 --- a/app/src/main/java/io/apicurio/registry/rest/ArtifactsResourceImpl.java +++ b/app/src/main/java/io/apicurio/registry/rest/ArtifactsResourceImpl.java @@ -21,13 +21,29 @@ import io.apicurio.registry.metrics.ResponseErrorLivenessCheck; import io.apicurio.registry.metrics.ResponseTimeoutReadinessCheck; import io.apicurio.registry.metrics.RestMetricsApply; -import io.apicurio.registry.rest.beans.*; +import io.apicurio.registry.rest.beans.ArtifactMetaData; +import io.apicurio.registry.rest.beans.EditableMetaData; +import io.apicurio.registry.rest.beans.IfExistsType; +import io.apicurio.registry.rest.beans.Rule; +import io.apicurio.registry.rest.beans.UpdateState; +import io.apicurio.registry.rest.beans.VersionMetaData; import io.apicurio.registry.rules.RuleApplicationType; import io.apicurio.registry.rules.RulesService; import io.apicurio.registry.search.client.SearchClient; import io.apicurio.registry.search.common.Search; -import io.apicurio.registry.storage.*; -import io.apicurio.registry.types.*; +import io.apicurio.registry.storage.ArtifactAlreadyExistsException; +import io.apicurio.registry.storage.ArtifactMetaDataDto; +import io.apicurio.registry.storage.ArtifactNotFoundException; +import io.apicurio.registry.storage.ArtifactVersionMetaDataDto; +import io.apicurio.registry.storage.EditableArtifactMetaDataDto; +import io.apicurio.registry.storage.RegistryStorage; +import io.apicurio.registry.storage.RuleConfigurationDto; +import io.apicurio.registry.storage.StoredArtifact; +import io.apicurio.registry.types.ArtifactMediaTypes; +import io.apicurio.registry.types.ArtifactState; +import io.apicurio.registry.types.ArtifactType; +import io.apicurio.registry.types.Current; +import io.apicurio.registry.types.RuleType; import io.apicurio.registry.util.ArtifactIdGenerator; import io.apicurio.registry.util.ArtifactTypeUtil; import io.apicurio.registry.util.ContentTypeUtil; @@ -57,7 +73,13 @@ import java.util.concurrent.CompletionStage; import java.util.function.Supplier; -import static io.apicurio.registry.metrics.MetricIDs.*; +import static io.apicurio.registry.metrics.MetricIDs.REST_CONCURRENT_REQUEST_COUNT; +import static io.apicurio.registry.metrics.MetricIDs.REST_CONCURRENT_REQUEST_COUNT_DESC; +import static io.apicurio.registry.metrics.MetricIDs.REST_GROUP_TAG; +import static io.apicurio.registry.metrics.MetricIDs.REST_REQUEST_COUNT; +import static io.apicurio.registry.metrics.MetricIDs.REST_REQUEST_COUNT_DESC; +import static io.apicurio.registry.metrics.MetricIDs.REST_REQUEST_RESPONSE_TIME; +import static io.apicurio.registry.metrics.MetricIDs.REST_REQUEST_RESPONSE_TIME_DESC; import static org.eclipse.microprofile.metrics.MetricUnits.MILLISECONDS; /** @@ -95,6 +117,14 @@ public class ArtifactsResourceImpl implements ArtifactsResource, Headers { private static final int GET_ARTIFACT_IDS_LIMIT = 10000; + /** + * Make sure this is ONLY used when request instance is active. + * e.g. in actual http request + */ + private String getContentType() { + return request.getContentType(); + } + /** * Figures out the artifact type in the following order of precedent: *

@@ -102,17 +132,16 @@ public class ArtifactsResourceImpl implements ArtifactsResource, Headers { * 2) A hint provided in the Content-Type header * 3) Determined from the content itself * - * @param content the content + * @param content the content * @param xArtifactType the artifact type - * @param request http request + * @param ct content type from request API */ - private static ArtifactType determineArtifactType(ContentHandle content, ArtifactType xArtifactType, HttpServletRequest request) { + private static ArtifactType determineArtifactType(ContentHandle content, ArtifactType xArtifactType, String ct) { ArtifactType artifactType = xArtifactType; if (artifactType == null) { - artifactType = getArtifactTypeFromContentType(request); + artifactType = getArtifactTypeFromContentType(ct); if (artifactType == null) { - String contentType = request.getContentType(); - artifactType = ArtifactTypeUtil.discoverType(content, contentType); + artifactType = ArtifactTypeUtil.discoverType(content, ct); } } return artifactType; @@ -121,10 +150,9 @@ private static ArtifactType determineArtifactType(ContentHandle content, Artifac /** * Tries to figure out the artifact type by analyzing the content-type. * - * @param request http request + * @param contentType the content type header */ - private static ArtifactType getArtifactTypeFromContentType(HttpServletRequest request) { - String contentType = request.getHeader("Content-Type"); + private static ArtifactType getArtifactTypeFromContentType(String contentType) { if (contentType != null && contentType.contains(MediaType.APPLICATION_JSON) && contentType.indexOf(';') != -1) { String[] split = contentType.split(";"); if (split.length > 1) { @@ -176,24 +204,31 @@ private CompletionStage indexArtifact(String artifactId, Conte } } - private CompletionStage handleIfExists(ArtifactType artifactType, - String artifactId, IfExistsType ifExists, ContentHandle content) { + private CompletionStage handleIfExists( + ArtifactType artifactType, + String artifactId, + IfExistsType ifExists, + ContentHandle content, + String ct) { final ArtifactMetaData artifactMetaData = getArtifactMetaData(artifactId); switch (ifExists) { case UPDATE: - return updateArtifactInternal(artifactId, artifactType, content); + return updateArtifactInternal(artifactId, artifactType, content, ct); case RETURN: return CompletableFuture.completedFuture(artifactMetaData); case RETURN_OR_UPDATE: - return handleIfExistsReturnOrUpdate(artifactId, artifactType, content); + return handleIfExistsReturnOrUpdate(artifactId, artifactType, content, ct); default: throw new ArtifactAlreadyExistsException(artifactId); } } - private CompletionStage handleIfExistsReturnOrUpdate(String artifactId, - ArtifactType artifactType, ContentHandle content) { + private CompletionStage handleIfExistsReturnOrUpdate( + String artifactId, + ArtifactType artifactType, + ContentHandle content, + String ct) { try { ArtifactMetaDataDto mdDto = this.storage.getArtifactMetaData(artifactId, content); ArtifactMetaData md = DtoUtil.dtoToMetaData(artifactId, artifactType, mdDto); @@ -201,7 +236,7 @@ private CompletionStage handleIfExistsReturnOrUpdate(String ar } catch (ArtifactNotFoundException nfe) { // This is OK - we'll update the artifact if there is no matching content already there. } - return updateArtifactInternal(artifactId, artifactType, content); + return updateArtifactInternal(artifactId, artifactType, content, ct); } @Override @@ -245,11 +280,12 @@ public void updateArtifactVersionState(Integer version, String artifactId, Updat public void testUpdateArtifact(String artifactId, ArtifactType xRegistryArtifactType, InputStream data) { Objects.requireNonNull(artifactId); ContentHandle content = ContentHandle.create(data); - if (ContentTypeUtil.isApplicationYaml(request)) { + String ct = getContentType(); + if (ContentTypeUtil.isApplicationYaml(ct)) { content = ContentTypeUtil.yamlToJson(content); } - ArtifactType artifactType = determineArtifactType(content, xRegistryArtifactType, request); + ArtifactType artifactType = determineArtifactType(content, xRegistryArtifactType, ct); rulesService.applyRules(artifactId, artifactType, content, RuleApplicationType.UPDATE); } @@ -258,8 +294,9 @@ public void testUpdateArtifact(String artifactId, ArtifactType xRegistryArtifact */ @Override public CompletionStage createArtifact(ArtifactType xRegistryArtifactType, - String xRegistryArtifactId, IfExistsType ifExists, InputStream data) { + String xRegistryArtifactId, IfExistsType ifExists, InputStream data) { ContentHandle content = ContentHandle.create(data); + String ct = getContentType(); final ContentHandle finalContent = content; try { String artifactId = xRegistryArtifactId; @@ -267,11 +304,11 @@ public CompletionStage createArtifact(ArtifactType xRegistryAr if (artifactId == null || artifactId.trim().isEmpty()) { artifactId = idGenerator.generate(); } - if (ContentTypeUtil.isApplicationYaml(request)) { + if (ContentTypeUtil.isApplicationYaml(ct)) { content = ContentTypeUtil.yamlToJson(content); } - ArtifactType artifactType = determineArtifactType(content, xRegistryArtifactType, request); + ArtifactType artifactType = determineArtifactType(content, xRegistryArtifactType, ct); rulesService.applyRules(artifactId, artifactType, content, RuleApplicationType.CREATE); final String finalArtifactId = artifactId; return storage.createArtifact(artifactId, artifactType, content) @@ -285,12 +322,12 @@ public CompletionStage createArtifact(ArtifactType xRegistryAr throw new CompletionException(t); }) .thenCompose(amd -> amd == null ? - handleIfExists(xRegistryArtifactType, xRegistryArtifactId, ifExists, finalContent) : + handleIfExists(xRegistryArtifactType, xRegistryArtifactId, ifExists, finalContent, ct) : CompletableFuture.completedFuture(DtoUtil.dtoToMetaData(finalArtifactId, artifactType, amd)) ) .thenCompose(amdd -> indexArtifact(finalArtifactId, finalContent, amdd)); } catch (ArtifactAlreadyExistsException ex) { - return handleIfExists(xRegistryArtifactType, xRegistryArtifactId, ifExists, content) + return handleIfExists(xRegistryArtifactType, xRegistryArtifactId, ifExists, content, ct) .thenCompose(amdd -> indexArtifact(xRegistryArtifactId, finalContent, amdd)); } } @@ -320,13 +357,17 @@ public Response getLatestArtifact(String artifactId) { return builder.build(); } - private CompletionStage updateArtifactInternal(String artifactId, ArtifactType xRegistryArtifactType, ContentHandle content) { + private CompletionStage updateArtifactInternal( + String artifactId, + ArtifactType xRegistryArtifactType, + ContentHandle content, + String ct) { Objects.requireNonNull(artifactId); - if (ContentTypeUtil.isApplicationYaml(request)) { + if (ContentTypeUtil.isApplicationYaml(ct)) { content = ContentTypeUtil.yamlToJson(content); } - ArtifactType artifactType = determineArtifactType(content, xRegistryArtifactType, request); + ArtifactType artifactType = determineArtifactType(content, xRegistryArtifactType, ct); rulesService.applyRules(artifactId, artifactType, content, RuleApplicationType.UPDATE); return storage.updateArtifact(artifactId, artifactType, content).thenApply(dto -> DtoUtil.dtoToMetaData(artifactId, artifactType, dto)); } @@ -337,7 +378,7 @@ private CompletionStage updateArtifactInternal(String artifact @Override public CompletionStage updateArtifact(String artifactId, ArtifactType xRegistryArtifactType, InputStream data) { ContentHandle content = ContentHandle.create(data); - return updateArtifactInternal(artifactId, xRegistryArtifactType, content) + return updateArtifactInternal(artifactId, xRegistryArtifactType, content, getContentType()) .thenCompose(amdd -> indexArtifact(artifactId, content, amdd)); } @@ -365,11 +406,12 @@ public List listArtifactVersions(String artifactId) { public CompletionStage createArtifactVersion(String artifactId, ArtifactType xRegistryArtifactType, InputStream data) { Objects.requireNonNull(artifactId); ContentHandle content = ContentHandle.create(data); - if (ContentTypeUtil.isApplicationYaml(request)) { + String ct = getContentType(); + if (ContentTypeUtil.isApplicationYaml(ct)) { content = ContentTypeUtil.yamlToJson(content); } - ArtifactType artifactType = determineArtifactType(content, xRegistryArtifactType, request); + ArtifactType artifactType = determineArtifactType(content, xRegistryArtifactType, ct); rulesService.applyRules(artifactId, artifactType, content, RuleApplicationType.UPDATE); final ContentHandle finalContent = content; return storage.updateArtifact(artifactId, artifactType, content) @@ -477,7 +519,7 @@ public ArtifactMetaData getArtifactMetaData(String artifactId) { @Override public ArtifactMetaData getArtifactMetaDataByContent(String artifactId, InputStream data) { ContentHandle content = ContentHandle.create(data); - if (ContentTypeUtil.isApplicationYaml(request)) { + if (ContentTypeUtil.isApplicationYaml(getContentType())) { content = ContentTypeUtil.yamlToJson(content); } diff --git a/app/src/main/java/io/apicurio/registry/util/ContentTypeUtil.java b/app/src/main/java/io/apicurio/registry/util/ContentTypeUtil.java index a0f1e99fd5..eafdf96be8 100644 --- a/app/src/main/java/io/apicurio/registry/util/ContentTypeUtil.java +++ b/app/src/main/java/io/apicurio/registry/util/ContentTypeUtil.java @@ -16,12 +16,9 @@ package io.apicurio.registry.util; -import javax.servlet.http.HttpServletRequest; - import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; - import io.apicurio.registry.content.ContentHandle; /** @@ -38,10 +35,10 @@ public final class ContentTypeUtil { /** * Returns true if the Content-Type of the inbound request is "application/json". - * @param request + * + * @param ct content type */ - public static final boolean isApplicationJson(HttpServletRequest request) { - String ct = request.getContentType(); + public static boolean isApplicationJson(String ct) { if (ct == null) { return false; } @@ -50,17 +47,17 @@ public static final boolean isApplicationJson(HttpServletRequest request) { /** * Returns true if the Content-Type of the inbound request is "application/x-yaml". - * @param request + * + * @param ct content type */ - public static final boolean isApplicationYaml(HttpServletRequest request) { - String ct = request.getContentType(); + public static boolean isApplicationYaml(String ct) { if (ct == null) { return false; } return ct.contains(CT_APPLICATION_YAML); } - - public static final ContentHandle yamlToJson(ContentHandle yaml) { + + public static ContentHandle yamlToJson(ContentHandle yaml) { try { JsonNode root = yamlMapper.readTree(yaml.stream()); return ContentHandle.create(jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsBytes(root)); diff --git a/app/src/test/java/io/apicurio/registry/ibmcompat/IBMCompatApiTest.java b/app/src/test/java/io/apicurio/registry/ibmcompat/IBMCompatApiTest.java index 8acc144f52..ca3a41427e 100644 --- a/app/src/test/java/io/apicurio/registry/ibmcompat/IBMCompatApiTest.java +++ b/app/src/test/java/io/apicurio/registry/ibmcompat/IBMCompatApiTest.java @@ -27,23 +27,24 @@ import org.junit.jupiter.api.Test; import java.util.List; +import java.util.Optional; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; @QuarkusTest public class IBMCompatApiTest extends AbstractResourceTestBase { @Test - public void testCreateSchema() throws Exception { + public void testCreateSchema() { // Convert the file contents to a JSON string value String schemaDefinition = resourceToString("avro.json") - .replaceAll("\\\"", "\\\\\"") - .replaceAll("\\\n", "\\\\n"); + .replaceAll("\"", "\\\\\"") + .replaceAll("\n", "\\\\n"); String schemaName = "testCreateSchema_userInfo"; String versionName = "testversion_1.0.0"; @@ -87,21 +88,35 @@ public void testGetSchemas() throws Exception { createArtifact(schemaName, ArtifactType.AVRO, artifactContent); // Get the list of artifacts via ibmcompat API - List schemas = given() - .when() - .get("/ibmcompat/schemas") - .then() - .statusCode(200) - .extract().body().as(new TypeRef>(){}); - - // Find the schema that was just added - SchemaListItem schema = schemas.stream() - .filter(item -> schemaName.equals(item.getId())) - .findFirst() - .get(); + SchemaListItem schema; + int page = 0; + while (true) { + List schemas = given() + .when() + .get("/ibmcompat/schemas?page=" + page) + .then() + .statusCode(200) + .extract().body().as(new TypeRef>() { + }); + + if (schemas.isEmpty()) { + Assertions.fail("No such schema present: " + schemaName); + } + + // Find the schema that was just added + Optional so = schemas.stream() + .filter(item -> schemaName.equals(item.getId())) + .findFirst(); + if (so.isPresent()) { + schema = so.get(); + break; + } else { + page++; + } + } Assertions.assertEquals(schemaName, schema.getName()); - Assertions.assertEquals(true, schema.isEnabled()); + Assertions.assertTrue(schema.isEnabled()); Assertions.assertEquals(SchemaState.StateEnum.ACTIVE, schema.getState().getState()); Assertions.assertEquals(1, schema.getLatest().getId()); Assertions.assertEquals("userInfo", schema.getLatest().getName()); @@ -167,8 +182,8 @@ public void testPatchSchemaState() throws Exception { String artifactContent = resourceToString("avro.json"); String version2SchemaDefinition = artifactContent - .replaceAll("\\\"", "\\\\\"") - .replaceAll("\\\n", "\\\\n"); + .replaceAll("\"", "\\\\\"") + .replaceAll("\n", "\\\\n"); String schemaName = "testPatchSchemaState_userInfo"; String version2Name = "testversion_2.0.0"; @@ -265,8 +280,8 @@ public void testCreateSchemaVersion() throws Exception { String artifactContent = resourceToString("avro.json"); String newSchemaDefinition = artifactContent - .replaceAll("\\\"", "\\\\\"") - .replaceAll("\\\n", "\\\\n"); + .replaceAll("\"", "\\\\\"") + .replaceAll("\n", "\\\\n"); String schemaName = "testCreateSchemaVersion_userInfo"; String newVersionName = "testversion_2.0.0"; @@ -301,8 +316,8 @@ public void testDeleteSchemaVersion() throws Exception { String artifactContent = resourceToString("avro.json"); String newSchemaDefinition = artifactContent - .replaceAll("\\\"", "\\\\\"") - .replaceAll("\\\n", "\\\\n"); + .replaceAll("\"", "\\\\\"") + .replaceAll("\n", "\\\\n"); String schemaName = "testDeleteSchemaVersion_userInfo"; String newVersionName = "testversion_2.0.0"; @@ -341,8 +356,8 @@ public void testPatchSchemaVersionState() throws Exception { String artifactContent = resourceToString("avro.json"); String version2SchemaDefinition = artifactContent - .replaceAll("\\\"", "\\\\\"") - .replaceAll("\\\n", "\\\\n"); + .replaceAll("\"", "\\\\\"") + .replaceAll("\n", "\\\\n"); String schemaName = "testPatchSchemaVersionState_userInfo"; String version2Name = "testversion_2.0.0"; diff --git a/pom.xml b/pom.xml index 3c48ab25c1..561b875674 100644 --- a/pom.xml +++ b/pom.xml @@ -116,7 +116,7 @@ 1.22.4 - 1.5.2.Final + 1.7.0.Final 1.0.8 diff --git a/search/client/src/main/java/io/apicurio/registry/search/client/hotrod/HotRodSearchClient.java b/search/client/src/main/java/io/apicurio/registry/search/client/hotrod/HotRodSearchClient.java index 74df604d78..f943294696 100644 --- a/search/client/src/main/java/io/apicurio/registry/search/client/hotrod/HotRodSearchClient.java +++ b/search/client/src/main/java/io/apicurio/registry/search/client/hotrod/HotRodSearchClient.java @@ -32,10 +32,9 @@ import org.infinispan.commons.marshall.ProtoStreamMarshaller; import org.infinispan.protostream.FileDescriptorSource; import org.infinispan.protostream.SerializationContext; +import org.infinispan.query.dsl.Query; import org.infinispan.query.dsl.QueryFactory; -import static io.apicurio.registry.search.client.SearchUtil.property; - import java.util.HashMap; import java.util.List; import java.util.Map; @@ -44,6 +43,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; +import static io.apicurio.registry.search.client.SearchUtil.property; + /** * @author Ales Justin */ @@ -139,7 +140,8 @@ public CompletionStage index(List artifacts) { public CompletionStage search(String query) { QueryFactory qf = org.infinispan.client.hotrod.Search.getQueryFactory(getCache()); query = query.replace("$Artifact", toFqn()); // simplify usage - List list = qf.create(query).list(); + Query q = qf.create(query); + List list = q.execute().list(); return CompletableFuture.completedFuture(new HotRodSearchResults(list)); }