DomUI
Welcome to DomUI Development environment
Using the Eclipse Java compiler (ecj) in Maven builds

Using the Eclipse Java compiler (ecj) in Maven builds

DomUI is compiled by the Eclipse batch compiler (ecj), not by javac. It is fast, it has far more warnings and errors that can be switched on per project, and it can do null analysis: with @NonNull and @Nullable on your code, a null that cannot happen becomes a compile error instead of an NPE in production.

To use it in Maven you need the plexus-compiler-eclipse compiler for maven-compiler-plugin, and nothing else. This is the configuration DomUI's own root pom uses:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.14.0</version>
    <configuration>
        <compilerId>eclipse</compilerId>
        <source>21</source>
        <target>21</target>

        <compilerArgs>
            <arg>-properties</arg>
            <arg>${project.basedir}/.settings/org.eclipse.jdt.core.prefs</arg>
            <arg>-enableJavadoc</arg>
            <arg>-nowarn</arg>
        </compilerArgs>

        <showWarnings>true</showWarnings>
        <showDeprecation>true</showDeprecation>
    </configuration>

    <dependencies>
        <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-eclipse</artifactId>
            <version>2.8.5</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jdt</groupId>
            <artifactId>ecj</artifactId>
            <version>3.36.0</version>
        </dependency>
    </dependencies>
</plugin>

Put it in the pluginManagement or the build section of your parent pom; Maven's configuration inherits, so a module only has to add what is specific to it.

The parts

<compilerId>eclipse</compilerId> is what switches the compiler; without it the plugin uses javac and the two dependencies below do nothing.

The two dependencies are separate on purpose. plexus-compiler-eclipse is the adapter that knows how to drive ecj from Maven; org.eclipse.jdt:ecj is the compiler itself. Always pin the ecj version. If you leave it out, the adapter picks a version, and the day it picks a different one is the day before your release.

<compilerArgs> are passed to ecj as they stand. This is the tag to use; the older <compilerArguments> is deprecated and mangles what it is given. The four arguments above are:

Argument What it does
-properties <file> read the warning/error configuration from that file
-enableJavadoc check javadoc references, so a @link to something that no longer exists is reported
-nowarn do not print the warnings; the properties file decides what is an error, and that is what should stop the build

The properties file

-properties points at a file in Eclipse's own format, and DomUI points it at ${project.basedir}/.settings/org.eclipse.jdt.core.prefs - which is exactly where the Eclipse IDE writes its per-project compiler settings. So every module carries its own file, and the build enforces what the IDE shows.

It is a flat list of problem=error|warning|ignore lines, 380 of them in DomUI's case. The ones that matter most are the null-analysis block:

org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=enabled

They name the annotations to trust - DomUI uses the org.eclipse.jdt.annotation ones - and switch the analysis on. inheritNullAnnotations makes an override inherit the annotations of the method it overrides, so an interface annotated once carries the contract to every implementation.

Annotation processing

The adapter runs annotation processors, so the processor that generates DomUI's typed properties is configured on the same plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>${maven-compiler-plugin.version}</version>
    <configuration>
        <annotationProcessors>
            <annotationProcessor>db.annotationprocessing.PropertyAnnotationProcessor</annotationProcessor>
        </annotationProcessors>
        <annotationProcessorPaths>
            <dependency>
                <groupId>to.etc.domui</groupId>
                <artifactId>property-annotations-processor</artifactId>
                <version>1.2-SNAPSHOT</version>
            </dependency>
        </annotationProcessorPaths>
    </configuration>

    <dependencies>
        <dependency>
            <groupId>to.etc.domui</groupId>
            <artifactId>property-annotations-processor</artifactId>
            <version>1.2-SNAPSHOT</version>
        </dependency>
    </dependencies>
</plugin>

There is no mention of plexus-compiler-eclipse here, and there does not need to be: the parent pom above already said which compiler to use, and this module only adds the processor to it.

Because part of the source is generated this way, a project has to be built by Maven at least once before an IDE can build it - the generated sources do not exist until the processor has run. For the same reason IntelliJ has to be told to use the Eclipse compiler, or it will disagree with the build about what compiles.

Last modified: 2026/09/06