Hibernate-reactive: openSession()はエラー「これはVert.xイベントループで実行する必要があります」を返します

作成日 2021年05月12日  ·  7コメント  ·  ソース: hibernate/hibernate-reactive

やあ、

これまで、HibernateリアクティブAPI(1.0.0.CR4)を使用している間、Vertxは単に私から隠されていました。 ただし、このAPIを使用するクライアントがセッションを閉じることを決定するまで開いたままになるセッションを返すには、APIを公開する必要があります。
JUnitテストを実行していて、次のAPIがあります。

    public Stage.Session openSession() throws ExecutionException, InterruptedException {
        if (session != null && session.isOpen()) {
            session.close();
        }
        Stage.Session newSession = sessionFactory.openSession();
        this.session = newSession;
        return newSession ;
   }

そして私のjunitテストでは:
Stage.Session session = deviceRepository.openSession();
コードを実行すると、次のエラーが発生しました。
This needs to be run on the Vert.x event loop
さまざまな方法でコードをリファクタリングしようとしましたが、実行に成功しませんでした。

正しく行う方法を教えてください。

ありがとう。

最も参考になるコメント

はい、そうします

全てのコメント7件

やあ、
セッションの問題は、スレッドセーフではないことです。別のスレッドでセッションを使用すると、デバッグが難しい問題が発生する可能性があります。 また、新しいセッションが作成されると、Vert.xコンテキストにバインドされ、その後は同じコンテキストで使用する必要があります。

これは通常、 SessionFactory#withTransactionSessionFactory#withSession使用するときに、HibernateReactiveによって処理されます。

テストは、Vert.xスレッドではなくJUnitスレッドで実行されるため、機能していません。
JUnit 4でこの問題を解決する1つの方法は、ライブラリio.vertx:vertx-unit:4.0.3含まれているルールを使用することです。

<strong i="13">@Rule</strong>
public RunTestOnContext vertxContextRule = new RunTestOnContext();

これにより、テストがVert.xコンテキストで実行されるようになります

ただし、これだけでは不十分です。また、セッションがルールで定義されているのと同じVert.xコンテキストにバインドされていることを確認する必要があります。

VertxInstanceサービス:

一般に、これを実現する方法は、カスタムVertxInstanceサービスを作成することです。

このサービスは、セッションの作成時に使用する正しいVert.xインスタンスを取得する方法をHibernateReactiveに指示します。
プログラムでSessionFactoryを作成する場合、その方法の例を次に示します。

Configuration configuration = new Configuration();
StandardServiceRegistryBuilder builder = new ReactiveServiceRegistryBuilder()
                .addService( VertxInstance.class, (VertxInstance) () -> getMyVertxInstance())
                .applySettings( configuration.getProperties() );
StandardServiceRegistry registry = builder.build();
SessionFactory sessionFactory = configuration.buildSessionFactory( registry );

または、 JDKのServiceLoaderメカニズムを使用して定義することもできます。

  1. org.hibernate.reactive.vertx.VertxInstanceという名前のテキストファイルを下に追加します
    /META-INF/services/
  2. テキストファイルには、 VertxInstanceインターフェイスを実装するクラスへのパスが含まれます。
    org.myproject.MyVertxProvider

これで、HibernateReactiveはVert.xインスタンスが必要なときにMyVertxProviderインスタンスを呼び出し、コードが同じVert.xコンテキストで実行される場合、すべてが機能するはずです。

JUnit 4の問題の修正:

テストに戻ると、それらを修正する1つの方法は次のとおりです。

<strong i="41">@Rule</strong>
public RunTestOnContext vertxContextRule = new RunTestOnContext();

...

Configuration configuration = new Configuration();
StandardServiceRegistryBuilder builder = new ReactiveServiceRegistryBuilder()
                .addService( VertxInstance.class, (VertxInstance) () -> vertxContextRule.vertx() )
                .applySettings( configuration.getProperties() );
SessionFactory sessionFactory = configuration.buildSessionFactory(  builder.build() );

ルールを使用していない場合は、次の方法で特定のVert.xコンテキストでコードを実行できます。

Context currentContext = Vertx.currentContext();
currentContext.runOnContext( event -> {
   // Here you should be able to use the session
});

あなたは今書いたものをFAQとしてウェブサイトやどこにでも追加するべきです。

はい、そうします

@DavideDご説明

ドキュメント/ウェブサイトへのこれらの変更を追跡するための問題を作成しました: https

この問題を解決します。 他に不明な点がある場合は、遠慮なく質問してください。

ありがとうございました。

@DavideD JUnit 5で前述した次のコードを使用することは可能ですか?

Context currentContext = Vertx.currentContext();
currentContext.runOnContext( event -> {
   // Here you should be able to use the session
});

はい、そのコードはVert.xであり、JUnitではありません。

ただし、ここでは、JUnit5の

<strong i="8">@Rule</strong>
public RunTestOnContext vertxContextRule = new RunTestOnContext();
このページは役に立ちましたか?
0 / 5 - 0 評価