Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8157413

Multiple WebView behavior looks to collide when loading the same URL

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Duplicate
    • Affects Version/s: 8u92, 9
    • Fix Version/s: 10
    • Component/s: javafx
    • Subcomponent:
      web
    • CPU:
      x86_64
    • OS:
      windows_7

      Description

      FULL PRODUCT VERSION :
      java version "1.8.0_92"
      Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
      Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      When in a JavaFX application you have multiple WebViews that load the same URL ; the changes reported by a listener on : view.getEngine().getLoadWorker().stateProperty().addListener(...) are totally incoherent.

      The same code works well when the URL are totally different.

      The bug occurs in all the versions I have tested 1.8.0_92, 1.8.0_74 & 1.8.0_102-ea-b01.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      execute the attached class and verify the logs ; incoherent states & missing DOM object are reported.

      The class support 3 modes, defined by the value of urlMode variable line 34.

      when urlMode = UrlMode.UNIQUE => multiple views opening the exact same URL
      when urlMode = UrlMode.UNIQUE_DIFF_PARAMETER=> multiple views opening the same URL with different parameters (html app
      scenario)
      when urlMode = UrlMode.MULTIPLE => multiple views opening different URLs

      Only when the URL are really different then no errors are reported , otherwise the listener receives incoherent information:
      - bad order of state changes
      - multiple times the same state
      - missing DOM document object when state is succeed

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Even when multiple webviews work on the same URL:
      - the reported states of the load worker are coherent
      - the dom object is available when the webpage succeed to load
      ACTUAL -
      Incoherent results when loading several time the same URL

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      package com.agfa.apps.bug.javafx;

      import org.w3c.dom.Document;

      import javafx.application.Application;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.concurrent.Worker;
      import javafx.concurrent.Worker.State;
      import javafx.scene.Scene;
      import javafx.scene.layout.FlowPane;
      import javafx.scene.web.WebView;
      import javafx.stage.Stage;

      public class MultipleWebViewBug extends Application {
          public static String[] uniqueURL = new String[] { "https://www.reddit.com/r/javafx" };

          public static String[] manyURLS = new String[] { "http://www.google.com",
                  "http://stackoverflow.com/questions/29779219/java-fx-loading-multiple-webpages-in-webview-at-a-time",
                  "http://oracle.com", "http://mysql.com", "https://www.reddit.com/r/javafx", "http://spring.io", "http://r-project.org",
                  "http://tomcat.apache.org" };

          @Override
          public void start(final Stage primaryStage) {
              final FlowPane root = new FlowPane();
              final Scene scene = new Scene(root, 780, 780);
              primaryStage.setScene(scene);
              primaryStage.show();

              
              // ++++++++++++++++++++++++++++++++
              // Change this for different behaviors
              // ++++++++++++++++++++++++++++++++
              UrlMode urlMode = UrlMode.UNIQUE;
              
              for (int i = 0; i < manyURLS.length; i++) {
                  root.getChildren().add(newView(i, retrieveURL(i, urlMode)));
              }
          }


          public static void main(final String[] args) {
              launch(args);
          }
          
          private String retrieveURL(int i, UrlMode mode) {
              switch (mode) {
                  case UNIQUE:
                      return uniqueURL[0];
                  case UNIQUE_DIFF_PARAMETER:
                      return uniqueURL[0] + "?nb="+i;
                  case MULTIPLE:
                      return manyURLS[i%manyURLS.length];
              }
              throw new IllegalStateException("enum value not handled: " + mode);
          }

          private WebView newView(int number, String url) {
              final WebView view = new WebView();
              view.setPrefSize(250.0, 250.0);
              addStateChangeListener("view-" + number, view);
              view.getEngine().load(url);
              return view;
          }

          private void addStateChangeListener(final String webViewName, final WebView view) {
              view.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
                  @Override
                  public void changed(final ObservableValue<? extends Worker.State> ov, final Worker.State oldState, final Worker.State newState) {
                      logState(webViewName, oldState, newState, view.getEngine().getDocument());
                  }
              });
          }

          private void logState(final String webViewName, final Worker.State oldState, final Worker.State newState, final Document dom) {
              // log state change
              final String domPresence = dom == null ? "NO DOM" : "DOM OK";
              System.out.println("> INFO " + webViewName + " dom=" + domPresence + ", oldState=" + oldState + ", newState=" + newState);

              // Log if state SUCCEEDED but Document is null
              if (newState == Worker.State.SUCCEEDED && dom == null) {
                  System.out.println("! ERROR " + webViewName + " state SUCCEEDED with null document");
              }

              if (oldState == State.READY && newState == State.SCHEDULED) {
                  return;
              }
              if (oldState == State.SCHEDULED && newState == State.RUNNING) {
                  return;
              }
              if (oldState == State.RUNNING && newState == State.SUCCEEDED) {
                  return;
              }
              // Log incoherent state transitions
              System.out.println("! ERROR " + webViewName + " Incoherent state change from " + oldState + " to " + newState);
          }
          
          private enum UrlMode {
              UNIQUE,
              UNIQUE_DIFF_PARAMETER,
              MULTIPLE;
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Do not allow multiple webviews to load in parallel :-(

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                ghb Guru Hb
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: