Внедрить бобы в RevisionListener Envers (Micronaut) - PullRequest
0 голосов
/ 20 апреля 2020

Я настраиваю Micronaut, Hibernate и Envers. Я понимаю, что RevisionListener Envers имеет жизненный цикл, отличный от bean-компонентов Micronaut, так как я могу получить дескриптор текущего пользователя от слушателя?

До сих пор я пытался ввести бины напрямую (пример ниже), вводя то же самое bean-компоненты в класс c (например, с Spring ), используя BeanContext.run().findBean(Class) или даже ApplicationContext.build().start().getBean(Class), но ни один из них не работает.

Поддерживается ли это даже?

package my.app.domain.revisions;

import io.micronaut.security.utils.SecurityService;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.NoArgsConstructor;
import org.hibernate.envers.RevisionListener;

@NoArgsConstructor
@Singleton
public class CustomRevisionListener implements RevisionListener {

    @Inject
    private transient SecurityService security;

    @Override
    public final void newRevision(final Object revision) {
        // FIXME security is null
        if (!this.security.username().isPresent()) {
            throw new IllegalStateException("Unauthorized request");
        }
        final CustomRevision entity = (CustomRevision) revision;
        entity.setTimestamp(System.nanoTime());
        entity.setUser(this.security.username().get());
    }
}

1 Ответ

0 голосов
/ 21 апреля 2020

Я публикую ответ на тот случай, если кто-то ищет то же самое. Основываясь на этом разговоре в чате Micronaut, приведенное ниже решение работает, за исключением запуска тестов:

CustomRevisionListener. java

package my.app.domain.revisions;

import io.micronaut.security.utils.SecurityService;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.NoArgsConstructor;
import my.app.Application;
import org.hibernate.envers.RevisionListener;

@NoArgsConstructor
@Singleton
public class CustomRevisionListener implements RevisionListener {

    private transient SecurityService security;

    @Override
    public final void newRevision(final Object revision) {
        if (this.security == null) {
            this.security = Application.context.getBean(SecurityService.class);
        }
        if (!this.security.username().isPresent()) {
            throw new IllegalStateException("Unauthorized request");
        }
        final CustomRevision entity = (CustomRevision) revision;
        entity.setTimestamp(System.nanoTime());
        entity.setUser(this.security.username().get());
    }
}

Приложение. java

...
public final class Application {

    ...

    public static ApplicationContext context;

    public static void main(String... args) {
        Application.context = Micronaut.run(Application.class);
    }

    ...

}

ОБНОВЛЕНИЕ : Другое решение состоит в том, чтобы использовать другой компонент и ввести туда ApplicationContext. Затем при запуске приложения обновите поле stati c с введенным bean-компонентом:

package my.package;

import io.micronaut.context.ApplicationContext;
import io.micronaut.context.event.StartupEvent;
import io.micronaut.runtime.event.annotation.EventListener;
import java.io.IOException;
import javax.inject.Singleton;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Singleton
public final class ApplicationStartup {

    @Getter
    private static ApplicationContext context;

    private final transient ApplicationContext appContext;

    @EventListener
    void onStartup(final StartupEvent event) throws IOException {
        ApplicationStartup.context = this.appContext;
    }

}

Вот как вы должны его использовать: ApplicationStartup.getContext(). Я не проверял это в тестовой среде, но думаю, что это должно работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...