- Notifications
You must be signed in to change notification settings - Fork0
Example Spring Boot application that demonstrates how to use Immutables with MapStruct in an almost real life scenario.
License
petitcl/spring-boot-mongo-immutables-demo
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This repository contains a sample Spring Boot projectthat demonstrates how to use immutables objects withimmutablesin an almost real life scenario.
This project is made with the following technologies:
- Spring Boot
- Spring Boot WebFlux
- Spring Boot Data Mongo Reactive
- Immutables (for immutable classes)
- lombok (for non immutable classes)
- MapStruct (for bean mapping)
The application is a simple JSON REST API that manages a list of books, authors and categories.The exposed routes are as follows:
GET /books=> find all booksGET /books/:id=> find book with id:idPOST /books=> create a bookGET /categories=> find all categoriesGET /categories/:id=> find category with id:idPOST /categories=> create a categoryGET /authors=> find all authorsGET /authors/:id=> find author with id:idPOST /authors=> create an author
The server offers the classic features of a real life application such as JSON serialization / deserialization,validation, business logic, storing data in a database (here mongodb) and unit testing.
In order to run the project, you will need a running mongodb instance on port27017.You can use you own mongodb server or simply run a dockerised version withdocker run -p 27017:27017 mongo:4.0-xenial.
The command to run the server is:mvn spring-boot:run. The server will listen on port8080
Here are some insights learned during the development of this demo application:
- Immutables will throw an error if a mandatory field is null during object initialization.This forces the developer to think about fields nullability,and it helps preventing them to create half initialized objects.
- DTO (Data Transfer Objects) can be immutables objects. There are however some gotchas to be aware of:
- It is not needed to annotate it with
JsonSerializenorJsonProperty;Jackson is clever enough to figure out the field names, based on beans names convention. - Given than an immutable object is self validating, it means that this validation can conflictwith a classic validation framework like javax validation.A solution is to annotate the DTO immutable class with
@Value.Style(validationMethod = Value.Style.ValidationMethod.NONE)in order to let javax validation take place.
- It is not needed to annotate it with
- Spring Data Mongodb can handle immutables objects. However, there are a some gotchas to be aware of(A complete meta annotation example that handles most of the points mentioned below can be found inImmutableMongoEntity.java):
- The
_idproperty that cannot be known during insertion, which can conflict with the null checks of immutablesif the_idproperty is mandatory. This means that a workaround must be implemented for that:- either annotate the id field with
@Nullable - or set the id field to be an
ObjectIdwith a default value ofObjectId.new()
- either annotate the id field with
- Spring Data is not able to find on its own the constructor / factory generated by Immutables.It is therefore necessary to create an annotation with
@InjectAnnotationthat will inject the@PersistenceConstructorannotation on the generated constructor.It is also needed to tell immutables to generate a constructor instead of a factory.This is done by adding the@Value.Style(of = "new", allParameters = true)annotation to the entity type. - If Guava is on classpath, collections fields will be generated as immutable guava collections.However, Spring Data does not handle guava collections(spring-data-commons/1817).This means the guava integration must be deactivated specifically for entitiy classes.This is easily done by adding
@Value.Style(jdkOnly = true)annotation to the entity. - If
Optional<T>are used, this might cause an incompatibility with immutables during deserialization.For that, it is necessary to add@Value.Style(optionalAcceptNullable = true). - There seem to be an issue with
ReactiveMongoRepository#saveAll(Publisher<T>):the returned entities do not have their_idproperty set (TODO open issue ?).
- The
About
Example Spring Boot application that demonstrates how to use Immutables with MapStruct in an almost real life scenario.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.