Bulletproof
Groovy AST transformations, such as @ValueObject and @NonNull, which makes constructing an instance more bullet-proof.
Install / Use
/learn @tvinke/BulletproofREADME
Bulletproof
Groovy AST transformations, such as @ValueObject and @NonNull, which makes constructing an instance more bullet-proof.

Groovy has the Immutable annotation which allows to create immutable classes, which is a prerequisite for creating value objects. Unfortunately, when a class has been annotated with Immutable it's no longer possible to add your own constructor to verify if provided parameters are not null, making our value objects really bullet-proof.
See Ted Vinke Blog: Make Your Groovy Objects More Bullet-Proof
Bulletproof helps to fill this gap by adding a few AST transformations.
- The
NonNullannotation which modifies every constructor to perform null-checks. Add this to anImmutableclass and nonullslips past your constructor. - The
ValueObjectmeta-annotation which puts bothNonNullandImmutableon your class as a convenience to do above step with one annotation.
Contents
Prerequisites
Bulletproof requires Java 7 or later.
Installation
Add the bulletproof jar to the classpath in your preferred way and you're set.
Grape
@Grab('com.github.tvinke:bulletproof:0.2')
Gradle
compile group: 'com.github.tvinke', name: 'bulletproof', version: '0.2'
Maven
<dependency>
<groupId>com.github.tvinke</groupId>
<artifactId>bulletproof</artifactId>
<version>0.2</version>
</dependency>
Annotations
Consult the bulletproof 0.2 Groovydocs for complete API information.
NonNull
The NonNull annotation on the class-level triggers an AST transformation which modifies every constructor to perform a null-check.
@groovy.transform.Immutable
@tvinke.bulletproof.transform.NonNull
class Person {
String name
}
new Person() // throws IllegalArgumentException: "Name can not be null"
Value Object
The ValueObject meta-annotation combines the Immutable and NonNull annotations, which is used to assist in the creation of value objects.
@tvinke.bulletproof.transform.ValueObject
class Money {
BigDecimal amount
}
new Money(amount: null) // throws IllegalArgumentException because of NonNull
def money = new Money(2.95)
money.amount = 3.0 // throws ReadOnlyPropertyException because of Immutable
Future Changes
- Consider allowing a mutable object (e.g. default Map constructor, or with
TupleConstructor) also to have null-checks performed. In this case probably also through the setters. - In above case, then probably you need you want to specify which properties need to be null-checked instead of just everything.
Related Skills
node-connect
345.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
106.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
345.9kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
345.9kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
