Совместимость между инъекциями в командах Picocli и микронавтом - PullRequest
1 голос
/ 24 июня 2019

Определение bean-компонента @Singleton в Micronaut не приводит к внедрению одного и того же экземпляра в команды Picocli.

Micronaut предлагает интеграцию с Picocli . Кажется, что важно сделать то, что с помощью команды Picocli можно запустить EmbeddedServer от Micronaut (может быть, проблема уже в том, что Micronaut запускается только из Picocli?). Когда я определяю класс как синглтон через @Singleton и @Inject его как в конечной точке отдыха Micronaut, так и в команде Picocli, он замечает, что это два разных экземпляра, и состояние не одно и то же. Что мне необходимо, это перенести некоторое состояние, предоставляемое через интерфейс командной строки, для настройки бэкэнда / Rest-службы. На данный момент я только что создал статический экземпляр для совместного использования этого состояния, но мне интересно, смогу ли я заставить инъекцию зависимости работать должным образом между Picocli и Micronaut.

@Singleton
public class SharedState {
    private int num;

    public void setNum(int num) { this.num = num };
    public int getNum() { return this.num; };
}

@Command(name = "ui", description = "...", mixinStandardHelpOptions = true)
public class UICommand implements Runnable {

    @Inject
    SharedState state;

    public static void main(String[] args) throws Exception {
        PicocliRunner.run(UICommand.class, args);
    }

    public void run() {
        EmbeddedServer server = ApplicationContext.run(EmbeddedServer.class);
        state.setNum(42);
    }
}

@Controller("/rest")
public class RestResource{

    @Inject
    SharedState state;

    @Get
    public String get() {
        return state.getNum();
    }
}

Если я установлю какое-либо состояние в экземпляре SharedState в методе run () - UICommand, я ожидаю, что смогу прочитать его из RestResource. Таким образом, я ожидал бы получить обратно «42», когда позвоню в конечную точку отдыха.

Есть ли способ каким-либо образом настроить Micronaut / Picocli, чтобы контейнер с инжекцией зависимостей в Micronaut / Picocli запускался раньше и использовался совместно? Или Micronaut действительно только запускается с помощью вызова EmbeddedServer? В таком случае, какие варианты у меня еще должны быть, чтобы у меня была совместимость? Могу ли я каким-то образом явно запросить у контейнера Micronaut DI экземпляр

1 Ответ

1 голос
/ 25 июня 2019

Я считаю, что проблема в том, что код в вопросе создает два отдельных ApplicationContext экземпляра.

При вызове PicocliRunner.run(UICommand.class, args) под капотом создается ApplicationContext , в то время какUICommand.run вызов метода ApplicationContext.run(EmbeddedServer.class), который запускает другой экземпляр ApplicationContext.

Одним из способов решения этой проблемы может быть внедрение ApplicationContext вместо запуска нового:

@Command(name = "ui", description = "...", mixinStandardHelpOptions = true)
public class UICommand implements Runnable {

    @Inject
    SharedState state;

    @Inject
    ApplicationContext appContext;

    public static void main(String[] args) throws Exception {
        PicocliRunner.run(UICommand.class, args);
    }

    public void run() {
        // start the injected, shared, application context (not a new instance)
        if (!appContext.isRunning()) { // future versions of PicocliRunner may start the context
            appContext.start();
        }

        // start the embedded server
        EmbeddedServer server = appContext.getBean(EmbeddedServer.class);
        if (!server.isRunning()) {
            server.start();
        }
        state.setNum(42);
    }
}
...