1

I try to load a class located in an external jar using classloader. The class "FXMLbase" loads ok, but the error is triggered when the FXMLdocument.fxml try to instantiate the FXMLDocumentController. However when the "FXMLbase" is instantiate throught the JavaFXApplication5.java (located at the external jar) it works fine. Any Ideas?

Class Loader

 File file = new File("C:/Users/Os/Dropbox/CODE_OS/JavaFXApplication5/dist/JavaFXApplication5.jar");
 URLClassLoader clazzLoader = URLClassLoader.newInstance(new URL[]{file.toURI().toURL()}, this.getClass().getClassLoader());
 Class c = clazzLoader.loadClass("javafxapplication5.FXMLbase");
 PluginInterface fXMLbase = (PluginInterface) c.newInstance();
 Parent loadScreen = fXMLbase.getRoot();

FXMLbase.java -- external jar --

public Parent getRoot() {
    Parent root = null;
    try {
        System.out.println("Class Name:" + getClass().getName());           
        root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
    } catch (IOException ex) {            
        Logger.getLogger(FXMLbase.class.getName()).log(Level.SEVERE, null, ex);
    }
    return root;
}

FXMLdocument.fxml -- external jar --

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8"  fx:controller="javafxapplication5.FXMLDocumentController">
<children>
    <Button fx:id="button" layoutX="126" layoutY="90" onAction="#handleButtonAction" text="Click Me! app5" />
    <Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
</children>

FXMLDocumentController.java -- external jar --

public class FXMLDocumentController implements Initializable{    
@FXML
private Label label;    
@FXML
private void handleButtonAction(ActionEvent event) {
    System.out.println("You clicked me!");
    label.setText("Hello World!");
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}    
}

JavaFxApplication5.java -- external jar --

public void start(Stage stage) throws Exception {        
    FXMLbase fXMLbase=new FXMLbase();
    Parent root = fXMLbase.getRoot();
    Scene scene = new Scene(root);        
    stage.setScene(scene);
    stage.show();
}

Error:

ago 28, 2014 2:26:16 PM javafxapplication5.FXMLbase getRoot
SEVERE: null
javafx.fxml.LoadException: 
file:/C:/Users/Os/Dropbox/CODE_OS/JavaFXApplication5/dist/JavaFXApplication5.jar!/javafxapplication5/FXMLDocument.fxml:9
 ....
Caused by: java.lang.ClassNotFoundException: javafxapplication5.FXMLDocumentController

1 Answers1

3

The FXMLLoader at some point has to load the controller class from the value of the fx:controller attribute in the root element of the FXML file. It looks like it is using the system class loader to do this: I think this is because the system class loader finds the FXMLLoader class and loads it, rather than the class loader used to load your FXMLBase class.

The only fix I can find for this is to explicitly set the controller class from the FXMLbase class, instead of specifying it in the FXML. This is a bit unsatisfactory; perhaps there is a better way I am missing.

Updated FXMLbase class:

public Parent getRoot() {
    Parent root = null;
    try {
        System.out.println("Class Name:" + getClass().getName());           
        FXMLLoader loader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
        loader.setController(new FXMLDocumentController());
        root = loader.load();
    } catch (IOException ex) {            
        Logger.getLogger(FXMLbase.class.getName()).log(Level.SEVERE, null, ex);
    }
    return root;
}

and you need to remove the fx:controller attribute from the FXML file.

James_D
  • 201,275
  • 16
  • 291
  • 322
  • Interested in this solution for a different issue however do you know how to handle that fact that the onAction handles don't like not having a controller set. – Gapp Apr 30 '15 at 18:38
  • I don't understand that question. – James_D Apr 30 '15 at 18:47
  • Thanks for the quick response, the issue was stilling throwing errors for me I thought it may be because once you remove the controller all the onAction references are tagged as issues. However it looks more like it's css and image references. – Gapp Apr 30 '15 at 18:55
  • @James_D Did you find an other solution yet? – alexander Mar 03 '19 at 15:32