This module is used by Helidon to generate types with builders (Prototypes) to be used in API of modules from a blueprint interface.
There are two modules that are used:
helidon-builder-api
- module required incompile
scope, contains annotations and APIs needed to write blueprints, and to build the generated codehelidon-builder-processor
- module to be placed on annotation processor path, generates the sources
There is one module useful for internal development
helidon-builder-tests-common-types
(located undertests/common-types
) that contains blueprints for the types we use inhelidon-common-types
. As the common types module is used by the processor, we would end up with a cyclic dependency, so this allows us to generate the next iteration of common types (requires manual copying of the generated types)
Generate all required types for Helidon APIs with builders, that follow the same style (method names, required validation etc.).
The following list of features is currently supported:
Builder
also implements the interface of the type (all getters are available also on builder)Type
options - interface returnsType
, such an option MUST NOT be null in the built instance, there is a validation in place on calling thebuild
orbuildPrototype
methods. Getters MAY return null on a builderOptional
options - interface returnsOptional<Type>
, setters use justType
, there is a package local setter that acceptsOptional
as well, to support updating a builder from an existing instanceList
options - interface returnsList<Type>
, never null - if there is no configured value, empty string is returnedSet
options - similar to listMap
options - key/value map, builders support any key/value types, but if configuration is used, the key must be a string- "Singular" for collection based options, which adds setter for a single value (for
List<String> algorithms()
, there would be the following setters:algorithms(List<String>)
,addAlgorithms(List<String>)
,addAlgorithm(String)
) - A type can be
@Configured
, which adds integration with Helidon common Config module, by adding a static factory methodcreate(io.helidon.common.Config)
to the generated type, as well asconfig(Config)
method to the generated builder, that sets all options annotated with@ConfiguredOption
from configuration (if present in the Config instance) - Capability to update the builder before validation (decorator)
- Support for custom methods (
@Prototype.CustomMethods
) for factory methods, prototype methods, and builder methods
We are not building a general purpose solution, there are limitations that are known and will not be targetted:
- the solution expects that everything is single package - blueprints are required to be package local, which does not allow using built types across packages within a single module
- we only support interface based definition of blueprints (no classes)
- we only support non-nullable options, instead of nullable, use
Optional
getters - implementation types of collections are fixed to
java.util.ArrayList
,java.util.LinkedHashSet
andjava.util.LinkedHashMap
- Write your interface that you want to have a builder for.
interface MyConfigBeanBlueprint {
String getName();
boolean isEnabled();
int getPort();
}
- Annotate your interface definition with
@Blueprint
, and optionally use@ConfiguredOption
,Singular
etc. to customize the getter methods. Remember to review the annotation attributes javadoc for any customizations. - Update your pom file to add annotation processor
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<version>${helidon.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
<!--
the following section is to enable correct reactor ordering without adding processor
to module classpath/module path
this is ONLY needed when adding (any) Helidon processor to a Helidon module (within the same Maven project)
-->
<dependencies>
<dependency>
<groupId>io.helidon.builder</groupId>
<artifactId>helidon-builder-processor</artifactId>
<version>${helidon.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
Generated types will be available under ./target/generated-sources/annotations
- MyConfigBean (in the same package as MyConfigBeanBlueprint), with inner classes
BuilderBase
(for inheritance),Builder
, - Support for
toString()
,hashCode()
, andequals()
are always included. - Support for
builder(MyConfigBean)
to create a new builder from an existing instance - Support for
from(MyConfigBean)
andfrom(MyConfigBean.BuilderBase<?, ?>)
to update builder from an instance or builder - Support for validation of required and non-nullable options (required options are options that have
@ConfiguredOption(required=true)
, non-nullable option is any option that is not primitive, collection, and does not return anOptional
) - Support for builder decorator (
@Bluprint(decorator = MyDecorator.class)
),class MyDecorator implements BuilderDecorator