hare-dev
hare-dev

Reputation: 3

How to map left side of Either with two different types erros with Validation and DomainError

I need help with Vavr in Java. I have a business process to update a book entity and I want to make validations before every update.

Steps:

  1. Request from RestController with Data to make Update as BookUpdateDto.
  2. Try to find BookById; return Book if exists or return Either with BOOK_NOT_FOUND.
  3. I make mapping from BookUpdateDto to BookCreateDto and validate.
  4. My validation return Validation<Seq<String>, BookCreateDto> and that's my problem.
  5. My question is: How I could pack my errors from validation with business error when a book does not exist?
public Either<BookError, BookCreateDto> updateBookById(final Long bookId, final BookUpdateDto toUpdate) {
        return findBookById(bookId)
                .toEither(BOOK_NOT_FOUND)
                .map(Book::response)
                .map(bookValidation::validate)
                
     

                .map(book -> book.mapToUpdate(toUpdate))
                .map(book -> book.update(toUpdate))
                .map(book -> bookRepository.save(book).response());
    }

I do not know how to map my errors from validation and domain error that BOOK_NOT_FOUND in empty space in code. Or maybe my architecture to solve my problem is wrong.

Upvotes: 0

Views: 182

Answers (2)

hare-dev
hare-dev

Reputation: 3

It looks great, but my BookError is enum with message error and http code. I will try to solve it. Thank you so much!

Upvotes: 0

Hinse ter Schuur
Hinse ter Schuur

Reputation: 390

It looks like Validation.toEither combined with a flatMap could do the trick.

The toEither changes the Validation into an Either<List<String>, BookCreateDto> and the mapLeft on that either changes the left side of the either from List<String> to a BookError.

public Either<BookError, BookCreateDto> updateBookById(final Long bookId, final BookUpdateDto toUpdate) {
    return findBookById(bookId)
        .toEither(BOOK_NOT_FOUND)
        .map(Book::response)
        .map(bookValidation::validate)

        // This should perform the desired conversion
        .flatMap(validation -> validation.toEither().mapLeft(this::validationErrorsToBookError))

        .map(book -> book.mapToUpdate(toUpdate))
        .map(book -> book.update(toUpdate))
        .map(book -> bookRepository.save(book).response());
}

The validationErrorsToBookError would be a function that is responsible for turning a list of validations into a BookError. Probably something along these lines:

BookError validationErrorsToBookError(Seq<String> validationErrors) {
    // Use logic that would fit your specific needs for BookErrors
    return new BookError(validationErrors.mkString(";"));
}

Upvotes: 0

Related Questions