Hibernate-reactive: openSession() mengembalikan kesalahan "Ini harus dijalankan pada loop acara Vert.x"

Dibuat pada 12 Mei 2021  ·  7Komentar  ·  Sumber: hibernate/hibernate-reactive

Hai,

sampai sekarang Vertx disembunyikan dari saya saat menggunakan API reaktif Hibernate (1.0.0.CR4). Tetapi saya harus mengekspos API untuk mengembalikan sesi yang akan tetap terbuka sampai klien yang menggunakan API ini memutuskan untuk menutupnya.
Saya menjalankan tes Junit, dan saya memiliki API berikut:

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

Dan dalam pengujian junit saya:
Stage.Session session = deviceRepository.openSession();
Ketika saya menjalankan kode saya mendapatkan kesalahan:
This needs to be run on the Vert.x event loop
Saya mencoba memfaktorkan ulang kode dengan berbagai cara tetapi saya tidak berhasil membuatnya berjalan.

Bisakah Anda memberi saya rekomendasi Anda bagaimana melakukannya dengan benar?

Terima kasih.

Komentar yang paling membantu

Ya saya akan

Semua 7 komentar

Hai,
masalah dengan sesi adalah bahwa itu tidak aman untuk utas, menggunakannya di utas yang berbeda dapat menyebabkan masalah yang sulit untuk di-debug. Juga, ketika sesi baru dibuat terikat dengan konteks Vert.x dan perlu digunakan dalam konteks yang sama setelah itu.

Ini biasanya ditangani oleh Hibernate Reactive ketika seseorang menggunakan SessionFactory#withTransaction dan SessionFactory#withSession .

Pengujian Anda tidak berfungsi karena dijalankan di utas JUnit, dan bukan di Vert.x.
Salah satu cara untuk mengatasi masalah ini di JUnit 4 adalah melalui aturan yang disertakan dalam perpustakaan io.vertx:vertx-unit:4.0.3 :

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

Ini akan memastikan bahwa pengujian Anda berjalan dalam konteks Vert.x .

Ini tidak cukup, Anda juga perlu memastikan bahwa sesi terikat pada konteks Vert.x yang sama yang ditentukan oleh aturan.

Layanan VertxInstance:

Secara umum, cara untuk mencapai ini adalah dengan membuat layanan VertxInstance kustom .

Layanan ini memberi tahu Hibernate Reactive cara mendapatkan Instans Vert.x yang benar untuk digunakan saat sesi dibuat.
Jika Anda membuat SessionFactory secara terprogram, berikut adalah contoh bagaimana Anda dapat melakukannya:

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 );

Atau, Anda dapat mendefinisikannya menggunakan mekanisme ServiceLoader dari JDK :

  1. Tambahkan file teks bernama org.hibernate.reactive.vertx.VertxInstance bawah
    /META-INF/services/
  2. File teks akan berisi jalur ke kelas yang mengimplementasikan antarmuka VertxInstance :
    org.myproject.MyVertxProvider

Sekarang Hibernate Reactive akan memanggil instance MyVertxProvider ketika membutuhkan instance Vert.x dan jika kode Anda berjalan dalam konteks Vert.x yang sama, semuanya akan berfungsi.

Memperbaiki masalah dengan JUnit 4:

Kembali ke tes, salah satu cara untuk memperbaikinya adalah:

<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() );

Jika Anda tidak menggunakan aturan, Anda dapat menjalankan kode dalam konteks Vert.x tertentu dengan cara berikut:

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

Anda harus menambahkan apa yang baru saja Anda tulis sebagai FAQ ke situs web atau di mana pun.

Ya saya akan

@DavideD Sangat menghargai penjelasan Anda. Terima kasih.

Saya telah membuat masalah untuk melacak perubahan ini pada dokumentasi/situs web: https://github.com/hibernate/hibernate-reactive/issues/751

Saya akan menutup masalah ini. Jangan ragu untuk mengajukan lebih banyak pertanyaan adalah sesuatu yang lain tidak jelas.

Terima kasih.

@DavideD Apakah mungkin menggunakan kode berikut yang Anda sebutkan sebelumnya dengan JUnit 5?

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

Ya, kode itu adalah Vert.x, bukan JUnit.

Tapi di sini bukan ekstensi yang setara untuk JUnit 5 dari:

<strong i="8">@Rule</strong>
public RunTestOnContext vertxContextRule = new RunTestOnContext();
Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

markusdlugi picture markusdlugi  ·  30Komentar

pqab picture pqab  ·  21Komentar

arifpratama398 picture arifpratama398  ·  10Komentar

hantsy picture hantsy  ·  7Komentar

gavinking picture gavinking  ·  6Komentar