Search code examples
javagradlejsonschema2pojo

How to Run Java Code from Gradle at Build Time


I'm using jsonschema-generator to generate a JSON schema file based on my POJOs. Currently I'm doing it via a test that is run during the gradle build step. This works fine but it doesn't feel right as really what I'm doing is not testing anything.

I've also found this answer which details how to run it on gradle run but this is not ideal either as it will pointlessly execute this every time the application comes up but not when I build.

Therefore, is there a way to tell gradle (in build.gradle) to run a piece of Java code at build time?

For completeness, here the code I'm looking to run:

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.victools.jsonschema.generator.Option;
import com.github.victools.jsonschema.generator.OptionPreset;
import com.github.victools.jsonschema.generator.SchemaGenerator;
import com.github.victools.jsonschema.generator.SchemaGeneratorConfig;
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder;
import com.mypackage.MyClass;
import org.junit.jupiter.api.Test;

import java.io.PrintWriter;
import java.util.Map;

@SuppressWarnings({"FieldCanBeLocal", "rawtypes"})
public class JsonSchemaGenerator {
    private final String SCHEMA_FOLDER = "schemas/";
    private final Map<Class, String> schemaToGenerate = Map.of(
            MyClass.class, "my-class.schema"
    );

    @Test
    public void generateJsonSchema() throws Exception {
        SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(new ObjectMapper(), OptionPreset.PLAIN_JSON);
        SchemaGeneratorConfig config = configBuilder.with(Option.DEFINITIONS_FOR_ALL_OBJECTS).build();
        SchemaGenerator generator = new SchemaGenerator(config);

        for (var entry : schemaToGenerate.entrySet()) {
            JsonNode jsonSchema = generator.generateSchema(entry.getKey());
            PrintWriter out = new PrintWriter(SCHEMA_FOLDER + entry.getValue());
            out.println(jsonSchema.toPrettyString());
            out.close();
        }
    }
}

Solution

  • The JavaExec Plugin seems to meet your requirements.

    This allows you to run a main() method and thereby any Java Code you want – including whatever JSON Schema generation you like.

    This other answer also describes pretty much what you want to do.


    Adapted from the linked documentation:

    apply plugin: 'java'
    
    task generateJsonSchema(type: JavaExec) {
      classpath = sourceSets.main.runtimeClasspath
    
      main = 'package.Main'
    
      // arguments to pass to the application
      args 'appArg1'
    }
    

    As per Jorn's comment below:

    You can depend the build task on your custom task: build.dependsOn generateJsonSchema if your custom task is defined as task generateJsonSchema(type: JavaExec) { ... }