やあ、
これまで、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
さまざまな方法でコードをリファクタリングしようとしましたが、実行に成功しませんでした。
正しく行う方法を教えてください。
ありがとう。
やあ、
セッションの問題は、スレッドセーフではないことです。別のスレッドでセッションを使用すると、デバッグが難しい問題が発生する可能性があります。 また、新しいセッションが作成されると、Vert.xコンテキストにバインドされ、その後は同じコンテキストで使用する必要があります。
これは通常、 SessionFactory#withTransaction
とSessionFactory#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サービスを作成することです。
このサービスは、セッションの作成時に使用する正しい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メカニズムを使用して定義することもできます。
org.hibernate.reactive.vertx.VertxInstance
という名前のテキストファイルを下に追加します
/META-INF/services/
VertxInstance
インターフェイスを実装するクラスへのパスが含まれます。
org.myproject.MyVertxProvider
これで、HibernateReactiveはVert.xインスタンスが必要なときにMyVertxProvider
インスタンスを呼び出し、コードが同じVert.xコンテキストで実行される場合、すべてが機能するはずです。
テストに戻ると、それらを修正する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ご説明
@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();
最も参考になるコメント
はい、そうします