JBatch: gradle and asciidoctor batch documentation


Generally most of the documentation of a project is manual but when you can automate some part why not doing it. When we speak about JBatch documentation we can automate two main parts by checking the sources:

  • The JBatch component documentation (ie their configuration)
  • The batch flow (ie drawing its flow diagram)

Side note: automating this part has an awesome benefit: you keep your documentation up to date without effort.

Apache BatchEE provides some Maven plugins to do so but when you use Gradle your are kind of on your own. However BatchEE plugin is developped in a way allowing you to reuse this logic without having to depend on maven (you just need to exclude the dependencies you don’t want if you care about them).

Document your components configuration

The idea there is just to browse the properties of the component and create a table having as key the property name and as value a description you can provide using BatchEE @Documentation annotation.

First to get this annotation add this dependency:

compile group: 'org.apache.batchee', name: 'batchee-doc-api', version: '0.3-incubating'

Then in your component you can use @Documentation on your properties:

@Named
@Documentation("Just write as it can some data.")
public class MyWriter extends MultiWriterBase {
  @Inject
  @BatchProperty
  @Documentation("The output file I will write awesome data to")
  private String output;

   // ...
}

Then to run the code processing these annotations and generating the documentation in asciidoctor format (to make it easy to integrate with any other doc) you just have to write a small task reusing ComponentDocumentationGenerator from batchee-maven-plugin:

class JBatchGenerator extends DefaultTask {
    @InputDirectory
    File classes

    @OutputDirectory
    File output

    @TaskAction
    def dynamicDoc() {
        output.mkdirs()
        println 'Generating JBatch components doc'
        // adoc4 means generate a adoc file using as root title level the level 4, 'adoc' starts at level 1
        new ComponentDocumentationGenerator(classes, new File(output, 'jbatch-components.adoc'), 'adoc4') {
            @Override
            protected void warn(String s) {
                logger.warn(s);
            }
        }.execute()
    }
}

Note: the dependency to compile this code is:

compile(group: 'org.apache.batchee', name: 'batchee-maven-plugin', version: '0.3-incubating') {
  exclude(module: 'batchee-jaxrs-client')
}

You can either add this in the buildscript classpath or if you use buildScr just add it to build.gradle dependencies of this build project.

Then in the main build.gradle add a task to execute this code:

task jbatchDoc(type: JBatchGenerator) {
    output = new File(project.buildDir, 'jbatch-doc')
    classes = sourceSets.main.output.classesDir
}

Tip: up to you now to bind this task to the build lifecycle or not

Then when you generate this task after having compiled your sources:

gradle jbatchDoc

You get this adoc:

==== myWriter

Just write as it can some data.

|===
|Name|Description
|output|The output file I will write awesome data to
|===

Of course it adds one line in the table by property and add as much blocks of this type as component it founds in classes directory. Not that components and properties are sorted to ensure to get a deterministic order of the report.

Now you just have to either include this document in another adoc file or directly render it using gradle asciidoctor plugin (https://github.com/asciidoctor/asciidoctor-gradle-plugin/). Just for the sample it can look like:

// note: in a real build file you would create a variable for new File(project.buildDir, 'jbatch-doc')
asciidoctor {
    logDocuments true
    backends 'html5', 'pdf'
    // includeBase allows the main adoc file to include the generated ones without caring of their location
    attributes 'icons': 'font', 'includeBase': new File(project.buildDir, 'jbatch-doc')
    sourceDir new File(project.projectDir, 'src/main/asciidoctor')
    sources { include 'my-super-doc.adoc' }

    dependsOn(jbatchDoc)
}

Get the diagram flow of your batches

Here the idea is the same as for components and I will skip some of the gradle glue code since it is globally the same as in the previous step. To get a diagram reusing BatchEE logic you have to use its DiagramGenerator class:

def generateJBatchDiagramsDoc() {
  println 'Generating JBatch diagrams'
  ['batch1.xml', 'batch2.xml'].each { // or list them using File#listFiles if you prefer
    new DiagramGenerator(
     new File(resources, "META-INF/batch-jobs/${it}").absolutePath, true, false,
       400, 300, false, output, 'png', "${it}-graph", true, 'level') {
         @Override
         protected void warn(String s) {
           logger.warn(s)
         }

         @Override
         protected void info(String s) {
           logger.info(s)
         }
       }.execute()
    }
}

The only difference there is instead of configuring classes folder in the task configuration we wire the resource fodler so the task would look like:

task jbatchDiagrams(type: JBatchDiagramGenerator) {
    output = new File(project.buildDir, 'jbatch-diagrams')
    classes = sourceSets.main.output.resourcesDir
}

Once executed you will get diagrams in build/jbatch-diagrams/ and the file names will be batch1.xml-graph.png but up to you to change it replacing ${it}-graph by what you prefer. Finally just integrate it in your main documentation and you have an up to date and easy to write documentation :).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s