Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/
public class JsonValidationResult {

protected static final JsonValidationResult SUCCESS = successfull();
protected static final JsonValidationResult SUCCESS = successful();

private boolean success;
private List<ValidationError> validationErrors;
Expand Down Expand Up @@ -54,7 +54,7 @@ public static JsonValidationResult fromErrors(List<ValidationError> errors) {
return new JsonValidationResult(errors);
}

public static JsonValidationResult successfull() {
public static JsonValidationResult successful() {
return new JsonValidationResult(null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import io.apicurio.registry.resolver.config.SchemaResolverConfig;
import io.apicurio.registry.resolver.data.Record;
import io.apicurio.registry.resolver.strategy.ArtifactReference;
import io.apicurio.registry.rest.client.models.ProblemDetails;
import io.apicurio.registry.types.ArtifactType;
import io.apicurio.registry.utils.IoUtil;
import org.json.JSONObject;
Expand Down Expand Up @@ -86,9 +87,15 @@ protected JsonValidator() {
*/
public JsonValidationResult validateByArtifactReference(Object bean) {
Objects.requireNonNull(this.artifactReference, "ArtifactReference must be provided when creating JsonValidator in order to use this feature");
SchemaLookupResult<JsonSchema> schema = this.schemaResolver.resolveSchemaByArtifactReference(this.artifactReference);
JsonNode jsonPayload = createJSONObject(bean);
return validate(schema.getParsedSchema().getParsedSchema(), jsonPayload);
try {
SchemaLookupResult<JsonSchema> schema = this.schemaResolver.resolveSchemaByArtifactReference(this.artifactReference);
JsonNode jsonPayload = createJSONObject(bean);
return validate(schema.getParsedSchema().getParsedSchema(), jsonPayload);
} catch (Exception e) {
return JsonValidationResult.fromErrors(List.of(
new ValidationError("Failed to resolve schema from registry: " + extractErrorMessage(e), "SCHEMA_RESOLUTION_ERROR")
));
}
}

/**
Expand All @@ -101,9 +108,15 @@ public JsonValidationResult validateByArtifactReference(Object bean) {
* @return JsonValidationResult
*/
public JsonValidationResult validate(Record<Object> record) {
SchemaLookupResult<JsonSchema> schema = this.schemaResolver.resolveSchema(record);
JsonNode jsonPayload = createJSONObject(record.payload());
return validate(schema.getParsedSchema().getParsedSchema(), jsonPayload);
try {
SchemaLookupResult<JsonSchema> schema = this.schemaResolver.resolveSchema(record);
JsonNode jsonPayload = createJSONObject(record.payload());
return validate(schema.getParsedSchema().getParsedSchema(), jsonPayload);
} catch (Exception e) {
return JsonValidationResult.fromErrors(List.of(
new ValidationError("Failed to resolve schema from registry: " + extractErrorMessage(e), "SCHEMA_RESOLUTION_ERROR")
));
}
}

protected JsonValidationResult validate(JsonSchema schema, JsonNode jsonPayload) {
Expand Down Expand Up @@ -142,6 +155,41 @@ private List<ValidationError> extractValidationErrors(Set<ValidationMessage> val
return errors;
}

private String extractErrorMessage(Exception e) {
StringBuilder errorMessage = new StringBuilder();

// Start with the exception type and message
errorMessage.append(e.getClass().getSimpleName());
String message = getDetailedMessage(e);
if (message != null && !message.isEmpty()) {
errorMessage.append(": ").append(message);
}

// Add cause chain for more context
Throwable cause = e.getCause();
while (cause != null) {
errorMessage.append(" | Caused by: ").append(cause.getClass().getSimpleName());
String causeMessage = getDetailedMessage(cause);
if (causeMessage != null && !causeMessage.isEmpty()) {
errorMessage.append(": ").append(causeMessage);
}
cause = cause.getCause();
}

return errorMessage.toString();
}

private String getDetailedMessage(Throwable throwable) {
// Special handling for ProblemDetails from Apicurio Registry REST client
if (throwable instanceof ProblemDetails) {
String detail = ((ProblemDetails) throwable).getDetail();
if (detail != null && !detail.isEmpty()) {
return detail;
}
}
return throwable.getMessage();
}

public static class JsonSchemaParser implements SchemaParser<JsonSchema, Object> {
@Override
public String artifactType() {
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
<version.maven-javadoc-plugin>3.5.0</version.maven-javadoc-plugin>
<version.maven-source-plugin>3.2.1</version.maven-source-plugin>
<version.maven-compiler-plugin>3.11.0</version.maven-compiler-plugin>
<apicurio.registry.version>3.0.7</apicurio.registry.version>
<apicurio.registry.version>3.1.2</apicurio.registry.version>
<json-schema-validator.version>1.5.1</json-schema-validator.version>
<org.json.version>20240303</org.json.version>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import io.apicurio.registry.resolver.config.SchemaResolverConfig;
import io.apicurio.registry.resolver.data.Record;
import io.apicurio.registry.resolver.strategy.ArtifactReference;
import io.apicurio.registry.rest.client.models.ProblemDetails;
import io.apicurio.registry.rules.compatibility.protobuf.ProtobufCompatibilityCheckerLibrary;
import io.apicurio.registry.utils.protobuf.schema.ProtobufFile;
import io.apicurio.registry.utils.protobuf.schema.ProtobufSchema;
Expand Down Expand Up @@ -54,9 +55,15 @@ protected ProtobufValidator() {
public ProtobufValidationResult validateByArtifactReference(Message bean) {
Objects.requireNonNull(this.artifactReference,
"ArtifactReference must be provided when creating JsonValidator in order to use this feature");
SchemaLookupResult<ProtobufSchema> schema = this.schemaResolver.resolveSchemaByArtifactReference(
this.artifactReference);
return validate(schema.getParsedSchema(), new ProtobufRecord(bean, null));
try {
SchemaLookupResult<ProtobufSchema> schema = this.schemaResolver.resolveSchemaByArtifactReference(
this.artifactReference);
return validate(schema.getParsedSchema(), new ProtobufRecord(bean, null));
} catch (Exception e) {
return ProtobufValidationResult.fromErrors(List.of(
new ValidationError("Failed to resolve schema from registry: " + extractErrorMessage(e), "SCHEMA_RESOLUTION_ERROR")
));
}
}

/**
Expand All @@ -69,8 +76,14 @@ public ProtobufValidationResult validateByArtifactReference(Message bean) {
* @return ProtobufValidationResult
*/
public ProtobufValidationResult validate(Record<Message> record) {
SchemaLookupResult<ProtobufSchema> schema = this.schemaResolver.resolveSchema(record);
return validate(schema.getParsedSchema(), record);
try {
SchemaLookupResult<ProtobufSchema> schema = this.schemaResolver.resolveSchema(record);
return validate(schema.getParsedSchema(), record);
} catch (Exception e) {
return ProtobufValidationResult.fromErrors(List.of(
new ValidationError("Failed to resolve schema from registry: " + extractErrorMessage(e), "SCHEMA_RESOLUTION_ERROR")
));
}
}

protected ProtobufValidationResult validate(ParsedSchema<ProtobufSchema> schema, Record<Message> record) {
Expand Down Expand Up @@ -100,4 +113,39 @@ private List<ProtobufDifference> validate(ParsedSchema<ProtobufSchema> schemaFro
fileAfter);
return checker.findDifferences();
}

private String extractErrorMessage(Exception e) {
StringBuilder errorMessage = new StringBuilder();

// Start with the exception type and message
errorMessage.append(e.getClass().getSimpleName());
String message = getDetailedMessage(e);
if (message != null && !message.isEmpty()) {
errorMessage.append(": ").append(message);
}

// Add cause chain for more context
Throwable cause = e.getCause();
while (cause != null) {
errorMessage.append(" | Caused by: ").append(cause.getClass().getSimpleName());
String causeMessage = getDetailedMessage(cause);
if (causeMessage != null && !causeMessage.isEmpty()) {
errorMessage.append(": ").append(causeMessage);
}
cause = cause.getCause();
}

return errorMessage.toString();
}

private String getDetailedMessage(Throwable throwable) {
// Special handling for ProblemDetails from Apicurio Registry REST client
if (throwable instanceof ProblemDetails) {
String detail = ((ProblemDetails) throwable).getDetail();
if (detail != null && !detail.isEmpty()) {
return detail;
}
}
return throwable.getMessage();
}
}