Skip to content

Marthym/entity

Entity GitHub license

Quality Gate Status Coverage Maintainability Rating

Size Limit CLI

Entity is a small library that handles the notion of model entity. Entity offers an elegant way of working with business objects that may or may not have an identifier.

The entity can hold, or not, some metadata. For example ID of the user who creates the entity, the date of creation, the last update, ... This metadata was embedded through an EnumMap, the most efficient structure to store unknown number of key/value pairs.

The jackson package offers a module for serializing and deserializing these entities in a flat manner.

Features

  • 🪪 Identifiable entity
  • 🏷️ Metadata embedded in the entity
  • 🎷 Jackson 2 & 3 module
  • 🫟 GraphQL module

Installation

Use the package manager maven to install entity.

<dependency>
    <groupId>fr.ght1pc9kc</groupId>
    <artifactId>entity-api</artifactId>
    <version>VERSION</version>
</dependency>
<dependency>
    <groupId>fr.ght1pc9kc</groupId>
    <artifactId>entity-jackson</artifactId>
    <version>VERSION</version>
</dependency>
<dependency> <!-- Jackson & Jackson 3 modules are exclusive -->
    <groupId>fr.ght1pc9kc</groupId>
    <artifactId>entity-jackson-3</artifactId>
    <version>VERSION</version>
</dependency>
<dependency>
    <groupId>fr.ght1pc9kc</groupId>
    <artifactId>entity-graphql</artifactId>
    <version>VERSION</version>
</dependency>

for gradle

compile "fr.ght1pc9kc:entity-api:VERSION"
compile "fr.ght1pc9kc:entity-jackson:VERSION"
compile "fr.ght1pc9kc:entity-jackson-3:VERSION"
compile "fr.ght1pc9kc:entity-graphql:VERSION"

Usage

Create an entity

import fr.ght1pc9kc.entity.api.Entity;

import java.time.Instant;

import static fr.ght1pc9kc.demo.DefaultMeta.createdBy;
import static fr.ght1pc9kc.demo.DefaultMeta.createdAt;

Entity<String> basic = Entity.identify("May the force")
        .withId("4TH");

Entity<String> simple = Entity.identify("May the force")
        .meta(createdBy, "Yoda")
        .meta(createdAt, Instant.now())
        .withId("4TH");

Entity<String> verySimple = Entity.identify("May the force").withId("4TH");

Entity<Saber> POLYMORPHIC_ENTITY = Entity
        .<Saber>identify(new LightSaber(Color.GREEN, 1))
        .meta(createdAt, Instant.parse("2024-01-20T15:06:42.546Z"))
        .meta(createdBy, "okenobi")
        .withId("LIGHTSABER");

Include Jackson 2 module

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import fr.ght1pc9kc.entity.jackson.EntityModule;

ObjectMapper mapper = new ObjectMapper()
        .registerModule(new JavaTimeModule())
        .registerModule(new EntityModule())
        .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

Using JavaTimeModule is mandatory to allow serialize Instant, WRITE_DATES_AS_TIMESTAMPS is optional but provide more beautiful json.

{
  "_id": "LIGHTSABER",
  "_createdAt": "2024-01-20T15:06:42.546Z",
  "_createdBy": "okenobi",
  "@type": "LIGHT",
  "blade": 1,
  "color": "GREEN"
}

Include Jackson 3 module

import tools.jackson.databind.ObjectMapper;
import tools.jackson.databind.cfg.DateTimeFeature;
import tools.jackson.databind.json.JsonMapper;
import fr.ght1pc9kc.entity.jackson.EntityModule;

ObjectMapper mapper = JsonMapper.builder()
        .disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
        .addModule(new EntityModule())
        .build();

Since jackson 3, JavaTimeModule is built-in and does not need to be registered.

{
  "_id": "LIGHTSABER",
  "_createdAt": "2024-01-20T15:06:42.546Z",
  "_createdBy": "okenobi",
  "@type": "LIGHT",
  "blade": 1,
  "color": "GREEN"
}

Use GraphQL DataFetcher module

In Spring Boot, create a configuration class into your module

@Slf4j
@Configuration
public class MyObjectEntityConfiguration {
    @Bean
    public RuntimeWiringConfigurer customRuntimeWiringConfigurer() {
        // Create the DataFetcher with the default EntityDataFetcher using simple reflection
        DataFetcher<Object> dataFetcher = EntityDataFetcher.builder().build();
        // Create a TypeResolver which detect Entity object
        TypeResolver typeResolver = new EntityTypeResolver();

        // customize WiringConfigurer to map possible Entity self object to use EntityDataFetcher
        return wiringBuilder -> wiringBuilder
                .type(MyObject.class.getSimpleName(), builder -> builder.defaultDataFetcher(dataFetcher).typeResolver(typeResolver));
    }
}
@Slf4j
@Configuration
public class MyObjectEntityConfiguration {
    @Bean
    public RuntimeWiringConfigurer customRuntimeWiringConfigurer(ObjectMapper mapper) {
        // Create the DataFetcher with Jackson ObjectMapper
        DataFetcher<Object> dataFetcher = EntityDataFetcher.builder()
                .mapper(mapper) // Jackaon 2 or 3 depending on the dependency you choose
                .build();
        // Create a TypeResolver which detect Entity object
        TypeResolver typeResolver = new EntityTypeResolver();

        // customize WiringConfigurer to map possible Entity self object to use EntityDataFetcher
        return wiringBuilder -> wiringBuilder
                .type(MyObject.class.getSimpleName(), builder -> builder.defaultDataFetcher(dataFetcher).typeResolver(typeResolver));
    }
}

You can use your own EntityMapper to customize the way the entity is serialized to graphql.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

MIT

About

Entity is a small library that handles the notion of model entity.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Languages