Exception error when I try to run the start of my javaFxApplication [duplicate] - exception

My JavaFX application needs to be able to find the FXML files to load them with the FXMLLoader, as well as stylesheets (CSS files) and images. When I try to load these, I often get errors, or the item I'm trying to load simply doesn't load at runtime.
For FXML files, the error message I see includes
Caused by: java.lang.NullPointerException: location is not set
For images, the stack trace includes
Caused by: java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
How do I figure out the correct resource path for these resources?

Short version of answer:
Use getClass().getResource(...) or SomeOtherClass.class.getResource(...) to create a URL to the resource
Pass either an absolute path (with a leading /) or a relative path (without a leading /) to the getResource(...) method. The path is the package containing the resource, with . replaced with /.
Do not use .. in the resource path. If and when the application is bundled as a jar file, this will not work. If the resource is not in the same package or in a subpackage of the class, use an absolute path.
For FXML files, pass the URL directly to the FXMLLoader.
For images and stylesheets, call toExternalForm() on the URL to generate the String to pass to the Image or ImageView constructor, or to add to the stylesheets list.
To troubleshoot, examine the content of your build folder (or jar file), not your source folder.
Placing src in the path when you get a resource is always wrong. The src directory is only available at development and build time, not at deployment and runtime.
Full Answer
Contents
Scope of this answer
Resources are loaded at runtime
JavaFX uses URLs to load resources
Rules for resource names
Creating a resource URL with getClass().getResource(...)
Organizing code and resources
Maven (and similar) standard layouts
Troubleshooting
Scope of this answer
Note that this answer only addresses loading resources (for example FXML files, images, and stylesheets) that are part of the application, and bundled with it. So, for example, loading images that the user chooses from the file system on the machine on which the application is running would require different techniques that are not covered here.
Resources are loaded at runtime
The first thing to understand about loading resources is that they, of course, are loaded at runtime. Typically, during development, an application is run from the file system: that is, the class files and resources required to run it are individual files on the file system. However, once the application is built, it is usually executed from a jar file. In this case, the resources such as FXML files, stylesheets, and images, are no longer individual files on the filesystem but are entries in the jar file. Therefore:
Code cannot use File, FileInputStream, or file: URLs to load a resource
JavaFX uses URLs to load resources
JavaFX loads FXML, Images, and CSS stylesheets using URLs.
The FXMLLoader explicitly expects a java.net.URL object to be passed to it (either to the static FXMLLoader.load(...) method, to the FXMLLoader constructor, or to the setLocation() method).
Both Image and Scene.getStylesheets().add(...) expect Strings that represent URLs. If URLs are passed without a scheme, they are interpreted relative to the classpath. These strings can be created from a URL in a robust way by calling toExternalForm() on the URL.
The recommended mechanism for creating the correct URL for a resource is to use Class.getResource(...), which is called on an appropriate Class instance. Such a class instance can be obtained by calling getClass() (which gives the class of the current object), or ClassName.class. The Class.getResource(...) method takes a String representing the resource name.
Rules for resource names
Resource names are /-separated path names. Each component represents a package or sub-package name component.
Resource names are case-sensitive.
The individual components in the resource name must be valid Java identifiers
The last point has an important consequence:
. and .. are not valid Java identifiers, so they cannot be used in resource names.
These may actually work when the application is running from the filesystem, though this is really more of an accident of the implementation of getResource(). They will fail when the application is bundled as a jar file.
Similarly, if you are running on an operating system that does not distinguish between filenames that differ only by case, then using the wrong case in a resource name might work while running from the filesystem, but will fail when running from a jar file.
Resource names beginning with a leading / are absolute: in other words they are interpreted relative to the classpath. Resource names without a leading / are interpreted relative to the class on which getResource() was called.
A slight variation on this is to use getClass().getClassLoader().getResource(...). The path supplied to ClassLoader.getResource(...) must not begin with a / and is always absolute, i.e. it is relative to the classpath. It should also be noted that in modular applications, access to resources using ClassLoader.getResource() is, under some circumstances, subject to rules of strong encapsulation, and additionally the package containing the resource must be opened unconditionally. See the documentation for details.
Creating a resource URL with getClass().getResource()
To create a resource URL, use someClass.getResource(...). Usually, someClass represents the class of the current object, and is obtained using getClass(). However, this doesn't have to be the case, as described in the next section.
If the resource is in the same package as the current class, or in a subpackage of that class, use a relative path to the resource:
// FXML file in the same package as the current class:
URL fxmlURL = getClass().getResource("MyFile.fxml");
Parent root = FXMLLoader.load(fxmlURL);
// FXML file in a subpackage called `fxml`:
URL fxmlURL2 = getClass().getResource("fxml/MyFile.fxml");
Parent root2 = FXMLLoader.load(fxmlURL2);
// Similarly for images:
URL imageURL = getClass().getResource("myimages/image.png");
Image image = new Image(imageURL.toExternalForm());
If the resource is in a package that is not a subpackage of the current class, use an absolute path. For example, if the current class is in the package org.jamesd.examples.view, and we need to load a CSS file style.css which is in the package org.jamesd.examples.css, we have to use an absolute path:
URL cssURL = getClass().getResource("/org/jamesd/examples/css/style.css");
scene.getStylesheets().add(cssURL.toExternalForm());
It's worth re-emphasizing for this example that the path "../css/style.css" does not contain valid Java resource names, and will not work if the application is bundled as a jar file.
Organizing code and resources
I recommend organizing your code and resources into packages determined by the part of the UI they are associated with. The following source layout in Eclipse gives an example of this organization:
Using this structure, each resource has a class in the same package, so it is easy to generate the correct URL for any resource:
FXMLLoader editorLoader = new FXMLLoader(EditorController.class.getResource("Editor.fxml"));
Parent editor = editorLoader.load();
FXMLLoader sidebarLoader = new FXMLLoader(SidebarController.class.getResource("Sidebar.fxml"));
Parent sidebar = sidebarLoader.load();
ImageView logo = new ImageView();
logo.setImage(newImage(SidebarController.class.getResource("logo.png").toExternalForm()));
mainScene.getStylesheets().add(App.class.getResource("style.css").toExternalForm());
If you have a package with only resources and no classes, for example, the images package in the layout below
you can even consider creating a "marker interface" solely for the purposes of looking up the resource names:
package org.jamesd.examples.sample.images ;
public interface ImageLocation { }
which now lets you find these resources easily:
Image clubs = new Image(ImageLocation.class.getResource("clubs.png").toExternalForm());
Loading resources from a subpackage of a class is also reasonably straightforward. Given the following layout:
we can load resources in the App class as follows:
package org.jamesd.examples.resourcedemo;
import java.net.URL;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class App extends Application {
#Override
public void start(Stage primaryStage) throws Exception {
URL fxmlResource = getClass().getResource("fxml/MainView.fxml");
Parent root = FXMLLoader.load(fxmlResource);
Scene scene = new Scene(root);
scene.getStylesheets().add(getClass().getResource("style/main-style.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
To load resources which are not in the same package, or a subpackage, of the class from which you're loading them, you need to use the absolute path:
URL fxmlResource = getClass().getResource("/org/jamesd/examples/resourcedemo/fxml/MainView.fxml");
Maven (and similar) standard layouts
Maven and other dependency management and build tools recommend a source folder layout in which resources are separated from Java source files, as per the Maven Standard Directory Layout. The Maven layout version of the previous example looks like:
It is important to understand how this is built to assemble the application:
*.java files in the source folder src/main/java are compiled to class files, which are deployed to the build folder or jar file.
Resources in the resource folder src/main/resources are copied to the build folder or jar file.
In this example, because the resources are in folders that correspond to subpackages of the packages where the source code is defined, the resulting build (which, by default with Maven, is in target/classes) consists of a single structure.
Note that both src/main/java and src/main/resources are considered the root for the corresponding structure in the build, so only their content, not the folders themselves, are part of the build. In other words, there is no resources folder available at runtime. The build structure is shown below in the "troubleshooting" section.
Notice that the IDE in this case (Eclipse) displays the src/main/java source folder differently from the src/main/resources folder; in the first case it displays packages, but for the resource folder it displays folders. Make sure you know if you are creating packages (whose names are .-delimited) or folders (whose names must not contain ., or any other character not valid in a Java identifier) in your IDE.
If you are using Maven and decide that for ease of maintenance you'd rather keep your .fxml files next to the .java files that reference them (instead of sticking strictly to the Maven Standard Directory Layout), you can do so. Just tell Maven to copy these files to the same folder in your output directory that it will place the class files generated from those source files into, by including something like the following in your pom.xml file:
<build>
...
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.fxml</include>
<include>**/*.css</include>
</includes>
</resource>
...
</build>
If you do this, you can then use an approach like FXMLLoader.load(getClass().getResource("MyFile.fxml")) to have your classes load .fxml resources from the directory which contains their own .class files.
Troubleshooting
If you get errors you do not expect, first check the following:
Make sure you are not using invalid names for your resources. This includes using . or .. in the resource path.
Make sure you are using relative paths where expected, and absolute paths where expected. for Class.getResource(...) the path is absolute if it has a leading /, and relative otherwise. For ClassLoader.getResource(...), the path is always absolute, and must not start with a /.
Remember that absolute paths are defined relative to the classpath. Typically the root of the classpath is the union of all source and resource folders in your IDE.
If all this seems correct, and you still see errors, check the build or deployment folder. The exact location of this folder will vary by IDE and build tool. If you are using Maven, by default it is target/classes. Other build tools and IDEs will deploy to folders named bin, classes, build, or out.
Often, your IDE will not show the build folder, so you may need to check it with the system file explorer.
The combined source and build structure for the Maven example above is
If you are generating a jar file, some IDEs may allow you to expand the jar file in a tree view to inspect its contents. You can also check the contents from the command line with jar tf file.jar:
$ jar -tf resource-demo-0.0.1-SNAPSHOT.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/jamesd/
org/jamesd/examples/
org/jamesd/examples/resourcedemo/
org/jamesd/examples/resourcedemo/images/
org/jamesd/examples/resourcedemo/style/
org/jamesd/examples/resourcedemo/fxml/
org/jamesd/examples/resourcedemo/images/so-logo.png
org/jamesd/examples/resourcedemo/style/main-style.css
org/jamesd/examples/resourcedemo/Controller.class
org/jamesd/examples/resourcedemo/fxml/MainView.fxml
org/jamesd/examples/resourcedemo/App.class
module-info.class
META-INF/maven/
META-INF/maven/org.jamesd.examples/
META-INF/maven/org.jamesd.examples/resource-demo/
META-INF/maven/org.jamesd.examples/resource-demo/pom.xml
META-INF/maven/org.jamesd.examples/resource-demo/pom.properties
$
If the resources are not being deployed, or are being deployed to an unexpected location, check the configuration of your build tool or IDE.
Example image loading troubleshooting code
This code is deliberately more verbose than is strictly necessarily to facilitate adding additional debugging information for the image loading process. It also uses System.out rather than a logger for easier portability.
String resourcePathString = "/img/wumpus.png";
Image image = loadImage(resourcePathString);
// ...
private Image loadImage(String resourcePathString) {
System.out.println("Attempting to load an image from the resourcePath: " + resourcePathString);
URL resource = HelloApplication.class.getResource(resourcePathString);
if (resource == null) {
System.out.println("Resource does not exist: " + resourcePathString);
return null;
}
String path = resource.toExternalForm();
System.out.println("Image path: " + path);
Image image = new Image(path);
System.out.println("Image load error? " + image.isError());
System.out.println("Image load exception? " + image.getException());
if (!image.isError()) {
System.out.println("Successfully loaded an image from " + resourcePathString);
}
return image;
}
External Tutorial Reference
A useful external tutorial for resource location is Eden coding's tutorial:
Where to put resource files in JavaFX.
The nice thing about the Eden coding tutorial is that it is comprehensive. In addition to covering the information on lookups from Java code which is in this question. The Eden tutorial covers topics such as locating resources that are encoded as urls in CSS, or resource references in FXML using an # specifier or fx:include element (which are topics currently not directly covered in this answer).

Related

Swagger API Specification filenames

I'm trying to use Swagger to create API documentation for an API we're building and I've never used it before.
The documentation on Github says that the Resources Listing needs t be at /api-docs and the various resource files need to be at /api-docs/books etc.
This makes naming files and folders very tricky. I think they expect the files to have no file names, rather than having a folder called /api-docs it has to be an extension-less file, then you can't put the resources in an api-docs folder because you can't call the folder that, so they suggest using a folder called /listings.
This folder doesn't appear in the URL structure of your documentation though, it's kind of invisible because you set the baseURL in your resources to the proper path, but it looks like that has to be an absolute path, which is awkward if you want to have it on several servers (local and production).
Maybe I just don't get it but this all seems to be absolutely nuts.
So, I have 2 questions.....
1) Can I give my resource listing file and my resource files a .json extension? This would make sense as it's a JSON file.
2) Can I use a relative path to the resource listing file in the baseURL in my resource files?
Ideally, my file structure would be flatter, like this...
/api-docs
resources.json
books.json
films.json
Is Swagger flexible enough to do this?
It's an IIS server if that makes any difference (if the solution requires routing for example).
I was able to put model files into a folder under the web root and could reference them like this.
$ref: '/models/model.yml#/MyObject'
Relative paths also worked without a leading slash.
$ref: 'models/model.yml#/MyObject'
Inside the model.yml, I can reference other objects int eh same file like this
$ref: '#/MyObject2'.
However, I could only get the main swagger file to import model files. I could not get one model file to cross-reference another model file.
I was using a Tomcat web server but the principle will be the same.

How can I import JSON data from a REST API into BIRT?

I want to use BIRT to generate reports against data that comes from a JSON based REST API. How can I import this data?
The process for doing this is described at http://developer.actuate.com/community/forum/?app=blog&blogid=45&showentry=471, but it turns out that there are a few important steps missing. I'll fill in a few blanks here.
The original instructions describe creating a Scripted Data Source, with an "open" script that makes use of the com.actuate.json.JSONParser class. First, it is important to realise that this class is not part of BIRT, and needs to be manually added (along with any dependencies).
The download provided by the original instructions provides the com.actuate.json.JSONParser class, but leaves it up to you to source the dependencies. To make things easier I have reimplemented the JSONParser library in Maven, which will then download and package the dependencies for you. It also includes some bug fixes and enhancements like GZIP compression support. You can get the Maven project from https://github.com/mcasperson/birt-jsonparser, and to build the JSONParser library and package the dependencies, run the command
mvn clean package dependency:copy-dependencies
This will result in the birt-jsonparser-0.0.1-SNAPSHOT.jar file being created in the target directory, and all the dependencies copied into the target\dependency directory. Copy all of these JAR files into the {BIRT_INSTALL}/plugins/org.eclipse.birt.report.viewer_{BIRT_VIEWER_VERSION}/birt/scriptlib directory to allow the JSONParser class to be accessed from within your BIRT report.
If you want to debug your report, these JAR files will also have to be referenced in the Debug profile.

Configuring DisplayTag for individual pages

I have too many modules (around 90) in my project.
But I want to keep individual displaytag.properties file for each module rather than having single file for whole project.
How to achieve this.
I am using struts2
I think that you can configure each displaytag using the appropiate bundle, remember the bundle search order from S2 docs:
ActionClass.properties Interface.properties
Interface.properties (every interface and sub-interface)
BaseClass.properties (all the way to Object.properties)
ModelDriven's model (if implements ModelDriven), for the model object repeat from 1
package.properties (of the directory where class is located and every parent directory all the way to the root directory)
search up the i18n message key hierarchy itself
global resource properties
and from the docs for the DisplayTag library:
For the whole web application, create a custom properties file named "displaytag.properties" and place it in the application classpath. Displaytag will use the locale of the request object to determine the locale of the property file to use; if the key required does not exist in the specified file, the key will be loaded from a more general property file.
so i guess that the displaytag will search the config keys in the s2 available bundles.

Change the include path for ActionScript

I am working on a custom library for Flash ActionScript3, and I have a handful of functions that I would like to add to Array.prototype.
I placed the extension in a separate .as file within a folder in the library directory, but when I make the include call from my document class, it tries to execute the include relative to the .fla file's location, rather than the library's source path.
I have already added the lib path to the Source Path: values under ActionScript3 Advanced Settings, which works for my import statements.
How do I get the include path to be relative to the library's path?
dir structure:
flash/
lib/libname/inc/array.as
projectname/project.fla
include that doesn't work (but should):
include "libname/inc/array.as";
include that works, but isn't portable if I move the project to a different location:
include "../lib/libname/inc/array.as";
I had a realization about how I was calling the include directive.
I had stored my document class in the same directory as the .fla file, because it's a class specific to the project. The document class contained the include directive, but the class that was actually using the extended Array functions was within lib/libname.
Moving the include directive to the .as file that required the extended features allowed the include directive to be called relative to the location of the calling class, which allowed me to use include "../inc/array.as"; because the .as file was within lib/libname/utils/ClassName.as.
So the answer to the issue is that the include path is relative to the location of the calling script, not the project. This means that any script within the library can include features from the library without issue, as the structure will be preserved.

Output reformatted text within a file included in a JSP

I have a few HTML files that I'd like to include via tags in my webapp.
Within some of the files, I have pseudo-dynamic code - specially formatted bits of text that, at runtime, I'd like to be resolved to their respective bits of data in a MySQL table.
For instance, the HTML file might include a line that says:
Welcome, [username].
I want this resolved to (via a logged-in user's data):
Welcome, user#domain.com.
This would be simple to do in a JSP file, but requirements dictate that the files will be created by people who know basic HTML, but not JSP. Simple text-tags like this should be easy enough for me to explain to them, however.
I have the code set up to do resolutions like that for strings, but can anyone think of a way to do it across files? I don't actually need to modify the file on disk - just load the content, modify it, and output it w/in the containing JSP file.
I've been playing around with trying to load the files into strings via the apache readFileToString, but I can't figure out how to load files from a specific folder within the webapp's content directory without hardcoding it in and having to worry about it breaking if I deploy to a different system in the future.
but I can't figure out how to load files from a specific folder within the webapp's content directory without hardcoding it in and having to worry about it breaking if I deploy to a different system in the future.
If those files are located in the webcontent, use ServletContext#getRealPath() to convert a relative web path to an absolute disk file system path. This works if the WAR is exploded in the appserver (most does it by default, only Weblogic doesn't do that by default, but this is configureable IIRC). Inside servlets you can obtain the ServletContext by the inherited getServletContext() method.
String relativeWebappURL = "/html/file.html";
String absoluteFilePath = getServletContext().getRealPath(relativeWebappURL);
File file = new File(absoluteFilePath);
// ...
Alternatively, you can put it in the classpath of the webapplication and make use of ClassLoader#getResource():
String relativeClasspathURL = "/html/file.html";
URL absoluteClasspathURL = Thread.currentThread().getContextClassLoader().getResource(relativeClasspathURL);
File file = new File(absoluteClasspathURL.toURI());
// ...
As to the complete picture, I question if you have ever considered an existing templating framework like Freemarker or Velocity to ease all the job?