Jilt 1.1 released
My last three articles on the blog were about new releases of Specnaz, my open-source Java/Kotlin testing library. In the last post, I promised the next one will be about something else. That’s why today, I’ll be talking about a new release of Jilt, which is… also an open-source Java library that I’ve created. This one, however, is an annotation processor for automatically generating classes that implement the Builder design pattern, including its Type-Safe variant (I’ve written about the Type-Safe Builder pattern variant, and Jilt, previously on this blog here).
Version 1.1
brings with it only one feature – the @BuilderInterfaces
annotation. This annotation can be used alongside the existing @Builder
annotation. It allows customizing the interfaces that will be generated for each property of the target class to ensure the type-safety of the resulting Builder. Because of that, it has any effect only when generating a Type-Safe Builder (so, when the style
attribute of the @Builder
annotation is either BuilderStyle.TYPE_SAFE
or BuilderStyle.TYPE_SAFE_UNGROUPED_OPTIONALS
).
@BuilderInterfaces
has 4 attributes. All of them are Strings, and all of them are optional. They are:
outerName
, which allows you to control the name of the outer interface that the per-property interfaces will be generated inside of.Since using Type-Safe Builders requires generating a large number of interfaces (usually one per each property of the built class), Jilt always generates them as nested interfaces, to not pollute the global namespace (and to reduce the chance of accidental conflicts, when 2 classes that we are generating Builders for are in the same Java package, and have a property with the same name).
The
outerName
attribute of the@BuilderInterfaces
annotation allows you to customize the name of that outer interface. By default, it’s equal to<BuiltClass>Builders
(so, if we’re generating Builders for a class namedPerson
, it will bePersonBuilders
).packageName
, which allows changing the Java package that the outer interface mentioned above (and, by extension, all of its inner interfaces) reside in.By default, the outer interface resides in the same package as the generated Builder (so, the same package as the
@Builder#packageName
attribute points to – if it’s empty, that will be the same package the built class is in).innerNames
, which allows you to customize the names of the per-property interfaces by providing a pattern for naming them. In the pattern, the character*
will be substituted with the (capitalized) name of the property the given interface corresponds to.So, if the built class has a property called
name
, and you set theinnerNames
attribute to"Jilt_*"
, the generated interface for thename
property will be calledJilt_Name
.By default, the interface names will simply be the capitalized name of their corresponding properties – so, the same as the pattern
"*"
.lastInnerName
, which is used to change the name of the final interface – the one that contains thebuild
method (it can also be called something other thanbuild
, by setting the@Builder#buildMethod
attribute).By default, that interface is called
Optionals
for Builders with theBuilderStyle.TYPE_SAFE
style, andBuild
forBuilderStyle.TYPE_SAFE_UNGROUPED_OPTIONALS
ones.There is an interesting subtlety with how this attribute interacts with
innerNames
described above. The name of the last interface is affected by setting theinnerNames
attribute. So, continuing the example from above, ifinnerNames
is"Jilt_*"
, then the last interface will be called eitherJilt_Optionals
orJilt_Build
, depending on the chosen style. This is usually what you want – if you’re settinginnerNames
, that most likely means you want all of the interfaces to share a common prefix and/or suffix.However, setting
lastInnerName
ignores the pattern frominnerNames
– so, iflastInnerName
is"Last"
, andinnerNames
is still"Jilt_*"
, the last interface will NOT be calledJilt_Last
– it will be justLast
. If you want it to be calledJilt_Last
, you need to explicitly setlastInnerName
to"Jilt_Last"
. This way, you have complete control over all of the names of interfaces, at the (small, I think) cost of needing to repeat the pattern if setting bothinnerNames
andlastInnerName
at the same time.
Summary
That’s Jilt 1.1 in a nutshell. Let me know what you think of the library in the comments!