Skip to content

Latest commit

 

History

History
156 lines (124 loc) · 4.41 KB

README.md

File metadata and controls

156 lines (124 loc) · 4.41 KB

Java records as DTOs

This is not production-ready code.

I created this code only for demonstrational purposes.

This project demonstrates one more way of using records as DTOs (data transfer objects).
It utilizes an in-memory H2 database (so no additional DB services are required), Spring Boot and Hibernate frameworks.

Entities:

  • Tag
  • Note

DTOs:

  • TagDto
  • NoteDto

Content objects:

  • TagContent
  • NoteContent

Models are used only within the service layer.
The service layer consumes/produces DTOs and content objects.
The content objects are purposed to transfer an object's content (like tag color and name).
DTOs and content objects are immutable Java records.

To demonstrate the process, I created very simple REST controllers (NoteController and TagController). For example:

    @PutMapping(PREFIX + VERSION + "/tags/{id}")
    TagDto updateTagContent(@PathVariable long id, @RequestBody TagContent content) {
        TagDto tag = tagService.getTagById(id).orElseThrow(() -> new NoSuchItemException("tag " + id));
        return tagService.updateTagContent(tag, content).orElseThrow(() -> new NotUpdatedException("tag " + id));
    }

Here is the service method:

    @Transactional
    public Optional<TagDto> updateTagContent(TagDto tag, TagContent content) {
        return Functions.checkTagDto.apply(tag)
                .flatMap(t -> repository.getTagById(t.id()))
                .flatMap(t -> setTagNameAndColor(t, content.name(), content.color()))
                .map(repository::saveAndFlush)
                .flatMap(t -> repository.findById(t.getId()));
    }

A DTO is received, checked, and "transformed" into a model. Then, the model properties are updated. After that, an updated DTO is fetched and returned.

Here is the corresponding repository method:

    @QueryHints(value = {
            @QueryHint(name = READ_ONLY, value = "true")
    })
    @Transactional(readOnly = true)
    @Query(value = "SELECT new dev.isdn.demo.records_dto.app.domain.tag.TagDto(t.id, t.name, t.color) FROM tags t WHERE t.id = :id")
    Optional<TagDto> findById(@Param("id") long id);

So, there is no need for special "mapper" functions to convert DTOs/models.

Build and run
mvn clean test
mvn clean package -DskipTests
java --enable-preview -jar target/records-dto-demo-0.1.jar

or

mvn clean spring-boot:run
Operations

List of notes:

curl -i http://127.0.0.1:8080/v1/notes

Create notes:

curl -i -H 'Content-type:application/json' -d '{"content":"test"}' -X POST http://127.0.0.1:8080/v1/notes
curl -i -H 'Content-type:application/json' -d '{"content":"another test"}' -X POST http://127.0.0.1:8080/v1/notes
curl -i -H 'Content-type:application/json' -d '{"content":""}' -X POST http://127.0.0.1:8080/v1/notes

Delete a note:

curl -i -X DELETE http://127.0.0.1:8080/v1/notes/766714176451034115

Get a note:

curl -i http://127.0.0.1:8080/v1/notes/2119985630772393670

Update a note:

curl -i -H 'Content-type:application/json' -d '{"content":"test updated"}' -X PUT http://127.0.0.1:8080/v1/notes/8465407150649195493

Get note tags:

curl -i http://127.0.0.1:8080/v1/notes/8465407150649195493/tags

List of tags:

curl -i http://127.0.0.1:8080/v1/tags

Create tags:

curl -i -H 'Content-type:application/json' -d '{"name":"test1", "color":"ffffff"}' -X POST http://127.0.0.1:8080/v1/tags
curl -i -H 'Content-type:application/json' -d '{"name":"test2"}' -X POST http://127.0.0.1:8080/v1/tags
curl -i -H 'Content-type:application/json' -d '{"name":"test3"}' -X POST http://127.0.0.1:8080/v1/tags

Delete a tag:

curl -i -X DELETE http://127.0.0.1:8080/v1/tags/614426635004842295

Get a tag:

curl -i http://127.0.0.1:8080/v1/tags/4760561560720237306

Update a tag:

curl -i -H 'Content-type:application/json' -d '{"name":"test3_updated", "color": "AAaaAA"}' -X PUT http://127.0.0.1:8080/v1/tags/4760561560720237306

Get tag notes:

curl -i http://127.0.0.1:8080/v1/tags/4760561560720237306/notes

Add tags to a note:

curl -i -X PUT http://127.0.0.1:8080/v1/notes/8465407150649195493/tags/4760561560720237306
curl -i -X PUT http://127.0.0.1:8080/v1/notes/8465407150649195493/tags/362170154209224171

Delete a tag from a note:

curl -i -X DELETE http://127.0.0.1:8080/v1/notes/8465407150649195493/tags/362170154209224171