# freebuilder
**Repository Path**: mirrors/freebuilder
## Basic Information
- **Project Name**: freebuilder
- **Description**: Automatic generation of the Builder pattern for Java
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 1
- **Created**: 2017-04-03
- **Last Updated**: 2025-12-27
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
FreeBuilder
===========
_Automatic generation of the Builder pattern for Java 1.8+_
[](https://search.maven.org/artifact/org.inferred/freebuilder)
[](https://github.com/inferred/FreeBuilder/actions/workflows/ci.yml?query=branch%3Amain)
> The Builder pattern is a good choice when designing classes whose constructors
> or static factories would have more than a handful of parameters.
> — Effective Java, Second Edition, page 39
Project Archival
----------------
FreeBuilder was released back in 2015! It was a pet project of my own that unfortunately generated a weird amount of controversy at the company I worked at at the time, and thus ended up being open-sourced after the Immutables project had already been on the scene for most of a year. While I hoped the different design that allowed using partials for robust testing would still be a winner, a community hasn't picked up, and as I haven't used Java at my work for over 5 years now, and it's clearly not keeping up with modern Java, I think it's time to archive it.
If someone feels strongly about picking up where I've left off, please do reach out and let me know! I'd ask that you first fork the project and modernize the dev and CI setup, which really needs doing.
Otherwise, it's been a fun ride, and thanks to everyone who's been building free with me along the way đ
— Alice
Table of Contents
-----------------
- [Project Archival](#project-archival)
- [Background](#background)
- [How to use FreeBuilder](#how-to-use-freebuilder)
- [Quick start](#quick-start)
- [What you get](#what-you-get)
- [Accessor methods](#accessor-methods)
- [Defaults and constraints](#defaults-and-constraints)
- [Optional values](#optional-values)
- [Using `@Nullable`](#using-nullable)
- [Converting from `@Nullable`](#converting-from-nullable)
- [Collections and Maps](#collections-and-maps)
- [Nested buildable types](#nested-buildable-types)
- [Lists of buildable types](#lists-of-buildable-types)
- [Disabling buildable lists](#disabling-buildable-lists)
- [Custom toString method](#custom-tostring-method)
- [Custom conventional method names](#custom-conventional-method-names)
- [Custom functional interfaces](#custom-functional-interfaces)
- [Builder construction](#builder-construction)
- [Partials](#partials)
- [Jackson](#jackson)
- [GWT](#gwt)
- [Build tools and IDEs](#build-tools-and-ides)
- [javac](#javac)
- [Maven](#maven)
- [Gradle](#gradle)
- [Eclipse](#eclipse)
- [IntelliJ](#intellij)
- [Release notes](#release-notes)
- [2.3âFrom method testability](#23from-method-testability)
- [2.2âPrimitive optional types](#22primitive-optional-types)
- [2.1âLists of buildable types](#21lists-of-buildable-types)
- [Upgrading from v1](#upgrading-from-v1)
- [Troubleshooting](#troubleshooting)
- [Troubleshooting javac](#troubleshooting-javac)
- [Troubleshooting Eclipse](#troubleshooting-eclipse)
- [Online resouces](#online-resouces)
- [Alternatives](#alternatives)
- [Immutables vs FreeBuilder](#immutables-vs-freebuilder)
- [AutoValue vs FreeBuilder](#autovalue-vs-freebuilder)
- [Proto vs FreeBuilder](#proto-vs-freebuilder)
- [Wait, why "free"?](#wait-why-free)
- [License](#license)
Background
----------
Implementing the [Builder pattern](http://en.wikipedia.org/wiki/Builder_pattern)
in Java is tedious, error-prone and repetitive. Who hasn't seen a ten-argument
constructor, thought cross thoughts about the previous maintainers of the
class, then added "just one more"? Even a simple four-field class requires 39
lines of code for the most basic builder API, or 72 lines if you don't use a
utility like [AutoValue][] to generate the value boilerplate.
FreeBuilder produces all the boilerplate for you, as well as free extras like
JavaDoc, getter methods, mapper methods, [collections support](#collections-and-maps),
[nested builders](#nested-buildable-types), and [partial values](#partials)
(used in testing), which are highly useful, but would very rarely justify
their creation and maintenance burden in hand-crafted code. (We also reserve
the right to add more awesome methods in future!)
> [The Builder pattern] is more verbose…so should only be used if there are
> enough parameters, say, four or more. But keep in mind that you may want to add
> parameters in the future. If you start out with constructors or static
> factories, and add a builder when the class evolves to the point where the
> number of parameters starts to get out of hand, the obsolete constructors or
> static factories will stick out like a sore thumb. Therefore, it's often better
> to start with a builder in the first place.
> — Effective Java, Second Edition, page 39
How to use FreeBuilder
----------------------
### Quick start
_See [Build tools and IDEs](#build-tools-and-ides) for how to add FreeBuilder
to your project's build and/or IDE._
Create your value type (e.g. `Person`) as an interface or abstract class,
containing an abstract accessor method for each desired field. Add the
`@FreeBuilder` annotation to your class, and it will automatically generate an
implementing class and a package-visible builder API (`Person_Builder`), which
you must subclass. For instance:
```java
import org.inferred.freebuilder.FreeBuilder;
@FreeBuilder
public interface Person {
/** Returns this person's full (English) name. */
String name();
/** Returns this person's age in years, rounded down. */
int age();
/** Returns a new {@link Builder} with the same property values as this person. */
Builder toBuilder();
/** Builder of {@link Person} instances. */
class Builder extends Person_Builder { }
}
```
The `toBuilder()` method here is optional but highly recommended.
You may also wish to make the builder's constructor package-protected and manually
provide instead a static `builder()` method on the value type (though
Effective Java does not do this).
### What you get
If you write the Person interface shown above, you get:
* A builder class with:
* a no-args constructor
* JavaDoc
* getters (throwing `IllegalStateException` for unset fields)
* setters
* lambda-accepting mapper methods
* `mergeFrom` and static `from` methods to copy data from existing values or builders
* a `build` method that verifies all fields have been set
* [see below for default values and constraint checking](#defaults-and-constraints)
* An implementation of `Person` with:
* `toString`
* `equals` and `hashCode`
* A [partial](#partials) implementation of `Person` for unit tests with:
* `UnsupportedOperationException`-throwing getters for unset fields
* `toString`
* `equals` and `hashCode`
```java
Person person = new Person.Builder()
.name("Phil")
.age(31)
.build();
System.out.println(person); // Person{name=Phil, age=31}
```
### JavaBean convention
If you prefer your value types to follow the JavaBean naming convention, just prefix your accessor methods with 'get' (or, optionally, 'is' for boolean accessors). FreeBuilder will follow suit, and additionally add 'set' prefixes on setter methods, as well as dropping the prefix from its toString output.
```java
@FreeBuilder
public interface Person {
/** Returns the person's full (English) name. */
String getName();
/** Returns the person's age in years, rounded down. */
int getAge();
/** Builder of {@link Person} instances. */
class Builder extends Person_Builder { }
}
Person person = new Person.Builder()
.setName("Phil")
.setAge(31)
.build();
System.out.println(person); // Person{name=Phil, age=31}
```
### Accessor methods
For each property `foo`, the builder gets:
| Method | Description |
|:------:| ----------- |
| A setter method, `foo` | Throws a NullPointerException if provided a null. (See the sections on [Optional](#optional-values) and [Nullable](#using-nullable) for ways to store properties that can be missing.) |
| A getter method, `foo` | Throws an IllegalStateException if the property value has not yet been set. |
| A mapper method, `mapFoo` | Takes a [UnaryOperator]. Replaces the current property value with the result of invoking the unary operator on it. Throws a NullPointerException if the operator, or the value it returns, is null. Throws an IllegalStateException if the property value has not yet been set. |
The mapper methods are very useful when modifying existing values, e.g.
```java
Person olderPerson = person.toBuilder().mapAge(age -> age + 1).build();
```
[UnaryOperator]: https://docs.oracle.com/javase/8/docs/api/java/util/function/UnaryOperator.html
### Defaults and constraints
We use method overrides to add customization like default values and constraint
checks. For instance:
```java
@FreeBuilder
public interface Person {
/** Returns the person's full (English) name. */
String name();
/** Returns the person's age in years, rounded down. */
int age();
/** Returns a human-readable description of the person. */
String description();
/** Builder class for {@link Person}. */
class Builder extends Person_Builder {
public Builder() {
// Set defaults in the builder constructor.
description("Indescribable");
}
@Override Builder age(int age) {
// Check single-field (argument) constraints in the setter method.
checkArgument(age >= 0);
return super.age(age);
}
@Override public Person build() {
// Check cross-field (state) constraints in the build method.
Person person = super.build();
checkState(!person.description().contains(person.name()));
return person;
}
}
}
```
### Optional values
If a property is optional—that is, has no reasonable default—then
use [the Java Optional type][] (or [the Guava Optional type][] for
backwards-compatibility).
[the Java Optional type]: https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
[the Guava Optional type]: http://google.github.io/guava/releases/19.0/api/docs/com/google/common/base/Optional.html
```java
/** Returns an optional human-readable description of the person. */
Optional description();
```
This property will now default to Optional.empty(), and the Builder
will gain additional convenience setter methods:
| Method | Description |
|:------:| ----------- |
| `description(String value)` | Sets the property to `Optional.of(value)`. Throws a NullPointerException if value is null; this avoids users accidentally clearing an optional value in a way that peer review is unlikely to catch. |
| `clearDescription()` | Sets the property to `Optional.empty()`. |
| `description(Optional value)` | Sets the property to `value`. |
| `nullableDescription(String value)` | Sets the property to `Optional.ofNullable(value)`. |
| `mapDescription(UnaryOperator mapper` | If the property value is not empty, this replaces the value with the result of invoking `mapper` with the existing value, or clears it if `mapper` returns null. Throws a NullPointerException if `mapper` is null. |
Prefer to use explicit defaults where meaningful, as it avoids the need for
edge-case code; but prefer Optional to ad-hoc 'not set' defaults, like -1 or
the empty string, as it forces the user to think about those edge cases.
#### Using `@Nullable`
As Java currently stands, **you should strongly prefer Optional to returning
nulls**. Using null to represent unset properties is the classic example of
[Hoare's billion-dollar mistake][Hoare]: a silent source of errors that users
won't remember to write test cases for, and which won't be spotted in code reviews.
The large "air gap" between the declaration of the getter and the usage is the
cause of this problem. Optional uses the compiler to force the call sites to
perform explicit null handling, giving reviewers a better chance of seeing
mistakes. See also [Using and Avoiding Null][].
Obviously, greenfield code can trivially adopt Optional, but even existing APIs
can be converted to Optional via a simple refactoring sequence; see below.
However, if you have **compelling legacy reasons** that mandate using nulls,
you can disable null-checking by marking the getter method `@Nullable`. (Any
annotation type named "Nullable" will do, but you may wish to use
`javax.annotation.Nullable`, as used in [Google Guava][Guava].)
```java
/** Returns an optional title to use when addressing the person. */
@Nullable String title();
```
This property will now default to null, and the Builder's setter methods will
change their null-handling behaviour:
| Method | Description |
|:------:| ----------- |
| `title(@Nullable String title)` | Sets the property to `title`. |
| `title()` | Returns the current value of the property. May be null. |
| `mapTitle(UnaryOperator mapper)` | Takes a [UnaryOperator]. Replaces the current property value, if it is not null, with the result of invoking `mapper` on it. Throws a NullPointerException if `mapper` is null. `mapper` may return a null. |
[Guava]: https://github.com/google/guava
[Hoare]: http://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare
[Using and Avoiding Null]: https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained
#### Converting from `@Nullable`
This is the O(1), non-tedious, non–error-prone way we recomment converting
`@Nullable` to Optional:
* Load all your code in Eclipse, or another IDE with support for renaming and
inlining.
* _[IDE REFACTOR]_ Rename all your `@Nullable` getters to `nullableX()` (or `getNullableX()` if you use JavaBean naming conventions).
* Add an Optional-returning `x()` (or `getX()`)
* Implement your nullableX methods as: `return x().orElse(null)`
(Guava: `return x().orNull()`)
* _[IDE REFACTOR]_ Inline your `nullableX()` methods
At this point, you have effectively performed an automatic translation of a
`@Nullable` method to an Optional-returning one. Of course, your code is not
optimal yet (e.g. `if (foo.x().orElse(null) != null)` instead of `if
(foo.x().isPresent())` ). Search-and-replace should get most of these issues.
* _[IDE REFACTOR]_ Rename all your `@Nullable` setters to `nullableX` (or `setNullableX`).
Your API is now FreeBuilder-compatible :)
### Collections and Maps
FreeBuilder has special support for collection and map properties, removing
the `foo` accessor method and generating new ones appropriate to the type.
Collection and map properties default to an empty collection/map and cannot hold
nulls.
```java
/** Returns a list of descendents for this person. **/
List descendants();
```
A [List][], [Set][], [SortedSet][] or [Multiset][]
property called 'descendants' would generate:
| Method | Description |
|:------:| ----------- |
| `addDescendants(String element)` | Appends `element` to the collection of descendants. If descendants is a set and the element is already present, it is ignored. Throws a NullPointerException if element is null. |
| `addDescendants(String... elements)` | Appends all `elements` to the collection of descendants. If descendants is a set, any elements already present are ignored. Throws a NullPointerException if elements, or any of the values it holds, is null. |
| `addAllDescendants(âIterable elements)`
`addAllDescendants(âStream elements)`
`addAllDescendants(âSpliterator elements)` | Appends all `elements` to the collection of descendants. If descendants is a set, any elements already present are ignored. Throws a NullPointerException if elements, or any of the values it holds, is null. |
| `mutateDescendants(âConsumer<â.â.â.â>Â mutator)` | Invokes the [Consumer] `mutator` with the collection of descendants. (The mutator takes a list, set or map as appropriate.) Throws a NullPointerException if `mutator` is null. As `mutator` is a void consumer, any value returned from a lambda will be ignored, so be careful not to call pure functions like [stream()] expecting the returned collection to replace the existing collection. |
| `clearDescendants()` | Removes all elements from the collection of descendants, leaving it empty. |
| `descendants()` | Returns an unmodifiable view of the collection of descendants. Changes to the collection held by the builder will be reflected in the view. |
| `setComparatorForDescendants(âComparator super String>Â comparator)` | *SortedSet only* A protected method that sets the [comparator] to keep the set elements ordered by. Must be called before any other accessor method for this property. Defaults to the [natural ordering] of the set's elements. |
```java
/** Returns a map of favourite albums by year. **/
Map albums();
```
A [Map][] property called 'albums' would generate:
| Method | Description |
|:------:| ----------- |
| `putAlbums(int key, String value)` | Associates `key` with `value` in albums. Throws a NullPointerException if either parameter is null. Replaces any existing entry. |
| `putAllAlbums(Map map)` | Associates all of `map`'s keys and values in albums. Throws a NullPointerException if the map is null or contains a null key or value. Replaces any existing mapping for all keys in `map`. |
| `removeAlbums(int key)` | Removes the mapping for `key` from albums. Throws a NullPointerException if the parameter is null. Does nothing if the key is not present. |
| `mutateAlbums(âConsumer