https://github.com/victorhsr/hermes-builder
A library that automates the creation of fluent object builders and DSL in Java
https://github.com/victorhsr/hermes-builder
annotation-processing domain-specific-language dsl java kotlin maven
Last synced: 4 months ago
JSON representation
A library that automates the creation of fluent object builders and DSL in Java
- Host: GitHub
- URL: https://github.com/victorhsr/hermes-builder
- Owner: victorhsr
- License: mit
- Created: 2022-11-14T01:57:35.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2025-01-20T02:03:51.000Z (about 1 year ago)
- Last Synced: 2025-02-01T11:34:55.930Z (about 1 year ago)
- Topics: annotation-processing, domain-specific-language, dsl, java, kotlin, maven
- Language: Kotlin
- Homepage:
- Size: 74.2 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Hermes Builder
[](https://github.com/victorhsr/hermes-builder/actions?query=workflow%3A"Maven+Build")
[](https://coveralls.io/github/victorhsr/hermes-builder)
[](https://opensource.org/licenses/mit)
[](https://jitpack.io/#victorhsr/hermes-builder)
Hermes is a library designed to streamline the generation of fluent object builders for your Java classes. Employing a declarative approach, it produces a straightforward Domain Specific Language (DSL) to facilitate the construction of object instances.
## Adding Hermes to your pom file
```xml
jitpack.io
https://jitpack.io
com.github.victorhsr
hermes-builder
1.1.0-beta
```
## Usage
Suppose we have classes `Person`, `Address` and `MetaDataWrapper` annotated with `@DSLRoot` and `@DSLProperty`:
```Java
@DSLRoot
public class Person {
private String name;
private Integer age;
private Address address;
@DSLProperty("metaData")
private MetaDataWrapper metaDataWrapper;
// getters and setters...
}
@DSLRoot
public class Address {
private String street;
private Integer houseNumber;
// getters and setters...
}
@DSLRoot
public class MetaDataWrapper {
private K key;
private V value;
// getters and setters...
}
```
Once you compile your project, the library will generate the classes `PersonDSL`, `AddressDSL` and `MataDataWrapperDSL` which are the builders. With it we can succinctly create an instance of `Person`:
```Java
Person personFromDsl =
person(
name("Victor"),
age(99),
address(
street("Foo street"),
houseNumber(99)
),
metaData(
key("LAST_LOGIN"),
value("01-01-2024")
)
);
````
Note that there's no need to instantiate `Address` or `MetaDataWrapper`, and more descriptive names for Person's fields can be used. All the building methods are static methods and high order functions.
## Annotations
- **@DSLRoot** - Indicates the intention to create a builder for the annotated class;
- **@DSLProperty** - Customizes the method name generated for a specific field. The default is the original field name;
- **@DSLIgnore** - Marks a field to be excluded when generating DSL code;
## Prerequisites
The Hermes builder requires elements annotated with **@DSLRoot** to have a public default constructor. Only attributes with a public setter method will have a higher-order function created.
## Lombok Support
The Hermes builder is compatible with the Lombok plugin. It recognizes the **@Data** and **@Setter** annotations from Lombok and uses their generated methods to compose the sources generated by Hermes Builder.
# Comparison with Traditional Java Classes
The equivalent implementation in traditional Java code involves a considerable amount of boilerplate:
```Java
private Person buildPerson() {
Person person = new Person();
person.setAge(99);
person.setName("Victor");
person.setAddress(buildAddress());
person.setMetaDataWrapper(buildMetaDataWrapper());
return person;
}
private MetaDataWrapper buildMetaDataWrapper() {
MetaDataWrapper metaData = new MetaDataWrapper<>();
metaData.setKey("LAST_LOGIN");
metaData.setValue("01-01-2024");
return characteristics;
}
private Address buildAddress() {
Address address = new Address();
address.setHouseNumber(99);
address.setStreet("Foo street");
return address;
}
```
That's a lot of code, almost twice the lines of our previous implementation. The Hermes Builder significantly reduces this boilerplate, providing a more concise and readable alternative.
# Using Lombok for comparison
An alternative approach using Lombok involves a cleaner syntax but may lack readability and customization
```Java
public Person buildPerson() {
return Person.builder()
.name("Victor")
.age(99)
.address(buildAddress())
.setMetaDataWrapper(buildMetaDataWrapper())
.build();
}
private MetaDataWrapper buildMetaDataWrapper() {
return MetaDataWrapper
.builder()
.key("LAST_LOGIN")
.value("01-01-2024")
.build()
}
private Address buildAddress() {
return Address.builder()
.houseNumber(99)
.street("Foo street")
.build()
}
```
In summary, the Hermes Builder strikes a balance between conciseness and customization, offering a powerful solution for building objects in a declarative manner.