Creating a custom task

In this tutorial, you create and add a custom task to a lifecycle to parse a new --encoding CLI option. This will be used to set the output log file encoding for the Finish task at runtime.

Prerequisites

Estimated time

This tutorial takes about 25 minutes to complete.

Steps

1. Create a Groovy task

Create a file called CLILogEncoding.groovy in your $DBB_BUILD/groovy folder with the following IBM-1047 encoded content:

// This causes the script to extend TaskScript, which injects an SLF4j logger into the class as the variable 'log'.
// Groovy scripts are required to extend AbstractLoader at a minimum
@groovy.transform.BaseScript com.ibm.dbb.groovy.TaskScript baseScript

// This package statement isn't necessary, but may be useful for organization when making use of the logger, otherwise
// you may reference this class's logger by its script name in your 'simplelogger.properties' file.
// package <my.package.qualfier>

import com.ibm.dbb.task.TaskConstants

// An instance of org.apache.commons.cli.CommandLine placed into the context by the zBuilder
def cli = context.getCommandLine(TaskConstants.COMMAND_LINE)
if (cli.hasOption("encoding")) {
    String encoding = cli.getOptionValue("encoding")
    log.debug("Pulled '{}' from the '--encoding' cli option.", encoding)
    context.setVariable("CLI_LOG_ENCODING", encoding)
}

// The zBuilder expects an integer return code as the returned value which can be used in subsequent conditions
return 0

This script checks the command line object provided by the zBuilder for an --encoding option with a value associated with it. It then places the value into the CLI_LOG_ENCODING context variable to be used by the Finish task. The only requirement for Groovy scripts is that they extend the com.ibm.dbb.groovy.AbstractLoader class, which this script does with this line at the top:

@groovy.transform.BaseScript com.ibm.dbb.groovy.TaskScript baseScript

The log member is made accessible by extending TaskScript, and the zBuilder makes the BuildContext context and TaskVariables config objects available through the scripts Binding.

2. Create a Java task

  1. Create a Java class that extends the com.ibm.dbb.task.AbstractTask class. The AbstractTask class contains helper methods for retrieving common objects such as the Apache CommandLine object, which this tutorial interacts with. It also provides methods to assert required context/config and CLI options are set. Additionaly, the task defines the logger Logger variable that can be used within the task.

    A constructor with arguments for the BuildContext and TaskVariables objects is required, and should be passed to the super classes' constructor to be placed into context and config member variables used within the task. The execute abstract method is the main location for the task code. Its Integer return is a return code that can be used in conditions for subsequent tasks.

    The code of Java task is as follows. It performs the same operations as the previous Groovy task.

    package <my.package.qualifier>;
    
    import org.apache.commons.cli.CommandLine;
    
    import com.ibm.dbb.build.BuildException;
    import com.ibm.dbb.task.AbstractTask;
    import com.ibm.dbb.task.BuildContext;
    import com.ibm.dbb.task.TaskConstants;
    import com.ibm.dbb.task.TaskVariables;
    
    public class CLILogEncoding extends AbstractTask {
        // This constructor is required for Java tasks, the context and config variables are assigned to members with the same name.
        public CLILogEncoding(BuildContext context, TaskVariables config) {
            super(context, config);
        }
    
        // The main execution method for the task, the zBuilder will call this when executing the task.
        @Override
        public Integer execute() throws BuildException {
            // The AbstractTask class contains convenience methods for verifying required variables, and retrieving common objects by their key
            CommandLine cli = getCommandLine();
            verifyRequiredContextVariable(cli, TaskConstants.COMMAND_LINE);
            
            if (cli.hasOption("encoding")) {
                String encoding = cli.getOptionValue("encoding");
                logger.debug("Pulled '{}' from the '--encoding' cli option.", encoding);
                context.setVariable("CLI_LOG_ENCODING", encoding);
            }
    
            return 0;
        }
    }
    
  2. Compile the Java code with a Java version 11 or later by using the following command:

    javac -encoding UTF8 -classpath "$DBB_HOME/lib/*" <my/package/qualifier>/CLILogEncoding.java
    

3. Add the created task to a lifecycle

  1. Add the CLILogEncoding task to the end of the tasks list in your $DBB_BUILD/dbb-build.yaml file:

    #########################################################################
    # Basic task configurations that can be referenced by multiple lifecycles
    #########################################################################
    tasks:
      # Creates a CLI_LOG_ENCODING context variable with the value from the added '--encoding' CLI option.
      - task: CLILogEncoding
    

    As you placed the Groovy script in the $DBB_BUILD/groovy folder with the same name as the task definition name, the zBuilder can discover it automatically. Alternatively, you can add the script field to the task definition with a file path to the Groovy script.

    (Optional) If you are adding a Java task, be sure to add the class field to the task definition:

      - task: CLILogEncoding
        class: <my.package.qualifier>.CLILogEncoding
    
  2. Set the logEncoding configuration variable of the Finish task to the CLI_LOG_ENCODING context variable that was created by the CLILogEncoding task. Place the following logEncoding variable definition in a new variables section under the Finish task definition in the same location:

    - task: Finish
      variables:
        - name: logEncoding
          select:
            - condition: { exists: "CLI_LOG_ENCODING" }
              value: "${CLI_LOG_ENCODING}"
    

    A select variable is used to set the logEncoding variable only when the CLILogEncoding task has been executed and has found a --encoding option on the command line. Otherwise, its value is null and the Finish task outputs log files in the systems default encoding.

  3. Add the CLILogEncoding task to a lifecycle of your choosing. This tutorial uses the full lifecycle in this case. Add the task name to the list of tasks under the lifecycle definition:

    lifecycles:
      # build all programs for the application
      - lifecycle: full
    
        # define the list of tasks to execute during the build lifecycle
        tasks:
          - Start
          - ScannerInit
          - MetadataInit
          - FullAnalysis
          - Languages    # Defined in Languages.yaml
          - CLILogEncoding
          - Finish
    

    It can be placed anywhere in the task list, so long as it comes before the Finish task where its created context variable is used.

  4. Add the --encoding CLI option to the lifecycle definition. At the top of the lifecycle definition edited in the previous step, place a cli section with the following content:

    lifecycles:
    # build all programs for the application
      - lifecycle: full
    
        cli:
          options:
            - longOption: "encoding"
              hasArg: true
              description: "Unless set in the application configuration, overrides the default encoding used when writing out log files in the Finish task."
    

    In this definition you set the option name, indicate that it has an argument, and a description to be output alongside the option when the command dbb build full --help is entered.

4. Execute the task

Execute the full lifecycle by changing directories to the Mortgage Application sample and running the following command:

dbb build full --encoding UTF-8

The output from the new task is displayed in the console:

Language: LinkEdit
> Building 'MortgageApplication/link/epsmlist.lnk'
Task: CLILogEncoding
Task: Finish

The log files will be output and tagged in the requested encoding. This can be verified by executing ls -T logs/ from the same directory:

~/MortgageApplication #>ls -T logs
...
t UTF-8       T=on  buildList.txt

This will only affect the created buildList.txt, changedFiles.txt, renamedFiles.txt, and deletedFiles.txt files. It is not covered in this tutorial, but this can be expanded to the language task logs by defining a new select variable with a default and then setting the logEncoding field of the dd statement to a reference of this new variable.

Next Steps