Skip to content

Custom Commands

Geert Bevin edited this page Jul 31, 2024 · 7 revisions

bld build files are pure Java source code, you can edit them with any Java IDE and the bld jar and javadocs will provide all the assistance you may require.

Commands

Your project's build file declares which commands are available to the build system. The standard Project, WebProject and BaseProject already declare the commands you've seen in the previous overview.

The easiest way to create a new command, or to override an existing one, is to create a method in your build file and to annotate it with @BuildCommand.

For example:

import rife.bld.BuildCommand;

public class MyappBuild extends WebProject {
    public MyappBuild() {
        // ...
    }

    @BuildCommand
    public void newcommand() {
        System.out.println("This is my new command");
    }

    @Override
    public void test()
    throws Exception {
        System.out.println("Do something before testing");
        super.test();
    }
    // public static void main ...
}

You can try your new command:

./bld newcommand
This is my new command

Or the modified test one:

./bld test
Do something before testing

└─ JUnit Jupiter ✔

Test run finished after 23 ms
[         1 containers found      ]
[         0 containers skipped    ]
[         1 containers started    ]
[         0 containers aborted    ]
[         1 containers successful ]
[         0 containers failed     ]
[         0 tests found           ]
[         0 tests skipped         ]
[         0 tests started         ]
[         0 tests aborted         ]
[         0 tests successful      ]
[         0 tests failed          ]

Command lambdas and classes

Another way to register new commands is to provide the logic for them in your constructor, for example:

public class MyappBuild extends WebProject {
    public MyappBuild() {
        // ...
        buildCommands().put("newcommand", () -> {
            System.out.println("This is my new command");
        });
    }
    // ...
}

Alternatively, you can also create a class that implements CommandDefinition if you want to further modularize your code:

import rife.bld.CommandDefinition;

public class MyappBuild extends WebProject {
    public static class NewCommand implements CommandDefinition {
        public void execute()  {
            System.out.println("This is my new command");
        }
    }
    
    public MyappBuild() {
        // ...
        buildCommands().put("newcommand", new NewCommand());
    }
    // ...
}

Operations

As you can see above, commands are just regular Java methods and can really do anything you want. bld implements a series of operations that are called by most of the standard commands.

For example:

    // ...
    @BuildCommand(help = RunHelp.class)
    public void run()
    throws Exception {
        new RunOperation().fromProject(this).execute();
    }

    @BuildCommand(help = TestHelp.class)
    public void test()
    throws Exception {
        new TestOperation().fromProject(this).execute();
    }
    // ...

The javadocs of the standard operations provide all the details of their features. Instead of delegating to the parent test() method in the first example, you could customize the TestOperation with other options that might be more appropriate:

public class MyappBuild extends WebProject {
    // ...
    @Override
    public void test()
    throws Exception {
        System.out.println("Do something before testing");
        new TestOperation()
            .fromProject(this)
            .mainClass("your.test.ToolExecutor")
            .execute();
    }
    // public static void main ...
}

Command help

The BuildCommand annotation can optionally take a help argument. This is an implementation of the CommandHelp interface that will be used when displaying help with bld's help command.

For example:

public class TestHelp implements CommandHelp {
    public String getSummary() {
        return "Tests the project";
    }

    public String getDescription(String topic) {
        return StringUtils.replace("""
            Tests the project.
                        
            Usage : ${topic}""", "${topic}", topic);
    }
}

Alternatively, you can also directly provide either the summary or the description as an annotation attribute.

For example:

public class MyappBuild extends WebProject {
    // ...
    @BuildCommand(summary = "Tests the project")
    public void test()
    throws Exception {
        new TestOperation().fromProject(this).execute();
    }
    // public static void main ...
}

Run operations once

The earlier paragraph showed how to directly execute operations. However, in reality bld uses an alternative way to ensure that a particular operation only executes once. This is especially useful for common commands like jar, that could be used by other commands like war and uberjar and be combined into a single series of build commands.

In order to achieve this, all standard operations provide the executeOnce method that takes a lambda to perform their configuration the first and only time they're executed.

Therefore, the real run command implementation is actually:

    // ...
    private final RunOperation runOperation = new RunOperation();

    @BuildCommand(help = RunHelp.class)
    public void run()
    throws Exception {
        runOperation.executeOnce(() -> runOperation.fromProject(this));
    }
    // ...

You can use a similar technique if you have operations that you never want to execute more once in a build.

Configuring standard operations

The Project and WebProject classes expose the standard operation instances that are used by the commands. You can retrieve them and change their options to change how the standard commands operate. Please refer to the javadocs of the operations for more details about these options.

The following methods are available for the standard operations:

cleanOperation();           // returns the standard instance of CleanOperation
compileOperation();         // returns the standard instance of CompileOperation
dependencyTreeOperation();  // returns the standard instance of DependencyTreeOperation
downloadOperation();        // returns the standard instance of DownloadOperation
jarJavadocOperation();      // returns the standard javadoc instance of JarOperation
jarOperation();             // returns the standard compiled instance of JarOperation
jarSourcesOperation();      // returns the standard sources instance of JarOperation
javadocOperation();         // returns the standard instance of JavadocOperation
precompileOperation();      // returns the standard instance of PrecompileOperation
publishOperation();         // returns the standard instance of PublishOperation
publishOperation();         // returns the standard instance of PublishOperation
purgeOperation();           // returns the standard instance of PurgeOperation
runOperation();             // returns the standard instance of RunOperation
testOperation();            // returns the standard instance of TestOperation
uberJarOperation();         // returns the standard instance of UberJarOperation
updatesOperation();         // returns the standard instance of UpdatesOperation
versionOperation();         // returns the standard instance of VersionOperation
warOperation();             // returns the standard instance of WarOperation

Next learn more about Configuring Bld Files

Clone this wiki locally