1 Reply Latest reply on Apr 11, 2013 3:02 PM by daniel

    Controller ClassNotFoundException when FXML loaded

    JGagnon
      I am using the following:
      JavaFX 2.2
      Java SE 1.6.0_30
      Eclipse Indigo (3.7)

      We are developing applications using JavaFX embedded within eclipse RCP plug-ins. To do this we are using the FXCanvas as the "container" for our JavaFX-specific code. The canvas class is then embedded within an RCP view class. This has been working well for us so far. Now, we are trying to transition to use the JavaFX Scene Builder to layout our UI screens and use the generated FXML in our canvas class instead of doing the layout in the Java code. I am having a problem where I get a ClassNotFoundException indicating that the controller class cannot be found. I've tried a number of things to no avail. I've tried out the examples provided in the JavaFX tutorials and they work fine - granted they are standalone programs and not embedded within RCP.

      All of the files used in this test example reside in the same package.

      Example FXML (Test.fxml):

      <?xml version="1.0" encoding="UTF-8"?>
      
      <?import java.lang.*?>
      <?import java.util.*?>
      <?import javafx.geometry.*?>
      <?import javafx.scene.control.*?>
      <?import javafx.scene.layout.*?>
      <?import javafx.scene.paint.*?>
      <?import mypackage.*?>
      
      <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
        prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml" fx:controller="mypackage.TestController">
        <center>
          <TableView prefHeight="200.0" prefWidth="200.0">
            <columns>
              <TableColumn prefWidth="100.0" text="User">
                     <cellValueFactory>
                          <PropertyValueFactory property="userId" />
                     </cellValueFactory>
                </TableColumn>
              <TableColumn prefWidth="180.0" text="Last Activity">
                     <cellValueFactory>
                          <PropertyValueFactory property="lastActivity" />
                     </cellValueFactory>
                </TableColumn>
              <TableColumn prefWidth="100.0" text="Activity Count" />
                     <cellValueFactory>
                          <PropertyValueFactory property="activityCount" />
                     </cellValueFactory>
                </TableColumn>
            </columns>
          </TableView>
        </center>
        <bottom>
          <FlowPane alignment="TOP_RIGHT">
            <children>
              <Button fx:id="okButton" mnemonicParsing="false" text="OK" onAction="#okClicked" />
              <Button fx:id="cancelButton" mnemonicParsing="false" text="Cancel" onAction="#cancelClicked" />
            </children>
          </FlowPane>
        </bottom>
      </BorderPane>
      Controller (TestController.java):

      package mypackage;
      
      imports ...
      
      public class TestController {
        @FXML private Button  okButton;
        @FXML private Button  cancelButton;
        @FXML private TableView<MyModel> tableView;
      
        @FXML
        protected void okClicked(ActionEvent event) {
          System.out.println("OK clicked");
        }
      
        @FXML
        protected void cancelClicked(ActionEvent event) {
          System.out.println("Cancel clicked");
        }
      }
      Canvas class (TestCanvas.java):

      package mypackage;
      
      imports ...
      
      public class TestCanvas extends FXCanvas {
        private TestViewModel viewModel;
      
        public TestCanvas(Composite parent, int style) {
          super(parent, style);
          configureScene();
        }
      
        private void configureScene() {
          try {
            Parent parent = FXMLLoader.load(getClass().getResource("Test.fxml"));
            Scene scene = new Scene(parent);
            setScene(scene);
          } catch (IOException e) {
          }
        }
      
        ...
      }
      Example of exception trace:
      ...
      ERROR <date/time> java.lang.ClassNotFoundException: mypackage.TestController
      mypackage/Test.fxml
        at javafx.fxml.FXMLLoader.importClass()
        at javafx.fxml.FXMLLoader.processImport()
        at javafx.fxml.FXMLLoader.processProcessingInstruction()
        at javafx.fxml.FXMLLoader.load()
        ...
        at mypackage.TestCanvas.configureScene()
        at mypackage.TestCanvas.<init>
        at mypackage.TestView.createPartControl()
        at org.eclipse.ui.internal.ViewReference.createPartHelper()
        at org.eclipse.ui.internal.ViewReference.createPart()
        ...
      Edited by: 998038 on Apr 11, 2013 10:03 AM

      Edited by: 998038 on Apr 11, 2013 10:18 AM
        • 1. Re: Controller ClassNotFoundException when FXML loaded
          daniel
          Hi,

          When you load custom types using SceneBuilder, you must take into account the fact that
          your types may not be present in the system class loader, but in an URLClassLoader that
          SceneBuilder created for loading your custom files.

          What you are seeing may be a problem similar to https://javafx-jira.kenai.com/browse/DTL-5177
          A possible fix for the issue may be to change your code in the following way:
            private void configureScene() {
              try {
                FXMLLoader loader = new FXMLLoader();
                loader.setLocation(this.getClass().getResource("Test.fxml"));
                
                // Make sure to load "Test.fxml" with the same classloader that
                // was used to load TestCanvas class.
                loader.setClassLoader(this.getClass().getClassLoader());
          
                Parent parent = loader.load();
                Scene scene = new Scene(parent);
                setScene(scene);
              } catch (IOException e) {
              }
            }
          Hope this helps,

          -- daniel