Hibernate-reactive: openSession () بإرجاع الخطأ "يجب تشغيل هذا في حلقة حدث Vert.x"

تم إنشاؤها على ١٢ مايو ٢٠٢١  ·  7تعليقات  ·  مصدر: hibernate/hibernate-reactive

أهلا،

حتى الآن ، تم إخفاء Vertx عني أثناء استخدام واجهة برمجة التطبيقات التفاعلية Hibernate (1.0.0.CR4). لكن لا بد لي من كشف واجهة برمجة التطبيقات (API) لإرجاع الجلسة التي ستظل مفتوحة حتى يقرر العميل الذي يستخدم واجهة برمجة التطبيقات هذه إغلاقها.
أنا أقوم بإجراء اختبار Junit ، ولدي واجهة برمجة التطبيقات التالية:

    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 ويجب استخدامها في نفس السياق بعد ذلك.

يتم الاعتناء بهذا عادةً بواسطة Hibernate Reactive عندما يستخدم المرء SessionFactory#withTransaction و SessionFactory#withSession .

لا تعمل اختباراتك لأنها تعمل في سلسلة رسائل JUnit ، وليست في Vert.x.
إحدى طرق حل هذه المشكلة في JUnit 4 هي عبر قاعدة مضمنة في المكتبة io.vertx:vertx-unit:4.0.3 :

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

سيؤدي هذا إلى التأكد من تشغيل اختباراتك في سياق Vert.x.

لكن هذا لا يكفي ، فأنت بحاجة أيضًا إلى التأكد من أن الجلسة مرتبطة بنفس سياق Vert.x المحدد بواسطة القاعدة.

خدمة VertxInstance:

بشكل عام ، تتمثل طريقة تحقيق ذلك في إنشاء خدمة VertxInstance مخصصة.

تخبر هذه الخدمة Hibernate Reactive بكيفية الحصول على مثيل Vert.x الصحيح لاستخدامه عند إنشاء الجلسة.
إذا قمت بإنشاء 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 );

بدلاً من ذلك ، يمكنك تحديده باستخدام آلية ServiceLoader الخاصة بـ JDK :

  1. أضف ملفًا نصيًا باسم org.hibernate.reactive.vertx.VertxInstance ضمنه
    /META-INF/services/
  2. سيحتوي الملف النصي على المسار إلى الفصل الذي يطبق واجهة VertxInstance :
    org.myproject.MyVertxProvider

الآن سوف يقوم Hibernate Reactive باستدعاء مثيل MyVertxProvider عند الحاجة إلى مثيل Vert.x وإذا كان الرمز الخاص بك يعمل في نفس سياق Vert.x ، فيجب أن يعمل كل شيء.

إصلاح المشكلة مع JUnit 4:

بالعودة إلى الاختبارات ، تتمثل إحدى طرق إصلاحها في:

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

يجب عليك إضافة ما كتبته للتو في صورة أسئلة وأجوبة إلى موقع الويب أو في أي مكان.

نعم سأفعل

DavideD نقدر جدا

لقد قمت بإنشاء مشكلة لتتبع هذه التغييرات على الوثائق / موقع الويب: https://github.com/hibernate/hibernate-reactive/issues/751

سأغلق هذه القضية. لا تتردد في طرح المزيد من الأسئلة شيء آخر غير واضح.

شكرا لك.

DavideD هل من الممكن استخدام الكود التالي الذي ذكرته سابقًا مع JUnit 5؟

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

نعم ، هذا الرمز هو Vert.x وليس JUnit.

لكن t هنا ليس امتدادًا مكافئًا لـ JUnit 5 لـ:

<strong i="8">@Rule</strong>
public RunTestOnContext vertxContextRule = new RunTestOnContext();
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات