Quarkus: как изменить метод с императивного на реактивный

Я создаю небольшой Rest API, чтобы больше узнать о фреймворке Quarkus. Теперь я хотел бы начать использовать фреймворк с его реактивным API, но мне сложно понять некоторые концепции. В настоящее время проект использует RESTEasy Reactive с Jackson, Hibernate Reactive с Panache и Postgresql Reactive Client.

Это мои занятия

      @Table(name = "cat_role")
@Entity
public class Role extends PanacheEntityBase {
    private static final long serialVersionUID = -2246110460374253942L;

    @Id
    @Column(name = "id", nullable = false, updatable = false)
    @GeneratedValue
    public UUID id;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "name", nullable = false, length = 18)
    public UserRole name;

    public enum UserRole {
        Administrador, Asesor_Empresarial, Asesor_Academico, Alumno
    }
    
}

Сейчас в моем сервисе (обязательно) делаю следующее:

Role.class

          public static Boolean existsRoleSeed(){
        return Role.count() > 0;
    }

RoleService.class

          @Transactional
    public void seedRoles() {
        if (!Role.existsRoleSeed()) {
            for(Role.UserRole userRole: Role.UserRole.values()){
                Role role = Role.builder()
                        .name(userRole)
                        .build();
                
                role.persist();
            }
        }
    }

Это, очевидно, зарегистрирует все роли из перечисления UserRole в базе данных, и оно будет работать правильно. Я пытаюсь воспроизвести этот метод, но с использованием реактивной формы. Это изменения, которые я внес в код

Role.class

          public static Uni<Boolean> existsRoleSeed() {
        return Role.count().map(x -> x > 0);
    }

RoleService.class

          @ReactiveTransactional
    public void seedRoles() {
        Role.existsRoleSeed()
                .map(exists -> {
                    if (!exists) {
                        Multi.createFrom()
                                .iterable(Arrays
                                        .stream(Role.UserRole.values())
                                        .map(userRole -> Role.builder()
                                                .name(userRole)
                                                .build())
                                        .collect(Collectors.toList()))
                                .map(role -> role.persistAndFlush())
                                .subscribe().with(item -> LOGGER.info("Something happened"), failure -> LOGGER.info("Something bad happened"));
                    }
                    return null;
                }).subscribe().with(o -> {
                });
    }

Когда я запускаю приложение, оно не выдает ошибок, журналы показывают, что что-то произошло, база данных создает таблицу, но ничего не вставляет. Я пробовал по-разному, но заставить работать так, как я надеюсь, не получилось.

2 ответа

Решение

Основываясь на ответе @Haroon и комментарии @Clement, я сделал следующее

  • Удален @ReactiveTransactional, поскольку мой метод возвращает void и не находится на границе REST
  • Когда я удалил аннотацию, мне нужно использовать метод Panache.withTransaction
  • И, наконец, в методе я подписался на мульти

Одно замечание: я изменил transformToUniAndMerge с ответа @Haroon на transformToUniAndConcatenate, чтобы сохранить порядок ролей.

      public void seedRoles() {
        Role.existsRoleSeed()
                .onItem().transformToMulti(exists -> {
                    if (!exists) {
                        return Multi.createFrom().items(Role.UserRole.values());
                    } else {
                        return Multi.createFrom().nothing();
                    }
                })
                .map(userRole -> Role.builder().name(userRole).build())
                .onItem().transformToUniAndConcatenate(role -> Panache.withTransaction(role::persist))
                .subscribe().with(subscription -> LOGGER.infov("Persisting: {0}", subscription));
    }

Не тестировал это. Но это должно дать вам какое-то представление.

      Multi<Role> savedRoles = Role.existsRoleSeed()
                                .onItem().transformToMulti(exists -> {
                                    if (!exists) {
                                        return Multi.createFrom().items(Role.UserRole.values());
                                    }
                                    return Multi.createFrom().nothing();
                                })
                                .map(userRole -> Role.builder().name(userRole).build())
                                .onItem().transformToUniAndMerge(role -> Panache.<Role>withTransaction(role::persist));

Другие вопросы по тегам