A Gradle plugin for generating JSON schemas from code using the Creel JSON Schema Generator.
See CreekService.org for info on Creek Service.
-## Supported Gradle versions
Gradle Version | Tested version | Notes |
---|---|---|
< 6.4 | Not compatible due to API changes in Gradle | |
6.4.+ | 6.4 | Supported & tested |
6.4+ | 6.9.4 | Supported & tested |
7.+ | 7.6.1 | Supported & tested |
8.+ | 8.8 | Supported & tested |
> 8.8 | Not currently tested. Should work... |
// Todo: update Gradle matrix
The plugin is available on the Gradle Plugin Portal. See the portal for instructions on how to add the plugin to your build.
The JSON Schema plugin adds the following tasks to your project:
generateJsonSchema - GenerateJsonSchema
Details of how to annotate classes to control their schema can be found in the Creek JSON Schema Generator docs.
Restricting class & module path scanning by setting allowed modules and allowed packages can increase the speed of your build.
Dependencies: compileJava
, compileKotlin
, compileGroovy
if they exist.
Dependants: processResources
The generateJsonSchema
task searches the class and module path for with @GeneratesSchema
and write out
JSON schemas for them in YAML. The generated schema output directory is added to the main
source set,
as an additional resource directories, meaning the schema will be included in any generated jar.
Types can be annotated both with Jackson and JsonSchema annotations, allowing control of the generated schema.
See the Creel JSON Schema Generator Docs for more information and examples.
Aside from the customisations possible using the creek.schema.json
extension, the task accepts the
following command line options:
--type-scanning-allowed-module
: (default: any module) restricts the classes to search to only those belonging to the specified module(s). Allowed module names can include the glob wildcard {@code *} character.--type-scanning-allowed-package
: (default: any package) restricts the classes to search to only those under the specified package(s). Allowed package names can include the glob wildcard {@code *} character.--subtype-scanning-allowed-module
: (default: any module) restricts the search for subtypes to only those belonging to the specified module(s). Allowed module names can include the glob wildcard {@code *} character.--subtype-scanning-allowed-package
: (default: any package) restrict the search for subtypes to only those under the specified package(s). Allowed package names can include the glob wildcard {@code *} character.
For example, the following limits the class & module path scanning to only two modules:
> ./gradlew generateJsonSchema \
--type-scanning-allowed-module=acme.finance.momdel \
--type-scanning-allowed-module=acme.sales.model
generateTestJsonSchema - GenerateJsonSchema
Details of how to annotate classes to control their schema can be found in the Creek JSON Schema Generator docs.
Restricting class & module path scanning by setting allowed modules and allowed packages can increase the speed of your build.
Dependencies: compileTestJava
, compileTestKotlin
, compileTestGroovy
if they exist.
Dependants: processTestResources
The generateTestJsonSchema
works the same as generateJsonSchema, only
for test code. The generated schema output directory is added to the test
source set,
as an additional resource directories, meaning the schema will be available during unit testing.
NOTE: due to a bug in the org.javamodularity.moduleplugin
Gradle plugin,
generated resources are NOT patched in to the module during unit testing.
This should be fixed once java9-modularity/gradle-modules-plugin#228 is merged and released.
Deletes the files created by the specified task. For example, cleanGenerateJsonSchema
will delete the generated JSON schema files.
The JSON Schema plugin does not require any specific project layout.
The JSON Schema plugin adds a number of dependency configurations to your project. Tasks such as generateJsonSchema
then use these configurations to get the corresponding files and use them, for example by adding them to the class path
when generating schemas.
jsonSchemaGenerator
the JSON schema generator dependency, defaulting to the same version as the plugin.
By default, the plugin generates JSON schema using the JSON schema generator of the same version. However,
you can configure the generator version via the jsonSchemaGenerator
dependency configuration.
For example, the following would always use the latest available generator:
dependencies {
jsonSchemaGenerator 'org.creekservice:creek-json-schema-generator:+'
}
dependencies {
jsonSchemaGenerator("org.creekservice:creek-json-schema-generator:+")
}
When running a different version of the generator it may be that the generator supports command line options that
are not exposed by the plugin. In such situations, you can pass extra arguments to the generator using the
extraArguments
method of the creek.schema.json
extension.
creek {
schema {
json {
extraArguments "--some", "--extra=arguments"
}
}
}
jsonSchema {
schema {
json {
extraArguments("--some", "--extra=arguments")
}
}
}
The JSON Schema plugin adds a json
extension to creek.schema
. This allows you to configure a number of task related properties
inside a dedicated DSL block.
creek.schema.json {
// Configure scanning for @GeneratesSchema annotated types:
typeScanning {
// Restrict scanning to certain JPMS modules:
moduleWhiteList 'acme-finance', 'acme-sales-*'
// Restrict scanning to certain packages:
packageWhiteList 'com.acme.finance', 'com.acme.sales.*'
}
// Configure scanning subtypes:
subTypeScanning {
// Restrict scanning to certain JPMS modules:
moduleWhiteList 'acme-finance', 'acme-sales-*'
// Restrict class scanning for subtypes to certain packages:
packageWhiteList 'com.acme.finance', 'com.acme.sales.*'
}
}
creek.schema.json {
// Configure scanning for @GeneratesSchema annotated types:
typeScanning {
// Restrict class scanning to certain JPMS modules:
moduleWhiteList("acme-finance", "acme-sales-")
// Restrict class scanning for base types to certain packages:
packageWhiteList("com.acme.finance", "com.acme.sales.*")
}
// Configure scanning subtypes:
subTypeScanning {
// Restrict class scanning to certain JPMS modules:
moduleWhiteList("acme-finance", "acme-sales-")
// Restrict class scanning for subtypes to certain packages:
packageWhiteList("com.acme.finance", "com.acme.sales.*")
}
}
// Todo: discuyss module plugin and $moduleName
The generator scans the class and module paths of the JVM to find:
- base types to generate a schema for, i.e. types annotated with
@GeneratesSchema
. - subtypes of polymorphic types it encounters while building schema, where the base type does not define an explicit
set of subtypes, i.e. types annotated with
@JsonTypeInfo
, but not@JsonSubTypes
.
By default, these scans scan the entire class and module paths of the JVM. This can both slow down your build and result in unwanted schema files being generated for annotated types found in dependencies.
The path scans can be restricted to exclude unwanted types from schema generation and speed up the build.
Base type scanning, i.e. scanning for types annotated with @GeneratesSchema
, can be restricted by either supplying
one or more JPMS modules to scan:
creek.schema.json {
typeScanning {
moduleWhiteList 'acme-finance', 'acme-sales-*'
}
}
creek.schema.json {
typeScanning {
moduleWhiteList("acme-finance", "acme-sales")
}
}
...and/or by restricting which package names to search under:
creek.schema.json {
typeScanning {
packageWhiteList 'com.acme.finance', 'com.acme.sales.*'
}
}
creek.schema.json {
typeScanning {
packageWhiteList("com.acme.finance", "com.acme.sales.*")
}
}
Subtype scanning, i.e. scanning for subtypes of polymorphic types, can be restricted by restricting which package names to search under:
creek.schema.json {
subTypeScanning {
moduleWhiteList("acme-finance", "acme-sales")
packageWhiteList 'com.acme.finance', 'com.acme.sales.*'
}
}
creek.schema.json {
subTypeScanning {
moduleWhiteList("acme-finance", "acme-sales")
packageWhiteList("com.acme.finance", "com.acme.sales.*")
}
}
The generateJsonSchema
task generates YAML files containing the JSON schema of each @GeneratesSchema
annotated type
it encounters. By default, these are written to $buildDir/generated/resources/schema/main/schema/json
, with
$buildDir/generated/resources/schema/main
being added as a resource root. This means the schema files generated will
be included in the jar under a schema/json
directory.
The generateTestJsonSchema
task outputs to the $buildDir/generated/resources/schema/test/schema/json
, with
$buildDir/generated/resources/schema/test
being added as a resource root.
The location where schema files are written can be changed by changing either:
creek.schema.json.schemaResourceRoot
: the resource root for schema, defaulting to$buildDir/generated/resources/schema/main
, orcreek.schema.json.testSchemaResourceRoot
: the resource root for test schema, defaulting to$buildDir/generated/resources/schema/test
, orcreek.schema.json.outputDirectoryName
: the name of the subdirectory undercreek.schema.json.schemaResourceRoot
andcreek.schema.json.testSchemaResourceRoot
where schemas will be written, and defining the relative path to the schema files within the resulting jar file. This defaults to not being set, which causes the plugin to outputting schemas under a package directory structure. If this property is set, schemas will be generated into the specified flat directory, where the filename matches that full class name.
creek.schema.json {
schemaResourceRoot = file("$buildDir/custom/build/path")
testSchemaResourceRoot = file("$buildDir/custom/build/path/for/test/schema")
outputDirectoryName = "custom/path/within/jar"
}
creek.schema.json {
schemaResourceRoot.set(file("$buildDir/custom/build/path"))
testSchemaResourceRoot.set(file("$buildDir/custom/build/path/for/test/schema"))
outputDirectoryName.set("custom/path/within/jar")
}
Java 9 introduced the JPMS which, by default, encapsulates classes and resources.
Resources, for example generated schema files, that are not in the root of jar,
are encapsulated by default, i.e. not accessible from outside the module,
unless the module definition explicitly opens
the package the resource is in.
Additionally, modules require each module to expose unique packages.
With default configuration this plugin will generate schemas under a resource root using the same directory structure as the source types, i.e. the schema file will be in the same package as the type it was built from in the jar file.
If you wish the generated schema resources to be accessible from other modules, then the module definition must
include an opens
statement for the package containing the source types.
For example, given types that generate schemas in an acme.finance.model
package, ensure:
module acme.model {
// Export the package types to everyone, i.e. the code:
exports acme.finance.model;
// Open the package resources to everyone, i.e. the schema files:
opens acme.finance.model;
}
Currently, the plugin automatically configures tasks to work with the standard Java, Groovy and Kotlin plugins.
Schema generation tasks are configured to read the output of compile[Test]Java
, compile[Test]Groovy
and compile[Test]Kotlin
tasks if they are present in the project.
Support for other JVM languages may be added later, or you may be able to configure your own instance of GenerateJsonSchema
to work with your chosen language. (Consider adding details to Issue 6 if you do).