The framework uses three main modules:

  • API: the runtime API, it is the runtime API, mainly resolution/look-up oriented

  • Build API: it is the API only required at build time, it is intended to be used to trigger the generation of the runtime classes using processor module,

  • Processor: it contains the magic generating most of the runtime and making the framework efficient and light.

Therefore the project will generally get the api in scope compile, the build api in scope provided or optional and the processor either in scope provided/optional or just defined as an annotation processor in your compiler configuration.

IMPORTANT
the generation process assumes the annotation processor is aware of all classes, depending the tools you generate you can need to disable incremental compilation as of today to ensure all classes are seen by the generator.

Maven

Simplest

The simplest is to just add the API (scope compile) and processor (scope provided):

<dependencies>
  <dependency>
    <groupId>io.yupiik.fusion</groupId>
    <artifactId>fusion-api</artifactId>
    <version>${fusion.version}</version>
  </dependency>
  <dependency>
    <groupId>io.yupiik.fusion</groupId>
    <artifactId>fusion-processor</artifactId>
    <version>${fusion.version}</version>
    <scope>provided</scope>
  </dependency>
</dependencies>
TIP

if can be sane to compile your project with maven (mvn compile or mvn process-classes) instead of relying on your IDE. This is indeed a general rule but, in this case, will enable to avoid the pitfalls of a fake incremental compilation (compiling only a few source files using the precompiled project output). This last case can lead to missing bean, you can obviously delete the target folder of your project to force your IDE to recompile but it is saner to just rely on a properly compile phase.

Java >=21

Java 21 starts to warn when you use annotation processors autodiscovery. Future java versions will even disable it by default.

For such version, you must explicitly enable the annotation processing. One option to do that is to use this maven-compiler-plugin configuration:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.11.0</version>
  <executions>
    <execution>
      <id>default-process-annotations</id>
      <phase>generate-sources</phase>
      <goals>
        <goal>compile</goal>
      </goals>
      <configuration>
        <proc>only</proc>
        <useIncrementalCompilation>true</useIncrementalCompilation>
      </configuration>
    </execution>
    <execution>
      <id>test-process-annotations</id>
      <phase>generate-test-sources</phase>
      <goals>
        <goal>testCompile</goal>
      </goals>
      <configuration>
        <proc>only</proc>
        <useIncrementalCompilation>true</useIncrementalCompilation>
      </configuration>
    </execution>
  </executions>
  <configuration>
    <proc>none</proc>
    <source>21</source>
    <target>21</target>
    <release>21</release>
    <encoding>UTF-8</encoding>
    <useIncrementalCompilation>false</useIncrementalCompilation>
    <compilerArgs>
      <compilerArg>-parameters</compilerArg>
    </compilerArgs>
    <annotationProcessors>
      <annotationProcessor>io.yupiik.fusion.framework.processor.FusionProcessor</annotationProcessor>
    </annotationProcessors>
  </configuration>
</plugin>

IDE/Jetbrains Idea

Until you configure IDEA to use maven to compile, it can happen it compiles a single source (at least not the whole module properly like Maven by default) so the output can miss some beans. If it happens (java: java.lang.IllegalArgumentException: Unsupported type: 'com.superbiz.MyJsonModel', known models: [....] at compile time or NoClassDefFoundError/No bean matching type '...' at test/runtime for example), then just Rebuild the project, command is in Build menu (shortcut: Alt+B -> R by default).

Ultimately just drop the target/out folder if it is not about adding a file but more about removing a file (incremental support of such a change is not great as of today - but this is not specific to this project ;)).

Use ECJ compiler (Eclipse)

For ECJ to work you need to ensure the argument -sourcepath is set in compiler configuration and import plexus-compiler-eclipse (Maven):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.10.1</version>
  <configuration>
    <compilerId>eclipse</compilerId>
    <compilerArguments>
      <sourcepath>${project.basedir}/src/main/java</sourcepath>
    </compilerArguments>
  </configuration>
  <dependencies>
    <dependency>
      <groupId>org.codehaus.plexus</groupId>
      <artifactId>plexus-compiler-eclipse</artifactId>
      <version>2.12.1</version>
    </dependency>
  </dependencies>
</plugin>

Do not expose processor in code completion

A more advanced option would be to define the api in scope compile, the build API in scope provided and the processor only in maven-compiler-plugin.

This option is more complex in terms of configuration but has the advantage to not expose the processor in the IDE (completion).

Here is what it can look like:

<project>
  <dependencies>
    <dependency>
      <groupId>io.yupiik.fusion</groupId>
      <artifactId>fusion-api</artifactId>
      <version>${fusion.version}</version>
    </dependency>
    <dependency>
      <groupId>io.yupiik.fusion</groupId>
      <artifactId>fusion-build-api</artifactId>
      <version>${fusion.version}</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.10.1</version>
        <configuration>
          <annotationProcessorPaths>
            <annotationProcessorPath>
              <groupId>io.yupiik.fusion</groupId>
              <artifactId>fusion-processor</artifactId>
              <version>${fusion.version}</version>
            </annotationProcessorPath>
          </annotationProcessorPaths>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
IMPORTANT

disabling the incremental compilation there is generally a good idea, in particular on CI but not having the processor in provided scope will make your IDE no more able to generate properly classes in general. So a better option can be to stick to previous dependencies only option (by default maven recompiles properly the module - don't set <useIncrementalCompilation>false</useIncrementalCompilation> it means do not use incremental compilation).

Kubernetes

By default Fusion configuration system comes with JVM system properties and environment variables support. It is also able to automatically enable default Kubernetes secret but most of the time you'll need to set the list of directories (comma separated) to the FUSION_CONFIGURATION_SOURCES_SECRETS environment variables if you mount them anywhere else than /var/run/secrets. If you use /var/run/secrets, ensure to bind secrets in a directory named as your configuration prefix, for example /var/run/secrets/app if you use app.xxxx keys. This will enable the autodiscovery to work automatically.

You can also bind in the same directory than your configuration (app in previous example) a _fusion.secrets.configuration.properties file - often in the same Secret in Kubernetes - to refine the way the directory name and children files recompose the configuration key name.

This file can contain folder.name.mode entry which can take these values:

  • default (or empty): do nothing, take the file name as configuration key,

  • concat: concatenate the directory name and file name separated by a dot (app/xxxx will lead to app.xxxx key),

  • strip: if the file name starts with the directory name, remove the directory name (with a dot suffix, for ex app/app.xxxx will lead to xxxx key).