JAVAFX: Location is not set error [duplicate]

When you use getClass().getResource(...) you are loading a resource, not specifying a path to a file. In the case where the class loader loads classes from the file system, these essentially equate to the same thing, and it does actually work (though even then there’s no technical reason it has to). When the class loader is loading classes by other mechanisms (and probably in all cases anyway), then it’s important to pay attention to the Java specifications for a resource.

In particular, note:

Resources, names, and contexts

A resource is identified by a string consisting of a sequence of
substrings, delimited by slashes (/), followed by a resource name.
Each substring must be a valid Java identifier. The resource name is of the form shortName or shortName.extension. Both shortName
and extension must be Java identifiers.

(My emphasis.) Since .. is not a valid Java identifier, there’s no guarantee of this resource being resolvable. It happens that the file system class loader resolves this in the way you expect, which is why it works in your IDE, but the implementation of getResource(...) in the jar class loader does not implement this in the way you are hoping.

Try

FXMLLoader loader = new FXMLLoader(getClass().getResource("/sm/customer/CustomerHome.fxml"));

Using controller locations to load FXML:

Since you have organized your code so that each FXML is in the same package as its corresponding controller file (which I think is a sensible way to do things), you could also leverage this in loading the FXML: just load the FXML “relative to its controller”:

FXMLLoader loader = new FXMLLoader(CustomerHomeCtrl.class.getResource("CustomerHome.fxml"));

This seems fairly natural in this setup, and the compiler will check that you have the package name for CustomerHomeCtrl correct at the point where you import the class. It also makes it easy to refactor: for example suppose you wanted to split sm.admin into multiple subpackages. In Eclipse you would create the subpackages, drag and drop the FXML and controllers to the appropriate subpackages, and the import statements would automatically be updated: there would be no further changes needed. In the case where the path is specified in the getResource(...), all those would have to be changed by hand.

Leave a Comment