diff --git a/app/src/main/java/io/apicurio/registry/services/http/CoreRegistryExceptionMapperService.java b/app/src/main/java/io/apicurio/registry/services/http/CoreRegistryExceptionMapperService.java index 5309e8c387..e6b4b8268a 100644 --- a/app/src/main/java/io/apicurio/registry/services/http/CoreRegistryExceptionMapperService.java +++ b/app/src/main/java/io/apicurio/registry/services/http/CoreRegistryExceptionMapperService.java @@ -81,19 +81,21 @@ private ProblemDetails toProblemDetails(Throwable t, int code) { if (t instanceof RuleViolationException) { RuleViolationException rve = (RuleViolationException) t; details = new RuleViolationProblemDetails(); + ((RuleViolationProblemDetails) details).setTitle(rve.getMessage()); + ((RuleViolationProblemDetails) details).setDetail(rve.getDetailMessage()); ((RuleViolationProblemDetails) details).setCauses(toRestCauses(rve.getCauses())); } else { details = new ProblemDetails(); + details.setTitle(t.getLocalizedMessage()); + if (includeStackTrace) { + details.setDetail(getStackTrace(t)); + } else { + details.setDetail(getRootMessage(t)); + } } details.setStatus(code); - details.setTitle(t.getLocalizedMessage()); details.setName(t.getClass().getSimpleName()); - if (includeStackTrace) { - details.setDetail(getStackTrace(t)); - } else { - details.setDetail(getRootMessage(t)); - } return details; } diff --git a/schema-util/common/src/main/java/io/apicurio/registry/rules/RuleViolationException.java b/schema-util/common/src/main/java/io/apicurio/registry/rules/RuleViolationException.java index f14863d115..a8867c1f9b 100644 --- a/schema-util/common/src/main/java/io/apicurio/registry/rules/RuleViolationException.java +++ b/schema-util/common/src/main/java/io/apicurio/registry/rules/RuleViolationException.java @@ -73,8 +73,7 @@ public RuleViolationException(String message, RuleType ruleType, String ruleConf this.causes = causes; } - @Override - public String getMessage() { + public String getDetailMessage() { return super.getMessage() + causes.stream().map(rv -> rv.getDescription() + (rv.getContext() != null && !rv.getContext().isBlank() ? " at " + rv.getContext() : "")) .reduce((left, right) -> left + ", " + right).map(s -> " Causes: " + s).orElse(""); diff --git a/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/AbstractRegistryMojo.java b/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/AbstractRegistryMojo.java index d8bb5df1c9..d2aad34707 100644 --- a/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/AbstractRegistryMojo.java +++ b/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/AbstractRegistryMojo.java @@ -1,7 +1,10 @@ package io.apicurio.registry.maven; +import com.microsoft.kiota.ApiException; import io.apicurio.registry.client.auth.VertXAuthFactory; import io.apicurio.registry.rest.client.RegistryClient; +import io.apicurio.registry.rest.client.models.ProblemDetails; +import io.apicurio.registry.rest.client.models.RuleViolationProblemDetails; import io.apicurio.registry.types.ContentTypes; import io.kiota.http.vertx.VertXRequestAdapter; import io.vertx.core.Vertx; @@ -141,4 +144,37 @@ public void setUsername(String username) { public void setPassword(String password) { this.password = password; } + + protected void logAndThrow(ApiException e) throws MojoExecutionException, MojoFailureException { + if (e instanceof RuleViolationProblemDetails) { + logAndThrow((RuleViolationProblemDetails) e); + } + if (e instanceof ProblemDetails) { + logAndThrow((ProblemDetails) e); + } + } + + protected void logAndThrow(ProblemDetails e) throws MojoExecutionException { + getLog().error("---"); + getLog().error("Error registering artifact: " + e.getName()); + getLog().error(e.getTitle()); + getLog().error(e.getDetail()); + getLog().error("---"); + throw new MojoExecutionException("Error registering artifact: " + e.getName(), e); + } + + protected void logAndThrow(RuleViolationProblemDetails e) throws MojoFailureException { + getLog().error("---"); + getLog().error("Registry rule validation failure: " + e.getName()); + getLog().error(e.getTitle()); + if (e.getCauses() != null) { + e.getCauses().forEach(cause -> { + getLog().error("\t-> " + cause.getContext()); + getLog().error("\t " + cause.getDescription()); + }); + } + getLog().error("---"); + throw new MojoFailureException("Registry rule validation failure: " + e.getName(), e); + } + } diff --git a/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/RegisterRegistryMojo.java b/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/RegisterRegistryMojo.java index 26be0f744e..2f7adb54af 100644 --- a/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/RegisterRegistryMojo.java +++ b/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/RegisterRegistryMojo.java @@ -15,6 +15,7 @@ import io.apicurio.registry.rest.client.models.CreateVersion; import io.apicurio.registry.rest.client.models.IfArtifactExists; import io.apicurio.registry.rest.client.models.ProblemDetails; +import io.apicurio.registry.rest.client.models.RuleViolationProblemDetails; import io.apicurio.registry.rest.client.models.VersionContent; import io.apicurio.registry.rest.client.models.VersionMetaData; import io.apicurio.registry.types.ArtifactType; @@ -25,6 +26,7 @@ import org.apache.avro.Schema; import org.apache.commons.io.FileUtils; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; @@ -54,7 +56,7 @@ public class RegisterRegistryMojo extends AbstractRegistryMojo { /** * The list of pre-registered artifacts that can be used as references. */ - @Parameter(required = true) + @Parameter(required = false) List existingReferences; /** @@ -69,6 +71,13 @@ public class RegisterRegistryMojo extends AbstractRegistryMojo { @Parameter(property = "skipRegister", defaultValue = "false") boolean skip; + /** + * Set this to 'true' to perform the action with the "dryRun" option enabled. This will effectively test + * whether registration *would have worked*. But it results in no changes made on the server. + */ + @Parameter(property = "dryRun", defaultValue = "false") + boolean dryRun; + DefaultArtifactTypeUtilProviderImpl utilProviderFactory = new DefaultArtifactTypeUtilProviderImpl(); /** @@ -85,6 +94,10 @@ protected boolean validate() throws MojoExecutionException { return false; } + if (existingReferences == null) { + existingReferences = new ArrayList<>(); + } + int idx = 0; int errorCount = 0; for (RegisterArtifact artifact : artifacts) { @@ -182,8 +195,8 @@ protected void executeInternal() throws MojoExecutionException { } private VersionMetaData registerWithAutoRefs(RegistryClient registryClient, RegisterArtifact artifact, - ReferenceIndex index, Stack registrationStack) - throws IOException, ExecutionException, InterruptedException { + ReferenceIndex index, Stack registrationStack) throws IOException, + ExecutionException, InterruptedException, MojoExecutionException, MojoFailureException { if (loopDetected(artifact, registrationStack)) { throw new RuntimeException( "Artifact reference loop detected (not supported): " + printLoop(registrationStack)); @@ -203,7 +216,8 @@ private VersionMetaData registerWithAutoRefs(RegistryClient registryClient, Regi .findExternalReferences(typedArtifactContent); // Register all of the references first, then register the artifact. - List registeredReferences = externalReferences.stream().map(externalRef -> { + List registeredReferences = new ArrayList<>(externalReferences.size()); + for (ExternalReference externalRef : externalReferences) { IndexedResource iresource = index.lookup(externalRef.getResource(), Paths.get(artifact.getFile().toURI())); @@ -236,16 +250,17 @@ private VersionMetaData registerWithAutoRefs(RegistryClient registryClient, Regi reference.setVersion(iresource.getRegistration().getVersion()); reference.setGroupId(iresource.getRegistration().getGroupId()); reference.setArtifactId(iresource.getRegistration().getArtifactId()); - - return reference; - }).sorted((ref1, ref2) -> ref1.getName().compareTo(ref2.getName())).collect(Collectors.toList()); + registeredReferences.add(reference); + } + registeredReferences.sort((ref1, ref2) -> ref1.getName().compareTo(ref2.getName())); registrationStack.pop(); return registerArtifact(registryClient, artifact, registeredReferences); } private void registerDirectory(RegistryClient registryClient, RegisterArtifact artifact) - throws IOException, ExecutionException, InterruptedException { + throws IOException, ExecutionException, InterruptedException, MojoExecutionException, + MojoFailureException { switch (artifact.getArtifactType()) { case ArtifactType.AVRO: final AvroDirectoryParser avroDirectoryParser = new AvroDirectoryParser(registryClient); @@ -277,8 +292,8 @@ private void registerDirectory(RegistryClient registryClient, RegisterArtifact a } private VersionMetaData registerArtifact(RegistryClient registryClient, RegisterArtifact artifact, - List references) - throws FileNotFoundException, ExecutionException, InterruptedException { + List references) throws FileNotFoundException, ExecutionException, + InterruptedException, MojoExecutionException, MojoFailureException { if (artifact.getFile() != null) { return registerArtifact(registryClient, artifact, new FileInputStream(artifact.getFile()), references); @@ -303,7 +318,7 @@ private VersionMetaData getArtifactVersionMetadata(RegistryClient registryClient private VersionMetaData registerArtifact(RegistryClient registryClient, RegisterArtifact artifact, InputStream artifactContent, List references) - throws ExecutionException, InterruptedException { + throws ExecutionException, InterruptedException, MojoFailureException, MojoExecutionException { String groupId = artifact.getGroupId(); String artifactId = artifact.getArtifactId(); String version = artifact.getVersion(); @@ -350,6 +365,9 @@ private VersionMetaData registerArtifact(RegistryClient registryClient, Register if (artifact.getIfExists() != null) { config.queryParameters.ifExists = IfArtifactExists .forValue(artifact.getIfExists().value()); + if (dryRun) { + config.queryParameters.dryRun = true; + } } config.queryParameters.canonical = canonicalize; }); @@ -358,8 +376,9 @@ private VersionMetaData registerArtifact(RegistryClient registryClient, Register groupId, artifactId, vmd.getVersion().getGlobalId())); return vmd.getVersion(); - } catch (ProblemDetails e) { - throw new RuntimeException(e.getDetail()); + } catch (RuleViolationProblemDetails | ProblemDetails e) { + logAndThrow(e); + return null; } } @@ -368,8 +387,8 @@ private static boolean hasReferences(RegisterArtifact artifact) { } private List processArtifactReferences(RegistryClient registryClient, - List referencedArtifacts) - throws FileNotFoundException, ExecutionException, InterruptedException { + List referencedArtifacts) throws FileNotFoundException, + ExecutionException, InterruptedException, MojoExecutionException, MojoFailureException { List references = new ArrayList<>(); for (RegisterArtifactReference artifact : referencedArtifacts) { List nestedReferences = new ArrayList<>(); @@ -434,7 +453,6 @@ private void addExistingReferencesToIndex(RegistryClient registryClient, Referen } index.index(ref.getResourceName(), vmd); } - ; } } diff --git a/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/TestUpdateRegistryMojo.java b/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/TestUpdateRegistryMojo.java index 986bc6db8f..870a9095a1 100644 --- a/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/TestUpdateRegistryMojo.java +++ b/utils/maven-plugin/src/main/java/io/apicurio/registry/maven/TestUpdateRegistryMojo.java @@ -15,8 +15,11 @@ /** * Test artifact against current artifact rules, if an update is possible / valid. + * + * @deprecated In favor of using the "dryRun" option of the "register" mojo. */ @Mojo(name = "test-update") +@Deprecated public class TestUpdateRegistryMojo extends AbstractRegistryMojo { /**