question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unable to use "$ref" with "$id" and "jar" protocol

See original GitHub issue

I am trying to refer a separate json schema file using $ref but getting Malformed url exception without adding file:// before the file name. After adding file:// , the code expects BaseJsonSchema.json in the current directory instead of data/src/main/resources

Schema File: data/src/main/resources/TwitterJsonSchema.json

{
  "description" : "Twitter data",
  "type":"object",
  "allOf":[
     { "$ref":"BaseJsonSchema.json#/definitions/baseData" },
    {
         "properties": {
             "followersCount": {"type":"number" },
          }
     }]
} 

Schema File: data/src/main/resources/BaseJsonSchema.json

{
    "title": "baseData",
   "type":"object",
   "definitions":{
     "baseData": {
          "type": "object",
          "properties": {
                  "sourceUrl": {
                        "type": "string"
                   },
          }
      }
   }
}

Code:

package com.data.commons.validator 

class JsonValidator{

    public static void main(String[] args) {
        validateJsonSchema(args[0], args[1])
    }

    static void validateJsonSchema(String jsonSchemaFile, String json) {
        JSONObject jsonObject = new JSONObject(json)
        Schema schema = SchemaLoader.builder().schemaJson(new JSONObject(new JSONTokener(this.getClass().getResourceAsStream(jsonSchemaFile)))).build().load().build()
        schema.validate(jsonObject)
    }
}

Exception:

Exception in thread "main" java.io.UncheckedIOException: java.net.MalformedURLException: no protocol: BaseJsonSchema.json
	at org.everit.json.schema.loader.internal.DefaultSchemaClient.get(DefaultSchemaClient.java:35)
	at org.everit.json.schema.loader.internal.JSONPointer.executeWith(JSONPointer.java:87)
	at org.everit.json.schema.loader.internal.JSONPointer.lambda$forURL$1(JSONPointer.java:141)
	at org.everit.json.schema.loader.internal.JSONPointer.query(JSONPointer.java:162)
	at org.everit.json.schema.loader.SchemaLoader.lookupReference(SchemaLoader.java:578)
	at org.everit.json.schema.loader.SchemaLoader.buildSchemaWithoutExplicitType(SchemaLoader.java:435)
	at org.everit.json.schema.loader.SchemaLoader.load(SchemaLoader.java:517)
	at org.everit.json.schema.loader.SchemaLoader.loadChild(SchemaLoader.java:530)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.IntPipeline$4$1.accept(IntPipeline.java:250)
	at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110)
	at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
	at org.everit.json.schema.loader.SchemaLoader.tryCombinedSchema(SchemaLoader.java:640)
	at org.everit.json.schema.loader.SchemaLoader.load(SchemaLoader.java:514)
	at org.everit.json.schema.loader.SchemaLoader$load$0.call(Unknown Source)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
	at com.tracxn.data.commons.validator.JsonValidator.validateJsonSchema(JsonValidator.groovy:19)
	at com.tracxn.data.commons.validator.JsonValidator.main(JsonValidator.groovy:11)
Caused by: java.net.MalformedURLException: no protocol: BaseJsonSchema.json
	at java.net.URL.<init>(URL.java:593)
	at java.net.URL.<init>(URL.java:490)
	at java.net.URL.<init>(URL.java:439)
	at org.everit.json.schema.loader.internal.DefaultSchemaClient.get(DefaultSchemaClient.java:33)
	... 24 more

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
ankshahcommented, Sep 20, 2018

the base is jar://data/target/data-1.0.0.jar!/TwitterJsonSchema.json , then URI.resolve() returns jar://data/target/data-1.0.0.jar!/BaseJsonSchema.json , which is correct, but you get a MalformedURLException one step later when you try to open the connection.

Okay. Will try to debug this oddity later. Thanks for the pointer.

I am not using spring. I have worked the issue out by modifying the json schema file at runtime. My base $refs are limited to one or two files, I read the definitions from these files and inject in other schemas at runtime - a bit hackish, but works for my use case.

Thanks for your time and support @erosb 👍

1reaction
erosbcommented, Sep 19, 2018

I’m not sure what version of json schema are you trying to use, but "id" works only for draft-4 schemas (which is an old version), and the keyword changed to "$id" in draft-6.

Also, the value you set "jar:file:data/target/data-1.0.0.jar!/TwitterJsonSchema.json" is not a valid URL so it definitely won’t work.

There are multiple ways to make progress on it:

  • the library just uses the URL class of the JDK so the library supports whatever protocol supported by the URL class. If necessary, you can define your own protocol handler.
  • alternatively you can use a custom SchemaClient interface and wire it into the SchemaLoader. This part will look something like this:
SchemaLoader loader = SchemaLoader.builder().schemaJson(yourSchemaJson).httpClient(new YourSchemaClient()).build();
Schema schema = loader.load().build();

Then in the YourSchemaClient you load the schema from whatever source you would like to. You will be given a String as parameter and should return the InputStream of the found json content.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Eclipse error: indirectly referenced from required .class files?
It means: "A class that you use needs another class that is not on the classpath." You should make sure (as Harry Joy...
Read more >
Amend JarURLConnection::getJarFile() to return JarFile ...
JDK-8132359 : Amend JarURLConnection::getJarFile() to return JarFile object reference for nonexistent JAR file entry URL. Type: Bug; Component: core-libs ...
Read more >
How to call to a shared flow in Mule 4 | MuleSoft Help Center
jar ' file) demonstrates a flow in the main Mule application XML re-using a flow named 'echoFlow', which is defined within the external...
Read more >
Spring Boot Gradle Plugin Reference Guide
The Spring Boot Gradle Plugin provides Spring Boot support in Gradle. It allows you to package executable jar or war archives, run Spring ......
Read more >
Apache Tomcat 9 (9.0.70) - JNDI Datasource How-To
Failure of a web application to close these resources can result in ... Tomcat will only use *.jar files installed in $CATALINA_HOME/lib ....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found