Skip to content

Configuring Files

Geert Bevin edited this page Aug 30, 2024 · 6 revisions

Your build configuration also happens in Java. bld has a Project class that is used by the app and lib templates, and a WebProject that is used for RIFE2. The only real difference is that the web project has support for the webapp directory and war archive creation, the rest is identical.

NOTE: the base template uses the BaseProject class that provides a minimal amount of standard commands, the template is really only useful if you want to fully take control over every aspect of your build. The majority of projects don't need this.

The build class that bld creates will extend either of these project classes, and the app project is already configured for testing with JUnit.

Start from scratch

Let's take an even bigger step back and construct a build file from scratch without any dependencies.

First create a baseline bld project:

bld create-base com.example myapp

Bare-bones bld project

When using plain Java and no external libraries, this is what a bld file located at src/bld/java/com/example/MyappBuild.java could look like:

Feel free to replace your MyappBuild.java file to follow along step-by-step.

package com.example;

import rife.bld.Project;

public class MyappBuild extends Project {
    public MyappBuild() {
        pkg = "com.example";                  // the root Java package of your project
        name = "Myapp";                       // the name of your project
        mainClass = "com.example.MyappMain";  // the fully qualified main class of your project
        version = version(0,1,0);             // your project's version
    }

    public static void main(String[] args) {
        new MyappBuild().start(args);         // kick off bld and pass it your CLI arguments
    }
}

The project structure that bld creates is what Project is set up to use by default. Just by organizing your files in the appropriate locations, they can be compiled, tested, ran, packaged, ...

NOTE: while the default layout works perfectly fine, you can also relocate almost every directory if you prefer to do so, we'll get into that later.

Your main class in src/main/java/com/example/MyappMain.java already looks like this, bld generated it to get you started:

package com.example;

public class MyappMain {
    public String getMessage() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        System.out.println(new MyappMain().getMessage());
    }
}

Now, make sure the myapp project folder is your current directory, and you can type:

./bld compile run

but also:

./bld jar
./bld uberjar
./bld clean

All very convenient commands even if you don't use any dependencies.

Let's continue and add a test, without using a testing framework.

For instance src/test/java/com/example/MyappTest.java that bld created for you:

package com.example;

public class MyappTest {
    void verifyHello() {
        if (!"Hello World!".equals(new MyappMain().getMessage())) {
            throw new AssertionError();
        } else {
            System.out.println("Succeeded");
        }
    }

    public static void main(String[] args) {
        new MyappTest().verifyHello();
    }
}

You also need to tell bld what the main class is for test execution, in this case you can add this line to src/bld/java/com/example/MyappBuild.java:

// ...
public class MyappBuild extends Project {
    public MyappBuild() {
        // ...
        testOperation().mainClass("com.example.MyappTest");  // the main class of your test tool
    }
    // public static void main ...
}

Now you can type:

./bld compile test

Add some dependencies

In order to make that test more informative, we could expand the Java code and add progress reporting, but we could also use a testing framework. bld is by default set up to use the JUnit 5 test tool, so let's go with that, which means we can delete the testOperation().mainClass() line we just added.

// ...
public class MyappBuild extends Project {
    public MyappBuild() {
        // testOperation().mainClass("com.example.MyappTest");
    }
    // public static void main ...
}

Let's rewrite that test with JUnit:

package com.example;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class MyappTest {
    @Test void verifyHello() {
        assertEquals("Hello World!", new MyappMain().getMessage());
    }
}

When you now compile, you'll get a bunch of compilation errors.

./bld compile
/Users/youruser/myapp/src/test/java/com/example/MyappTest.java:3: error: package org.junit.jupiter.api does not exist
import org.junit.jupiter.api.Test;
                            ^
/Users/youruser/myapp/src/test/java/com/example/MyappTest.java:4: error: package org.junit.jupiter.api does not exist
import static org.junit.jupiter.api.Assertions.*;
                                   ^
/Users/youruser/myapp/src/test/java/com/example/MyappTest.java:7: error: cannot find symbol
    @Test void verifyHello() {
     ^
  symbol:   class Test
  location: class com.example.MyappTest
/Users/youruser/myapp/src/test/java/com/example/MyappTest.java:8: error: cannot find symbol
        assertEquals("Hello World!", new MyappMain().getMessage());
        ^
  symbol:   method assertEquals(java.lang.String,java.lang.String)
  location: class com.example.MyappTest

This makes sense, because we don't have any libraries installed in lib/test. If you want, you can manually hunt down all the JUnit 5 libraries and dependencies and put them in the lib/test directory. The compile command will work fine after that. However, finding all those jar files is quite an endeavour because they're split up in small projects that depend on each-other.

So, let's use bld to download them for us:

package com.example;

import rife.bld.Project;
import java.util.List;
import static rife.bld.dependencies.Repository.*;
import static rife.bld.dependencies.Scope.*;

public class MyappBuild extends Project {
    public MyappBuild() {
        // ...
        repositories = List.of(MAVEN_CENTRAL, SONATYPE_SNAPSHOTS);
        scope(test)
            .include(dependency("org.junit.jupiter", "junit-jupiter", version(5,11,0)))
            .include(dependency("org.junit.platform", "junit-platform-console-standalone", version(1,11,0)));
    }
    // public static void main ...
}

Now type:

./bld download
Downloading: https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter/5.11.0/junit-jupiter-5.11.0.jar ... done
Downloading: https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-api/5.11.0/junit-jupiter-api-5.11.0.jar ... done
Downloading: https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-params/5.11.0/junit-jupiter-params-5.11.0.jar ... done
Downloading: https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-engine/5.11.0/junit-jupiter-engine-5.11.0.jar ... done
Downloading: https://repo1.maven.org/maven2/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar ... done
Downloading: https://repo1.maven.org/maven2/org/junit/platform/junit-platform-commons/1.11.0/junit-platform-commons-1.11.0.jar ... done
Downloading: https://repo1.maven.org/maven2/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar ... done
Downloading: https://repo1.maven.org/maven2/org/junit/platform/junit-platform-engine/1.11.0/junit-platform-engine-1.11.0.jar ... done
Downloading: https://repo1.maven.org/maven2/org/junit/platform/junit-platform-console-standalone/1.11.0/junit-platform-console-standalone-1.11.0.jar ... done
Downloading finished successfully.

NOTE: this is very different from auto-dependency resolving in other build tools, the resolution and downloading will only happen when you execute the command. It's a convenience method to get all the jars you want where they should be.

With everything downloaded to the right location, you can now compile and run your test with JUnit 5:

./bld compile test
Compilation finished successfully.
Test plan execution started. Number of static tests: 1
╷
├─ JUnit Jupiter
│  ├─ MyappTest
│  │  ├─ verifyHello()
│  │  │       tags: []
│  │  │   uniqueId: [engine:junit-jupiter]/[class:com.example.MyappTest]/[method:verifyHello()]
│  │  │     parent: [engine:junit-jupiter]/[class:com.example.MyappTest]
│  │  │     source: MethodSource [className = 'com.example.MyappTest', methodName = 'verifyHello', methodParameterTypes = '']
│  │  │   duration: 10 ms
│  │  │     status: ✔ SUCCESSFUL
│  └─ MyappTest finished after 20 ms.
└─ JUnit Jupiter finished after 27 ms.
Test plan execution finished. Number of all tests: 1

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

Beautiful!


Next learn more about Project Options

Clone this wiki locally