java-json-tools/json-schema-validator

Bug in -core: URI normalization fails with URNs/"opaque" URIs (was Validation breaks when using Jackson >= 2.4.2)

tkruse opened this issue · 12 comments

For us, tests break with weird Exception at bottom.


private static final JsonValidator VALIDATOR = JsonSchemaFactory.byDefault().getValidator();

 @Test
    public void verifySuccessfulValidation() throws ProcessingException, IOException {

        final String validStatusUpdate = "{\"@type\": \"APPLICATION_STATUS_UPDATED\", \"applicationId\": \"id\", \"projectTitle\": \"title\", \"userId\": \"id\", \"timestamp\": [2014, 5, 28, 8, 47, 30, 500]}";
        final ProcessingReport validReport = VALIDATOR.validate(incomingSchema, JsonLoader.fromString(validStatusUpdate));
    }

I notice that the schema we generate using Jackson 2.4.3 now has additional lines:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "definitions": {
        "accountRestrictionsUpdated": {
+            "id": "urn:jsonschema:com:example:AccountRestrictionsUpdated",
         ...

The new line with urn: seems a likely cause.
Not sure how to best reproduce this.

Exception:

MessageSchemaGeneratorTest > verifySuccessfulValidation FAILED
    com.google.common.util.concurrent.UncheckedExecutionException: com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalStateException: How did I get there??
        at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2203)
        at com.google.common.cache.LocalCache.get(LocalCache.java:3937)
        at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941)
        at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824)
        at com.github.fge.jsonschema.core.processing.CachingProcessor.process(CachingProcessor.java:109)
        at com.github.fge.jsonschema.processors.validation.InstanceValidator.process(InstanceValidator.java:136)
        at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:56)
        at com.github.fge.jsonschema.processors.validation.ValidationProcessor.process(ValidationProcessor.java:34)
        at com.github.fge.jsonschema.core.processing.ProcessingResult.of(ProcessingResult.java:79)
        at com.github.fge.jsonschema.main.JsonValidator.validate(JsonValidator.java:104)
        at com.github.fge.jsonschema.main.JsonValidator.validate(JsonValidator.java:124)
        at MessageSchemaGeneratorTest.verifySuccessfulValidation(MessageSchemaGeneratorTest.java:66)

        Caused by:
        com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalStateException: How did I get there??
            at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2203)
            at com.google.common.cache.LocalCache.get(LocalCache.java:3937)
            at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3941)
            at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4824)
            at com.github.fge.jsonschema.core.processing.CachingProcessor.process(CachingProcessor.java:109)
            at com.github.fge.jsonschema.processors.validation.ValidationChain.process(ValidationChain.java:107)
            at com.github.fge.jsonschema.processors.validation.ValidationChain.process(ValidationChain.java:57)
            at com.github.fge.jsonschema.core.processing.ProcessorMap$Mapper.process(ProcessorMap.java:166)
            at com.github.fge.jsonschema.core.processing.ProcessingResult.of(ProcessingResult.java:79)
            at com.github.fge.jsonschema.core.processing.CachingProcessor$1.load(CachingProcessor.java:128)
            at com.github.fge.jsonschema.core.processing.CachingProcessor$1.load(CachingProcessor.java:120)
            at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3527)
            at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2319)
            at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2282)
            at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2197)
            ... 11 more

            Caused by:
            java.lang.IllegalStateException: How did I get there??
                at com.github.fge.jsonschema.core.util.URIUtils$2.apply(URIUtils.java:113)
                at com.github.fge.jsonschema.core.util.URIUtils$2.apply(URIUtils.java:87)
                at com.github.fge.jsonschema.core.util.URIUtils.normalizeURI(URIUtils.java:238)
                at com.github.fge.jsonschema.core.ref.JsonRef.fromURI(JsonRef.java:183)
                at com.github.fge.jsonschema.core.ref.JsonRef.fromString(JsonRef.java:207)
                at com.github.fge.jsonschema.core.tree.BaseSchemaTree.idFromNode(BaseSchemaTree.java:278)
                at com.github.fge.jsonschema.core.tree.BaseSchemaTree.nextRef(BaseSchemaTree.java:303)
                at com.github.fge.jsonschema.core.tree.BaseSchemaTree.<init>(BaseSchemaTree.java:145)
                at com.github.fge.jsonschema.core.tree.CanonicalSchemaTree.<init>(CanonicalSchemaTree.java:79)
                at com.github.fge.jsonschema.core.tree.CanonicalSchemaTree.append(CanonicalSchemaTree.java:86)
                at com.github.fge.jsonschema.core.keyword.syntax.SyntaxProcessor.validate(SyntaxProcessor.java:118)
                at com.github.fge.jsonschema.core.keyword.syntax.SyntaxProcessor.rawProcess(SyntaxProcessor.java:70)
                at com.github.fge.jsonschema.core.keyword.syntax.SyntaxProcessor.rawProcess(SyntaxProcessor.java:45)
                at com.github.fge.jsonschema.core.processing.RawProcessor.process(RawProcessor.java:77)
                at com.github.fge.jsonschema.core.processing.RawProcessor.process(RawProcessor.java:41)
                at com.github.fge.jsonschema.core.processing.ProcessorChain$ProcessorMerger.process(ProcessorChain.java:190)
                at com.github.fge.jsonschema.core.processing.ProcessingResult.of(ProcessingResult.java:79)
                at com.github.fge.jsonschema.core.processing.CachingProcessor$1.load(CachingProcessor.java:128)
                at com.github.fge.jsonschema.core.processing.CachingProcessor$1.load(CachingProcessor.java:120)
                at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3527)
                at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2319)
                at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2282)
                at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2197)
                ... 25 more

                Caused by:
                java.net.URISyntaxException: Expected scheme-specific part at index 4: urn:
                    at java.net.URI$Parser.fail(URI.java:2829)
                    at java.net.URI$Parser.failExpecting(URI.java:2835)
                    at java.net.URI$Parser.parse(URI.java:3038)
                    at java.net.URI.<init>(URI.java:680)
                    at com.github.fge.jsonschema.core.util.URIUtils$2.apply(URIUtils.java:110)
                    ... 47 more
