JxBrowser TimeoutException при ожидании загрузки основного кадра (invokeAndWaitFinishLoadingMainFrame) - PullRequest
0 голосов
/ 01 мая 2019

Я использую JxBrowser в проекте. Я работаю только с локальными файлами HTML и поэтому использую следующий метод для отображения моих файлов HTML:

    public static void loadHTMLFile(Browser browser, String filename){
        String current = PathUtils.getCurrentDir();
        browser.loadURL("file:///" + current + "/some/path/in/my/project/resources/web/" + filename);
    } 

В некоторых случаях я должен использовать метод invokeAndWaitFinishLoadingMainFrame , поскольку мне нужно инициализировать кнопки, которые должны быть загружены полностью в первую очередь.

Пример с официального сайта JxBrowser (https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013107-loading-waiting) выглядит так:

// Blocks current thread execution and waits until http://www.google.com web page is loaded completely
Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {
    @Override
    public void invoke(Browser value) {
        value.loadURL("http://www.google.com");
    }
});

В моем случае это выглядит так:

public static void loadHTMLFileComplete(Browser browser, String filename){
    Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {
        @Override
        public void invoke(Browser value) {
            loadHTMLFile(value, filename);
        }
    });
}

Пока ничего удивительного ...

Теперь самое сложное:

Метод invAAWaitFinishLoadingMainFrame - это проблема:

  1. самое первое представление (представление входа в систему) загружается корректно с помощью invokeAndWaitFinishLoadingMainFrame -method
  2. после этого время ожидания моей программы (полное исключение ниже) при использовании invokeAndWaitFinishLoadingMainFrame -метода снова
    • например, когда я нажимаю на кнопку входа и хочу перенаправить на главный экран
  3. есть небольшой взлом, который я случайно обнаружил, чтобы он работал на данный момент (теперь он становится жутким):

    • проблема тайм-аута исчезает, когда я загружаю онлайн-страницу между, например. Google
    • это также может быть с invokeAndWaitFinishLoadingMainFrame -метод
    • вот как я это делаю

      public static void loadGoogle(Browser browser){
          Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {
          @Override
          public void invoke(Browser value) {
              value.loadURL("http://www.google.com");
      
          }
      });
      

      }

  4. наступает тайм-аут, о котором я упоминал ранее:

    -- Product name: JxBrowser
    -- Licensed version: 6.x
    -- Licensed to: 
    -- License type: Evaluation
    -- Generation date: 21.04.2019
    -- Expiration date: 21.05.2019
    -- License info: Single-user license
    -- Current date: 30.04.2019
    JxBrowser license valid.
    11:55:59 SCHWERWIEGEND:[0430/235559.671039:ERROR:sandbox_linux.cc(379)] InitializeSandbox() called with multiple threads in process gpu-process.
    com.teamdev.jxbrowser.chromium.Browser@6b9651f3
    11:56:49 SCHWERWIEGEND: Unexpected exception in DOMEventListener.handleEvent() method.
    java.lang.RuntimeException: java.util.concurrent.TimeoutException 
    at com.teamdev.jxbrowser.chromium.Browser.invokeAndWaitFinishLoadingMainFrame(SourceFile:570)
    at com.teamdev.jxbrowser.chromium.Browser.invokeAndWaitFinishLoadingMainFrame(SourceFile:532) 
    at browserActions.PageLoader.loadHTMLFileComplete(PageLoader.java:15)
    at browserViews.OrderCreationView.loadView(OrderCreationView.java:21)
    at browserActions.ButtonInitializer.lambda$0(ButtonInitializer.java:26)
    at com.teamdev.jxbrowser.chromium.dom.internal.EventTarget$a.onMessageReceived(SourceFile:179)
    at com.teamdev.jxbrowser.chromium.internal.ipc.q.a(SourceFile:1085)
    at com.teamdev.jxbrowser.chromium.internal.ipc.r.run(SourceFile:69)
    at com.teamdev.jxbrowser.chromium.internal.s.run(SourceFile:79)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
    Caused by: java.util.concurrent.TimeoutException
    ... 14 more
    

Подведем итог:

Не работает:

  • загрузить вид входа в систему
  • нажмите кнопку входа
  • попробуйте загрузить основной вид -> тайм-аут

Работает:

  • загрузить вид входа в систему
  • нажмите кнопку входа
  • загрузить Google
  • непосредственно после загрузки Google (нет времени для взаимодействия с пользователем), загрузить основной вид -> нет времени ожидания

Что здесь происходит: O?

Любая помощь будет потрясающей!

1 Ответ

1 голос
/ 08 мая 2019

JxBrowser основан на движке Chromium и наследует свою многопроцессорную архитектуру. Каждый экземпляр Browser связан как минимум с одним процессом рендеринга, который обрабатывает функции, связанные с DOM и JavaScript. Когда вы переходите в другой домен, механизм Chromium создает новый процесс рендеринга и убивает старый. Если вы перемещаетесь в пределах одного домена, процесс рендеринга остается прежним.

Из стека вызовов я вижу, что вы пытаетесь загрузить URL из прослушивателя DOM. Слушатели DOM вызываются синхронно, поэтому процесс рендеринга остается заблокированным, пока событие обрабатывается Java.

Когда вы загружаете URL, например, google.com, все работает просто отлично, потому что создается новый процесс рендеринга, и, как только страница загружается, метод Browser.invokeAndWaitFinishLoadingMainFrame возвращает управление и старый процесс рендеринга уничтожается. Однако если вы попытаетесь загрузить URL-адрес file:///, процесс рендеринга останется прежним, и загрузка не может начаться, потому что процесс рендеринга заблокирован методом Browser.invokeAndWaitFinishLoadingMainFrame, вызванным из прослушивателя DOM, поэтому вы получите тупик .

Во избежание этого исключения не следует запускать синхронную навигацию из приемника DOM.

В соответствии со стеком вызовов вы вызываете метод loadView из DOMEventListener. Чтобы избежать тупика, вы должны вызывать этот метод асинхронно, например:

import com.teamdev.jxbrowser.chromium.dom.events.DOMEvent;
import com.teamdev.jxbrowser.chromium.dom.events.DOMEventListener;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyDomEventListener implements DOMEventListener {

    private final ExecutorService executorService;
    private final OrderCreationView view;

    public MyDomEventListener(OrderCreationView view) {
        this.view = view;
        this.executorService = Executors.newCachedThreadPool();
    }

    @Override
    public void handleEvent(DOMEvent domEvent) {
        // Do not block the current thread and invoke the loadView method asynchronously.
        executorService.execute(view::loadView);
    }
}

В методе loadView вы можете синхронно загружать HTML:

public void loadView() {
    Browser.invokeAndWaitFinishLoadingMainFrame(browser, new Callback<Browser>() {
        @Override
        public void invoke(Browser browser) {
            browser.loadHTML("");
        }
    });
    initLoginButton();
}
...