Fusion framework Setup
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 ( |
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 |
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 toapp.xxxx
key), -
strip
: if the file name starts with the directory name, remove the directory name (with a dot suffix, for exapp/app.xxxx
will lead toxxxx
key).