In the next post of "Code generator" series we will will talk about Immutables. This annotation processor based code generator allows you to generate simple, safe and consistent value objects, without the need to write Builders, factory methods and so on... It is easy to use, it allows customization, and all you need to do is to define your model value object as interface or abstract class.

To start using Immutables, all you need to do is to add it to your dependencies. For example with Maven project you will have:
<dependency>
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
<version>${immutables-value.version}</version>
<scope>provided</scope>
</dependency>

IDE configuration

Let's see what should be done in IntelliJ IDEA to make work with Immutables easier. First we need to make sure that Annotation Processors are enabled for your project. To do this go to File > Settings > Build, Execution, Deployment > Compiler > Annotation Processors and select your module/project where you want to enable annotation processing:

"Enable annotation processing" checkbox should be checked together with "Obtain annotation processors from project classpath" option (like on the screenshot above). If they are not selected - click them and save the config. After this generated classes will appear in target subfolder. To make them visible to you in the IDE open module settings:
Select your module, and make sure that folder that contains your generated code is marked as "Sources" and "Exclude" is removed from that folder (in our case it's target/generated-sources/annotations). If you don't do this - your project will compile and work fine with Maven but not in the IDE, as generated stuff will not be visible to it.

For Eclipse configuration you can see the documentation here.

Creating value objects

Finally! Let's start creating immutable value objects. For purposes of this post we will consider a Book value object example. We will have a Book written by the Author and identified by ISBN number. Let's start with the Author:
@Value.Immutable
public abstract class Author {
public abstract String getName();
public abstract String getSurname();
}
So we see that all we need to do is define an abstract accessors to properties that we'd like our object to have and mark the class itself with @Value.Immutable. After doing this you can build the project and implementation will be generated for you, so you can start using Author objects:
@Test
public void simpleTest() {
Author author = ImmutableAuthor.builder()
.name( "John" )
.surname( "Smith" )
.build();
assertThat( author )
.hasFieldOrPropertyWithValue( "name", "John" )
.hasFieldOrPropertyWithValue( "surname", "Smith" );
assertThat( author.toString() ).isEqualTo( "Author{name=John, surname=Smith}" );
}
You can see how builder is generated by Immutables. By default Immutables will make sure that passed values are not null:
/**
* Initializes the value for the {@link Author#getName() name} attribute.
* @param name The value for name
* @return {@code this} builder for use in a chained invocation
*/
public final Builder name(String name) {
this.name = Objects.requireNonNull(name, "name");
initBits &= ~INIT_BIT_NAME;
return this;
}
But what if you need more validations applied? It's possible by adding check methods annotated with @Value.Check. Let's take a look at ISBN to show this:
@Value.Immutable
public abstract class ISBN {
public abstract String getNumber();
@Value.Check
protected void check() {
Preconditions.checkState( getNumber() != null,
"'ISBN number' cannot be null"
);
Preconditions.checkState( getNumber().length() >= 10,
"'ISBN number' should have at least ten chars"
);
Preconditions.checkState( isValidISBN10( getNumber() ),
"'ISBN number' should be a valid ISBN number"
);
}
private static boolean isValidISBN10(final String isbn) {
String digits = isbn.replaceAll( "[^\\d]", "" );
if ( digits.length() != 10 ) {
return false;
}
int sum = 0;
for ( int i = 0; i < digits.length() - 1; i++ ) {
sum += ( digits.charAt( i ) - '0' ) * ( i + 1 );
}
char checkSum = digits.charAt( 9 );
return sum % 11 == ( checkSum == 'X' ? 10 : checkSum - '0' );
}
}
view raw ISBN.java hosted with ❤ by GitHub
So we created another abstract class and added check method annotated with @Value.Check, which contains different kinds of checks for ISBN number. We used AssertJ Precondition methods to make a couple of checks for number validity. Note that these checks will run when you will try to construct an object - so no invalid objects should be present in your application.
Now let's combine our ISBN and Author into a Book and perform some simple manipulations on the book instance.
@Value.Immutable
public interface Book {
ISBN getISBN();
String getTitle();
Author getAuthor();
}
view raw Book.java hosted with ❤ by GitHub
As you see immutable objects can be built not only from abstract classes but from interfaces as well. Generated classes also have some methods to create new objects from your immutables. Let's see some simple examples:
public class BookTest {
@Test
public void bookManipulations() throws Exception {
Book firstBook = ImmutableBook.builder()
.title( "Immutables in Java" )
.iSBN( ImmutableISBN.builder().number( "5-02-013850-9" ).build() )
.author(
ImmutableAuthor.builder()
.name( "John" )
.surname( "Smith" )
.build()
).build();
// creates a new book with same author and ISBN but new title
Book secondBook = ( (ImmutableBook) firstBook ).withTitle( "Immutables in Java. Second edition" );
// as the title is changed the books are different
assertThat( firstBook ).isNotEqualTo( secondBook );
// but author and ISBN are still equals
assertThat( firstBook.getAuthor() ).isEqualTo( secondBook.getAuthor() );
assertThat( firstBook.getISBN() ).isEqualTo( secondBook.getISBN() );
// but if you try to use the same value - you'll receive the same object:
assertThat( firstBook ).isEqualTo( ( (ImmutableBook) firstBook ).withTitle( "Immutables in Java" ) );
}
}
view raw BookTest.java hosted with ❤ by GitHub
So we see that using Immutables allows us to save some time, as we don't need to write builders, over and over again, for each immutable object that we add, and we don't need to have properties and huge constructors, but just a list of accessor methods.
All the code from this post can be found on GitHub.

To be continued...