fge commented

You are indeed correct; and there are two problems here...

  • the first and most important: even the inserted id should not trigger a failure at this point; this is clearly a bug;
  • the second one: you say that it is Jackson which generates this id... Are you absolutely sure that it is Jackson which does that? Isn't that code that you use which uses Jackson, and the newer version of that code happens to use a newer version of Jackson?

So we use the Jackson ObjectMapper class to generate the schema.
Here is the code that generates the line causing the symptom:

    // creating the json schema an converting it to json tree (as instance of ObjectNode) for being able to customize
    private ObjectNode generateJsonSchemaForClass(Class<?> clazz) throws JsonMappingException {
        SchemaFactoryWrapper vis = new SchemaFactoryWrapper();
        om.acceptJsonFormatVisitor(clazz, vis);
        JsonSchema schema = vis.finalSchema();

        JsonNode res = om.valueToTree(schema); // res has element "id":"urn:..."

        return (ObjectNode) res;
    }

All classes in the code come from package com.fasterxml

Hm, missed the initialization of the ObjectMapper om:

 this.om = new ObjectMapper();
 this.om.registerModule(new SchemaGeneratorModule());


class SchemaGeneratorModule extends SimpleModule {

    private static final long serialVersionUID = 1L;

    public SchemaGeneratorModule()
    {
        super(PackageVersion.VERSION);
        // first deserializers
        addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());

        // then serializers:
        addSerializer(Partial.class, CustomJacksonSerializer.JODA_TIME_PARTIAL_SERIALIZER);
        addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
    }
}

fge commented

OK, I found the source of the bug; the normalizer method that I use seems to be broken for this particular type of URI...

Now working on fixing it...

fge commented

The source has been found: java-json-tools/json-schema-core@8d258e3

Specifically, in your case, the URI has a scheme but all other .get*() for the URI class (safe for .getSchemeSpecificPart()) are null.

So, this is really a bug in -core, which also affects -validator.

fge commented

OK, issue is fixed in -core. Since this requires a dependency update in the build file, I'll close this issue when a new -core version is available.

Great, thx. Sorry for not providing a reproduction example up front.

Any concrete plans for the next core release?

fge commented

@kschulst I need to solve issue #112 first; this one is not easy...

fge commented

Fixed with new version 2.2.6 (which is now published)

Is this fixed for draft 3 schema file as well?
I am using 2.2.6 dependency for json-schema-validator and schema is draft 3 and get identical error message:

--- BEGIN MESSAGES ---
fatal: URI scheme "urn" not supported (URI: "urn:jsonschema:com:x:y:z#")
level: "fatal"
scheme: "urn"
uri: "urn:jsonschema:com:x:y:Z:ClassName#"
info: "other messages follow (if any)"
--- END MESSAGES ---

fge commented

@njaiswal that's not the same problem at all you have here, look at what the error message says carefully...