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 @@ -18,40 +18,38 @@

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;

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;
Expand All @@ -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<SpecificationVersion> getSpecificationVersion(JsonNode schemaNode) {
if (schemaNode != null) {
JsonNode schema = schemaNode.get("$schema");
if (schema != null && schema.isTextual()) {
return SpecificationVersion.fromDialectId(schema.asText());
}
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<ValidationMessage> errors) throws ValidationException {
public void handleErrors(Exchange exchange, Schema schema, Set<Error> 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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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;

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -31,34 +31,34 @@ public class JsonValidationException extends ValidationException {
@Serial
private static final long serialVersionUID = 1L;

private final JsonSchema schema;
private final Set<ValidationMessage> errors;
private final Schema schema;
private final Set<Error> errors;

public JsonValidationException(Exchange exchange, JsonSchema schema, Set<ValidationMessage> errors) {
public JsonValidationException(Exchange exchange, Schema schema, Set<Error> 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<ValidationMessage> getErrors() {
public Set<Error> getErrors() {
return errors;
}

public int getNumberOfErrors() {
return errors.size();
}

private static String toString(Set<ValidationMessage> errors) {
return errors.stream().map(ValidationMessage::toString).collect(Collectors.joining("\n"));
private static String toString(Set<Error> errors) {
return errors.stream().map(Error::toString).collect(Collectors.joining("\n"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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();
}
Expand All @@ -148,11 +149,11 @@ protected void onExchange(Exchange exchange) throws Exception {
if (node == null) {
throw new NoJsonBodyValidationException(exchange);
}
Set<ValidationMessage> errors = localSchema.validate(node);
List<Error> 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");
}
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<ValidationMessage> errors) throws ValidationException;
void handleErrors(Exchange exchange, Schema schema, Set<Error> errors) throws ValidationException;

/**
* Process a general error that happens during valdating
Expand All @@ -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;

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,13 +30,13 @@ public class JsonValidationExceptionTest {

@Test
void testErrorsInfoInMessage() {
Set<ValidationMessage> errors = new LinkedHashSet<>();
Set<Error> 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());
}

Expand All @@ -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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -282,20 +282,20 @@ public YamlDslValidationResult camel_validate_yaml_dsl(
File tempFile = File.createTempFile("camel-validate-", ".yaml");
try {
Files.writeString(tempFile.toPath(), route);
List<ValidationMessage> messages = yamlValidator.validate(tempFile);

List<YamlDslError> 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<Error> errors = yamlValidator.validate(tempFile);

List<YamlDslError> 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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -53,7 +53,7 @@ public Integer doCall() throws Exception {
YamlValidator validator = new YamlValidator();
validator.init();

Map<String, List<ValidationMessage>> reports = new LinkedHashMap<>();
Map<String, List<Error>> reports = new LinkedHashMap<>();
for (String n : files) {
if (matchFile(n)) {
var report = validator.validate(new File(n));
Expand Down Expand Up @@ -100,9 +100,9 @@ private static boolean matchFile(String name) {
return "yml".equals(ext) || "yaml".equals(ext);
}

private static int errorCounts(Map<String, List<ValidationMessage>> reports) {
private static int errorCounts(Map<String, List<Error>> reports) {
int count = 0;
for (List<ValidationMessage> list : reports.values()) {
for (List<Error> list : reports.values()) {
if (!list.isEmpty()) {
count++;
}
Expand Down
Loading
Loading