Skip to content

Roadmap

fge edited this page Feb 12, 2013 · 127 revisions

Introduction

This page documents the features of upcoming versions 2.0.x.

This version fixes some shortcomings of the current stable versions while retaining all of its features. Its internal rearchitecturing, also documented in this page, will bring entirely new possibilites currently very hard to achieve with 1.x.

Shortcomings addressed

Schema addressing rework

While the current stable version does a good job in general, it is not really in line with the specification; in particular, it does not define URI scopes as per the current specification (draft v4).

Version 2.0.x removes that limitation. It still retains the ability to redefine URI scopes, preload schemas, support arbitrary schemes etc.

Separate schema syntax validation

Versions 1.x did not allow for separate schema syntax validation, this version will do. Moreover, schema syntax validation is complete and not on demand (note that the last 1.x version, 1.6.x, will also do this, but less efficiently).

Customized logging/validation behaviour

Versions 1.x never threw exceptions when validating, save for unchecked exceptions. With 2.0.x, this becomes an option, along with the ability to stop at the first validation error.

The new logging system will also allow to log messages at different levels, while 1.x really had only one level -- error.

New architecture

Here is a preview of the new core architecture of this library. For 2.0.x, these will be split into a separate package, which this library will depend upon.

Processors, processor chains and selectors

All steps of the validation process (JSON Reference resolution, syntax checking, schema digesting, keyword building, validation) are now separate processors. The existence of these processors is why 2.0.x allows separate syntax validation whereas 1.x could not.

The main interface is Processor. It has two helper classes: ProcessorChain and ProcessorSelector. The first allows to chain processors together, provided their inputs and outputs are compatible; the second one allows to "dispatch" processing to different processors according to a truth value (this truth value uses Guava's Predicate interface).

Here is a sample code showing what is possible:

final Processor<In, Out> choice1 = ProcessorChain.startWith(p1).chainWtih(p2).etc().end();
final Predicate<In> predicate1 = somePredicate();

// etc etc. And then:

final ProcessorSelector<In, Out> selector = new ProcessorSelector<In, Out>
    .when(predicate1).then(choice1)
    .when(predicate2).then(choice2)
    .etc().etc()
    .otherwise(defaultProcessor);

final Processor<In, Out> realProcessor = selector.getProcessor();

The validation itself uses such a combination of chained and selected processors, and is itself a processor. You will therefore be able to use it in your own, customized chains.

Logging

The base interface for this is ProcessingReport. It contains logging methods with familiar names like .debug(), .info(), .warn() and .error(). As it is an interface, the way to handle messages passed as arguments (which are ProcessingMessages, see below) is entirely up to implementations.

The base abstract class implementing this interface allows you to set the logging threshold and exception threshold as well, which is how you can tell the validation process to stop at the first error.

Logging messages and exceptions

The ProcessingMessage class is what processors use to report messages to a ProcessingReport, as already mentioned. One feature of processing messages is that they have a builtin exception mechanism, via the .asException() method. The base abstract implementation of a report, AbstractProcessingReport, uses that (throw message.asException();) to throw exceptions when the log level of a message is greater than, or equal to, the exception threshold.

By default, the exception thrown is a plain ProcessingException. You can change that by using .setExceptionProvider() and provide this method with an implementation of ExceptionProvider. This allows to differentiate exceptions according to which processor threw the exception.

Note however that all exceptions must be subclasses of ProcessingException.

There is also an unchecked exception class called ProcessingConfigurationError. As its name says, this class, and its subclasses, are used when configuration errors are encountered. As you cannot alter a validator once it is built (at least, not with this library), those exceptions are guaranteed never to be thrown while processing.

Future plans

The processor and logging infrastructure will eventually have their own package, upon which this library will depend. This is mainly because other processors can be written to completement the validation API. For instance:

  • conversion from other JSON libraries (Gson, org.json) to Jackson;
  • partial updates validation: given a schema and a pointer into an instance, find the appropriate subschemas; validate only against said subschemas;
  • schema generation from annotated POJOs: there is actually a project aiming at doing that (https://github.com/reinert/JJSchema); chain this before the validation chain;
  • the reverse (POJO generation from schemas): build a processor for http://code.google.com/p/jsonschema2pojo/, chain it after syntax validation.

Etc etc.

Clone this wiki locally