From f5be4e4a201273809ea332c930a07acdee33cd44 Mon Sep 17 00:00:00 2001 From: James Netherton Date: Tue, 7 Apr 2026 09:54:11 +0100 Subject: [PATCH] CAMEL-23292: Upgrade json-schema-validator to 2.0.1 --- .../DefaultJsonUriSchemaLoader.java | 47 ++++++++++------- .../DefaultJsonValidationErrorHandler.java | 8 +-- .../jsonvalidator/JsonUriSchemaLoader.java | 4 +- .../JsonValidationException.java | 20 +++---- .../jsonvalidator/JsonValidatorEndpoint.java | 17 +++--- .../JsonValidatorErrorHandler.java | 8 +-- .../JsonValidationExceptionTest.java | 13 ++--- .../pages/camel-4x-upgrade-guide-4_19.adoc | 6 +++ .../core/commands/mcp/TransformTools.java | 24 ++++----- .../validate/YamlValidateCommand.java | 8 +-- .../dsl/yaml/validator/ValidateMojo.java | 12 ++--- .../dsl/yaml/validator/CamelYamlParser.java | 13 +++-- .../camel/dsl/yaml/validator/YamlParser.java | 13 +++-- .../dsl/yaml/validator/YamlValidator.java | 52 ++++++++++++------- .../dsl/yaml/support/YamlTestSupport.groovy | 17 +++--- parent/pom.xml | 2 +- 16 files changed, 149 insertions(+), 115 deletions(-) diff --git a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/DefaultJsonUriSchemaLoader.java b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/DefaultJsonUriSchemaLoader.java index 3a5ea02e8dad3..18c4242fd1d23 100644 --- a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/DefaultJsonUriSchemaLoader.java +++ b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/DefaultJsonUriSchemaLoader.java @@ -18,15 +18,15 @@ import java.io.*; import java.net.*; +import java.util.Optional; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.networknt.schema.JsonSchema; -import com.networknt.schema.JsonSchemaException; -import com.networknt.schema.JsonSchemaFactory; -import com.networknt.schema.SchemaValidatorsConfig; -import com.networknt.schema.SpecVersion; -import com.networknt.schema.SpecVersionDetector; +import com.networknt.schema.Schema; +import com.networknt.schema.SchemaLocation; +import com.networknt.schema.SchemaRegistry; +import com.networknt.schema.SchemaRegistryConfig; +import com.networknt.schema.SpecificationVersion; import org.apache.camel.CamelContext; import org.apache.camel.support.ResourceHelper; @@ -34,24 +34,22 @@ public class DefaultJsonUriSchemaLoader implements JsonUriSchemaLoader { protected ObjectMapper mapper = new ObjectMapper(); - protected SchemaValidatorsConfig config = new SchemaValidatorsConfig(); + protected SchemaRegistryConfig config = SchemaRegistryConfig.builder().build(); - protected SpecVersion.VersionFlag defaultVersion = SpecVersion.VersionFlag.V201909; + protected SpecificationVersion defaultVersion = SpecificationVersion.DRAFT_2019_09; @Override - public JsonSchema createSchema(CamelContext camelContext, String schemaUri) throws Exception { - // determine schema version + public Schema createSchema(CamelContext camelContext, String schemaUri) throws Exception { + // Load the schema content InputStream stream = ResourceHelper.resolveMandatoryResourceAsInputStream(camelContext, schemaUri); JsonNode node = mapper.readTree(stream); - SpecVersion.VersionFlag version; - try { - version = SpecVersionDetector.detect(node); - } catch (JsonSchemaException e) { - // default if no schema version was specified - version = defaultVersion; - } - JsonSchemaFactory factory = JsonSchemaFactory.getInstance(version); + // Determine schema version from $schema property or use the default + SpecificationVersion version = getSpecificationVersion(node).orElse(defaultVersion); + + // Create schema registry with the detected version + SchemaRegistry schemaRegistry = SchemaRegistry.withDefaultDialect(version, + builder -> builder.schemaRegistryConfig(config)); // the URI based method will correctly resolve relative schema references to other schema in the same directory URI uri; @@ -60,7 +58,18 @@ public JsonSchema createSchema(CamelContext camelContext, String schemaUri) thro } else { uri = URI.create("classpath:" + schemaUri); } - return factory.getSchema(uri, node, config); + + SchemaLocation schemaLocation = SchemaLocation.of(uri.toString()); + return schemaRegistry.getSchema(schemaLocation, node); } + static Optional getSpecificationVersion(JsonNode schemaNode) { + if (schemaNode != null) { + JsonNode schema = schemaNode.get("$schema"); + if (schema != null && schema.isTextual()) { + return SpecificationVersion.fromDialectId(schema.asText()); + } + } + return Optional.empty(); + } } diff --git a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/DefaultJsonValidationErrorHandler.java b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/DefaultJsonValidationErrorHandler.java index 51d977a0bfe68..f96da6307b7bc 100644 --- a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/DefaultJsonValidationErrorHandler.java +++ b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/DefaultJsonValidationErrorHandler.java @@ -18,20 +18,20 @@ import java.util.Set; -import com.networknt.schema.JsonSchema; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; +import com.networknt.schema.Schema; import org.apache.camel.Exchange; import org.apache.camel.ValidationException; public class DefaultJsonValidationErrorHandler implements JsonValidatorErrorHandler { @Override - public void handleErrors(Exchange exchange, JsonSchema schema, Set errors) throws ValidationException { + public void handleErrors(Exchange exchange, Schema schema, Set errors) throws ValidationException { throw new JsonValidationException(exchange, schema, errors); } @Override - public void handleErrors(Exchange exchange, JsonSchema schema, Exception e) throws ValidationException { + public void handleErrors(Exchange exchange, Schema schema, Exception e) throws ValidationException { throw new JsonValidationException(exchange, schema, e); } diff --git a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonUriSchemaLoader.java b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonUriSchemaLoader.java index 3aeab7e028aa8..62db61e970f9d 100644 --- a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonUriSchemaLoader.java +++ b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonUriSchemaLoader.java @@ -16,7 +16,7 @@ */ package org.apache.camel.component.jsonvalidator; -import com.networknt.schema.JsonSchema; +import com.networknt.schema.Schema; import org.apache.camel.CamelContext; /** @@ -31,6 +31,6 @@ public interface JsonUriSchemaLoader { * @param schemaUri the schema URI * @return a Schema to be used when validating incoming requests */ - JsonSchema createSchema(CamelContext camelContext, String schemaUri) throws Exception; + Schema createSchema(CamelContext camelContext, String schemaUri) throws Exception; } diff --git a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidationException.java b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidationException.java index 78a77268dc9fe..c83f1ee02fbdb 100644 --- a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidationException.java +++ b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidationException.java @@ -21,8 +21,8 @@ import java.util.Set; import java.util.stream.Collectors; -import com.networknt.schema.JsonSchema; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; +import com.networknt.schema.Schema; import org.apache.camel.Exchange; import org.apache.camel.ValidationException; @@ -31,26 +31,26 @@ public class JsonValidationException extends ValidationException { @Serial private static final long serialVersionUID = 1L; - private final JsonSchema schema; - private final Set errors; + private final Schema schema; + private final Set errors; - public JsonValidationException(Exchange exchange, JsonSchema schema, Set errors) { + public JsonValidationException(Exchange exchange, Schema schema, Set errors) { super(exchange, "JSON validation error with " + errors.size() + " errors:\n" + toString(errors)); this.schema = schema; this.errors = errors; } - public JsonValidationException(Exchange exchange, JsonSchema schema, Exception e) { + public JsonValidationException(Exchange exchange, Schema schema, Exception e) { super(e.getMessage(), exchange, e); this.schema = schema; this.errors = Collections.emptySet(); } - public JsonSchema getSchema() { + public Schema getSchema() { return schema; } - public Set getErrors() { + public Set getErrors() { return errors; } @@ -58,7 +58,7 @@ public int getNumberOfErrors() { return errors.size(); } - private static String toString(Set errors) { - return errors.stream().map(ValidationMessage::toString).collect(Collectors.joining("\n")); + private static String toString(Set errors) { + return errors.stream().map(Error::toString).collect(Collectors.joining("\n")); } } diff --git a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java index 9c921cedefbda..44713220763d3 100644 --- a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java +++ b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorEndpoint.java @@ -17,13 +17,14 @@ package org.apache.camel.component.jsonvalidator; import java.io.InputStream; -import java.util.Set; +import java.util.HashSet; +import java.util.List; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.networknt.schema.JsonSchema; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; +import com.networknt.schema.Schema; import org.apache.camel.Category; import org.apache.camel.Component; import org.apache.camel.Exchange; @@ -44,7 +45,7 @@ remote = false, producerOnly = true, category = { Category.VALIDATION }) public class JsonValidatorEndpoint extends ResourceEndpoint { - private volatile JsonSchema schema; + private volatile Schema schema; @UriParam(defaultValue = "true") private boolean failOnNullBody = true; @@ -123,7 +124,7 @@ protected void onExchange(Exchange exchange) throws Exception { } // Get a local copy of the current schema to improve concurrency. - JsonSchema localSchema = this.schema; + Schema localSchema = this.schema; if (localSchema == null) { localSchema = getOrCreateSchema(); } @@ -148,11 +149,11 @@ protected void onExchange(Exchange exchange) throws Exception { if (node == null) { throw new NoJsonBodyValidationException(exchange); } - Set errors = localSchema.validate(node); + List errors = localSchema.validate(node); if (!errors.isEmpty()) { this.log.debug("Validated JSON has {} errors", errors.size()); - this.errorHandler.handleErrors(exchange, schema, errors); + this.errorHandler.handleErrors(exchange, schema, new HashSet<>(errors)); } else { this.log.debug("Validated JSON success"); } @@ -187,7 +188,7 @@ private boolean shouldUseHeader() { * * @return The currently loaded schema */ - private JsonSchema getOrCreateSchema() throws Exception { + private Schema getOrCreateSchema() throws Exception { getInternalLock().lock(); try { if (this.schema == null) { diff --git a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorErrorHandler.java b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorErrorHandler.java index d391c143aa535..dba59f966848c 100644 --- a/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorErrorHandler.java +++ b/components/camel-json-validator/src/main/java/org/apache/camel/component/jsonvalidator/JsonValidatorErrorHandler.java @@ -18,8 +18,8 @@ import java.util.Set; -import com.networknt.schema.JsonSchema; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; +import com.networknt.schema.Schema; import org.apache.camel.Exchange; import org.apache.camel.ValidationException; @@ -33,7 +33,7 @@ public interface JsonValidatorErrorHandler { * @param errors the validation errors * @throws ValidationException is thrown in case of validation errors */ - void handleErrors(Exchange exchange, JsonSchema schema, Set errors) throws ValidationException; + void handleErrors(Exchange exchange, Schema schema, Set errors) throws ValidationException; /** * Process a general error that happens during valdating @@ -43,6 +43,6 @@ public interface JsonValidatorErrorHandler { * @param e general error * @throws ValidationException is thrown in case of validation errors */ - void handleErrors(Exchange exchange, JsonSchema schema, Exception e) throws ValidationException; + void handleErrors(Exchange exchange, Schema schema, Exception e) throws ValidationException; } diff --git a/components/camel-json-validator/src/test/java/org/apache/camel/component/jsonvalidator/JsonValidationExceptionTest.java b/components/camel-json-validator/src/test/java/org/apache/camel/component/jsonvalidator/JsonValidationExceptionTest.java index a4020631bd828..75bae1cb37dcc 100644 --- a/components/camel-json-validator/src/test/java/org/apache/camel/component/jsonvalidator/JsonValidationExceptionTest.java +++ b/components/camel-json-validator/src/test/java/org/apache/camel/component/jsonvalidator/JsonValidationExceptionTest.java @@ -20,7 +20,7 @@ import java.util.LinkedHashSet; import java.util.Set; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -30,13 +30,13 @@ public class JsonValidationExceptionTest { @Test void testErrorsInfoInMessage() { - Set errors = new LinkedHashSet<>(); + Set errors = new LinkedHashSet<>(); errors.add(createError("name: is missing but it is required")); errors.add(createError("id: string found, integer expected")); final JsonValidationException jsonValidationException = new JsonValidationException(null, null, errors); assertEquals( - "JSON validation error with 2 errors:\nname: is missing but it is required\nid: string found, integer expected", + "JSON validation error with 2 errors:\n: name: is missing but it is required\n: id: string found, integer expected", jsonValidationException.getMessage()); } @@ -45,9 +45,10 @@ void testErrorsEmpty() { assertEquals(0, new JsonValidationException(null, null, new Exception()).getNumberOfErrors()); } - private ValidationMessage createError(String msg) { - return new ValidationMessage.Builder() + private Error createError(String msg) { + return Error.builder() .messageKey(String.valueOf(errorId++)) - .format(new MessageFormat(msg)).build(); + .format(new MessageFormat(msg)) + .build(); } } diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc index 6b38eb74b9b4b..3541ddc876853 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_19.adoc @@ -587,6 +587,12 @@ Five new configuration properties have been added to the SSH endpoint to expose All properties default to `0`, which means the Apache MINA SSHD defaults are used. This is an additive change with no impact on existing configurations. +=== camel-json-validator + +The JSON validation library `com.networknt:json-schema-validator` used by `camel-json-validator` has been upgraded from 1.x to 2.x. + +The `json-schema-validator` https://github.com/networknt/json-schema-validator/blob/master/doc/migration-2.0.0.md[migration guide] can help to migrate your applications if you refer to types that have been updated or removed in 2.x. + === MDC older logic (Deprecation) The older logic used for MDC (enabled via `camel.main.useMdcLogging = true`) is deprecated in favor of `camel-mdc` component. diff --git a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TransformTools.java b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TransformTools.java index ed9d857075bdd..9f638f385b2ba 100644 --- a/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TransformTools.java +++ b/dsl/camel-jbang/camel-jbang-mcp/src/main/java/org/apache/camel/dsl/jbang/core/commands/mcp/TransformTools.java @@ -29,7 +29,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; import io.quarkiverse.mcp.server.Tool; import io.quarkiverse.mcp.server.ToolArg; import io.quarkiverse.mcp.server.ToolCallException; @@ -282,20 +282,20 @@ public YamlDslValidationResult camel_validate_yaml_dsl( File tempFile = File.createTempFile("camel-validate-", ".yaml"); try { Files.writeString(tempFile.toPath(), route); - List messages = yamlValidator.validate(tempFile); - - List errors = null; - if (!messages.isEmpty()) { - errors = messages.stream() - .map(m -> new YamlDslError( - m.getMessage(), - m.getInstanceLocation() != null ? m.getInstanceLocation().toString() : null, - m.getType(), - m.getSchemaLocation() != null ? m.getSchemaLocation().toString() : null)) + List errors = yamlValidator.validate(tempFile); + + List errorDetails = null; + if (!errors.isEmpty()) { + errorDetails = errors.stream() + .map(e -> new YamlDslError( + e.getMessage(), + e.getInstanceLocation() != null ? e.getInstanceLocation().toString() : null, + e.getMessageKey(), + e.getSchemaLocation() != null ? e.getSchemaLocation().toString() : null)) .toList(); } - return new YamlDslValidationResult(messages.isEmpty(), messages.size(), errors); + return new YamlDslValidationResult(errors.isEmpty(), errors.size(), errorDetails); } finally { tempFile.delete(); } diff --git a/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlValidateCommand.java b/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlValidateCommand.java index 84436f06e96d0..3d72ed72876ce 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlValidateCommand.java +++ b/dsl/camel-jbang/camel-jbang-plugin-validate/src/main/java/org/apache/camel/dsl/jbang/core/commands/validate/YamlValidateCommand.java @@ -25,7 +25,7 @@ import java.util.Map; import java.util.Stack; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; import org.apache.camel.dsl.jbang.core.commands.CamelCommand; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; import org.apache.camel.dsl.yaml.validator.YamlValidator; @@ -53,7 +53,7 @@ public Integer doCall() throws Exception { YamlValidator validator = new YamlValidator(); validator.init(); - Map> reports = new LinkedHashMap<>(); + Map> reports = new LinkedHashMap<>(); for (String n : files) { if (matchFile(n)) { var report = validator.validate(new File(n)); @@ -100,9 +100,9 @@ private static boolean matchFile(String name) { return "yml".equals(ext) || "yaml".equals(ext); } - private static int errorCounts(Map> reports) { + private static int errorCounts(Map> reports) { int count = 0; - for (List list : reports.values()) { + for (List list : reports.values()) { if (!list.isEmpty()) { count++; } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator-maven-plugin/src/main/java/org/apache/camel/dsl/yaml/validator/ValidateMojo.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator-maven-plugin/src/main/java/org/apache/camel/dsl/yaml/validator/ValidateMojo.java index 56da16719c1ef..a8dc751afba76 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator-maven-plugin/src/main/java/org/apache/camel/dsl/yaml/validator/ValidateMojo.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator-maven-plugin/src/main/java/org/apache/camel/dsl/yaml/validator/ValidateMojo.java @@ -27,7 +27,7 @@ import javax.inject.Inject; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; import org.apache.camel.support.PatternHelper; import org.apache.camel.util.FileUtil; import org.apache.maven.execution.MavenSession; @@ -124,7 +124,7 @@ public void execute() throws MojoExecutionException { findYamlRouters(yamlFiles, includeTest, ext, project); getLog().debug("Found " + yamlFiles.size() + " YAML files ..."); - Map> reports = new LinkedHashMap<>(); + Map> reports = new LinkedHashMap<>(); List matched = new ArrayList<>(); for (File file : yamlFiles) { if (matchFile(file)) { @@ -147,7 +147,7 @@ public void execute() throws MojoExecutionException { validateResults(reports); } - private void validateResults(Map> reports) throws MojoExecutionException { + private void validateResults(Map> reports) throws MojoExecutionException { int count = errorCounts(reports); if (count == 0) { getLog().info("Validation success (files:" + reports.size() + ")"); @@ -174,9 +174,9 @@ private void validateResults(Map> reports) throws } } - private int errorCounts(Map> reports) { + private int errorCounts(Map> reports) { int count = 0; - for (List list : reports.values()) { + for (List list : reports.values()) { if (!list.isEmpty()) { count++; } @@ -184,7 +184,7 @@ private int errorCounts(Map> reports) { return count; } - private List validateYamlRoute(File file) throws Exception { + private List validateYamlRoute(File file) throws Exception { getLog().debug("Validating YAML DSL in file: " + file); return validator.validate(file); } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java index bf2975578880f..6a3d2a244b9ae 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/CamelYamlParser.java @@ -18,10 +18,11 @@ import java.io.File; import java.nio.file.Files; +import java.text.MessageFormat; import java.util.Collections; import java.util.List; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; import org.apache.camel.CamelContext; import org.apache.camel.TypeConverterExists; import org.apache.camel.component.properties.PropertiesComponent; @@ -49,7 +50,7 @@ */ public class CamelYamlParser { - public List parse(File file) throws Exception { + public List parse(File file) throws Exception { DefaultRegistry registry = new DefaultRegistry(); registry.addBeanRepository(new StubBeanRepository("*")); @@ -96,9 +97,11 @@ public List parse(File file) throws Exception { return Collections.emptyList(); } } catch (Exception e) { - ValidationMessage vm = ValidationMessage.builder().type("parser") - .messageSupplier(() -> e.getClass().getName() + ": " + e.getMessage()).build(); - return List.of(vm); + Error error = Error.builder() + .messageKey("parser") + .format(new MessageFormat(e.getClass().getName() + ": " + e.getMessage())) + .build(); + return List.of(error); } } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlParser.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlParser.java index ccf1ca30ec2a3..16142ce61b627 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlParser.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlParser.java @@ -17,12 +17,13 @@ package org.apache.camel.dsl.yaml.validator; import java.io.File; +import java.text.MessageFormat; import java.util.Collections; import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; /** * YAML DSL parser that tooling can use to parse Camel source files to check if they can be YAML parsed. @@ -34,14 +35,16 @@ public class YamlParser { private final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - public List parse(File file) throws Exception { + public List parse(File file) throws Exception { try { mapper.readTree(file); return Collections.emptyList(); } catch (Exception e) { - ValidationMessage vm = ValidationMessage.builder().type("parser") - .messageSupplier(() -> e.getClass().getName() + ": " + e.getMessage()).build(); - return List.of(vm); + Error error = Error.builder() + .messageKey("parser") + .format(new MessageFormat(e.getClass().getName() + ": " + e.getMessage())) + .build(); + return List.of(error); } } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java index 39b3d7a13e336..72922f3f16b38 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl-validator/src/main/java/org/apache/camel/dsl/yaml/validator/YamlValidator.java @@ -17,19 +17,21 @@ package org.apache.camel.dsl.yaml.validator; import java.io.File; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; +import java.util.Optional; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import com.networknt.schema.JsonMetaSchema; -import com.networknt.schema.JsonSchema; -import com.networknt.schema.JsonSchemaFactory; -import com.networknt.schema.NonValidationKeyword; -import com.networknt.schema.SchemaValidatorsConfig; -import com.networknt.schema.SpecVersionDetector; -import com.networknt.schema.ValidationMessage; +import com.networknt.schema.Error; +import com.networknt.schema.Schema; +import com.networknt.schema.SchemaLocation; +import com.networknt.schema.SchemaRegistry; +import com.networknt.schema.SchemaRegistryConfig; +import com.networknt.schema.SpecificationVersion; /** * YAML DSL validator that tooling can use to validate Camel source files if they can be parsed and are valid according @@ -37,13 +39,12 @@ */ public class YamlValidator { - private static final String DRAFT = "http://json-schema.org/draft-04/schema#"; private static final String LOCATION = "/schema/camelYamlDsl.json"; private final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - private JsonSchema schema; + private Schema schema; - public List validate(File file) throws Exception { + public List validate(File file) throws Exception { if (schema == null) { init(); } @@ -51,20 +52,33 @@ public List validate(File file) throws Exception { var target = mapper.readTree(file); return new ArrayList<>(schema.validate(target)); } catch (Exception e) { - ValidationMessage vm = ValidationMessage.builder().type("parser") - .messageSupplier(() -> e.getClass().getName() + ": " + e.getMessage()).build(); - return List.of(vm); + Error error = Error.builder() + .messageKey("parser") + .format(new MessageFormat(e.getClass().getName() + ": " + e.getMessage())) + .build(); + return List.of(error); } } public void init() throws Exception { var model = mapper.readTree(YamlValidator.class.getResourceAsStream(LOCATION)); - var factory = JsonSchemaFactory.getInstance(SpecVersionDetector.detect(model)); - var config = SchemaValidatorsConfig.builder().locale(Locale.ENGLISH).build(); - // include deprecated as an unknown keyword so the validator does not WARN log about this - JsonMetaSchema jms = factory.getMetaSchema(DRAFT, null); - jms.getKeywords().put("deprecated", new NonValidationKeyword("deprecated")); - schema = factory.getSchema(model, config); + var version = getSpecificationVersion(model).orElse(SpecificationVersion.DRAFT_4); + var config = SchemaRegistryConfig.builder().locale(Locale.ENGLISH).build(); + + var schemaRegistry = SchemaRegistry.withDefaultDialect(version, + builder -> builder.schemaRegistryConfig(config)); + + // Use a proper URI for the schema location to ensure $ref resolution works + var schemaLocation = SchemaLocation.of(LOCATION); + schema = schemaRegistry.getSchema(schemaLocation, model); + } + + private static Optional getSpecificationVersion(JsonNode schemaNode) { + var schemaField = schemaNode.get("$schema"); + if (schemaField != null && schemaField.isTextual()) { + return SpecificationVersion.fromDialectId(schemaField.asText()); + } + return Optional.empty(); } } diff --git a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy index b5753649c37fd..3fde4697ce057 100644 --- a/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy +++ b/dsl/camel-yaml-dsl/camel-yaml-dsl/src/test/groovy/org/apache/camel/dsl/yaml/support/YamlTestSupport.groovy @@ -18,9 +18,10 @@ package org.apache.camel.dsl.yaml.support import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.dataformat.yaml.YAMLFactory -import com.networknt.schema.JsonSchemaFactory -import com.networknt.schema.SchemaValidatorsConfig -import com.networknt.schema.SpecVersionDetector +import com.networknt.schema.SchemaLocation +import com.networknt.schema.SchemaRegistry +import com.networknt.schema.SchemaRegistryConfig +import com.networknt.schema.SpecificationVersion import groovy.util.logging.Slf4j import org.apache.camel.CamelContext import org.apache.camel.FluentProducerTemplate @@ -42,13 +43,9 @@ import java.nio.charset.StandardCharsets class YamlTestSupport extends Specification implements HasCamelContext { static def MAPPER = new ObjectMapper(new YAMLFactory()) static def SCHEMA_NODE = MAPPER.readTree(ResourceHelper.getResourceAsStream('/schema/camelYamlDsl.json')) - static def FACTORY = JsonSchemaFactory.getInstance(SpecVersionDetector.detect(SCHEMA_NODE)) - static def SCHEMA_VALIDATORS_CONFIG = { - SchemaValidatorsConfig config = new SchemaValidatorsConfig() - config.setLocale(Locale.ENGLISH) - return config - }() - static def SCHEMA = FACTORY.getSchema(SCHEMA_NODE, SCHEMA_VALIDATORS_CONFIG) + static def SCHEMA_REGISTRY_CONFIG = SchemaRegistryConfig.builder().locale(Locale.ENGLISH).build() + static def SCHEMA_REGISTRY = SchemaRegistry.withDefaultDialect(SpecificationVersion.DRAFT_4, builder -> builder.schemaRegistryConfig(SCHEMA_REGISTRY_CONFIG)) + static def SCHEMA = SCHEMA_REGISTRY.getSchema(SchemaLocation.of('/schema/camelYamlDsl.json'), SCHEMA_NODE) @AutoCleanup def context = new DefaultCamelContext() diff --git a/parent/pom.xml b/parent/pom.xml index 224f67d3117ce..bdfe6e595ae56 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -435,7 +435,7 @@ 6.0.4 4.2.12.Final 2.0.5 - 1.5.9 + 2.0.1 10.9 2.0.13 5.0.0