Incorrect relative path in java - java

My issue is in the code here (seperated for debugging purposes):
// creating newUniversePane
Scene newUniverseScene = new Scene(newUniversePane, 300, 200);
Class<? extends WorldNoteOrganizerMainController> aClass = getClass();
URL resource = aClass.getResource("../../resources/css/main.css");
String s = resource.toExternalForm();
newUniverseScene.getStylesheets().add(s);
//more code
So, by looking at many examples here on Stack Overflow, it seems that my relative path is correct. However, when I run the program, and it reaches this code, it gives me an error.(I am attempted to add the css to a scene which will be added to a Stage as a popup)
Error message:
Caused by: java.lang.NullPointerException at
controller.WorldNoteOrganizerMainController.handleNewUniverse(WorldNoteOrganizerMainController.java:169)
This error points to the line:
String s = resource.toExternalForm();
which is because resource is null. I have tried many different paths to try to get the file, but have not been successful. Also, I looked around on here, so that I am not repeating a question, but I could not find any questions that would help. I found relative class path questions, but they did not help me fix this. Any help would be greatly appreciated! I have added relative information to the end.
Actual one-liner code:
newUniverseScene.getStylesheets().add(getClass().getResource("/../../resources/css/main.css").toExternalForm();
Paths tried:
URL resource = aClass.getResource("/../resources/css/main.css");
URL resource = aClass.getResource("/resources/css/main.css");
Snapshot of hierarchy:

You need to find out what folder your app is at, when it runs, and how you look it up. Using this.getClass().getResource() the lookup is relative to the location of the class file itself, if the path begins with anything other than "/", When the path begins with "/", it is assumed to be an "absolute" path, and it will start at the "top" of the classpath (which in Eclipse ought to be the "target" folder). So - in you case, you would probably need to use "/css/main.css" (since src/main/resources/* will be copied to target/) - and as pointed out below, "relative paths" do not make sense here.

When you are using relative path, use this:
aClass.getClassLoader().getResource("relative-path");
If you are using Intellij there is an option that gives you the relative path by right clicking on the file.

When you specify the resources folder as a resource folder in Inillj IDEA (the yellow little icon) then call getClass().getResources() it gets you inside the resources directory itself so you just use getClass().getResources("css/main.css")

Related

Why does my Image not load in this path, but in another?

I Tried putting an image onto a JButton. After wrote down the path to the image, ran the Program,then image was not on the Button. Code Sample below:
public static JButton start = new JButton(new ImageIcon("resources//img//menu//Start_Game.png"));
The "resources" folder is in the "src" folder. Here is the Hirarchy in Eclipse
After I double checked I spelled everything right, I put in an other path.
public static JButton start = new JButton(new ImageIcon(System.getProperty("user.home") + "//Tindir//Hauptmenue//Start_Game.png"));
Suddenly it worked. It is obvious that the first path was not correct.
Question If there is a way to input a path to an Image in the same Project-Folder as the Code?
Yes, but not that way - those arguments are filenames, and java code is not deployed as a sack of files. It's deployed as a jar file. An entry inside a jar file does not count and can never be used with this API.
So, don't use this call. Use the other one, that takes a URL, because you certainly can represent either a file, or an entry within a jarfile, as one of those:
MyClass.class.getResource("Start_Game.png")
That is what you put instead of "resources/etc/Start_Game.png" in that code. This looks for a resource named Start_Game.png in the exact same place that MyApp.class is found, even if that is found inside a jar file, loaded out of a DB, live-streamed from the internet - whatever. You're using the same mechanism.
If your Start-Game file is somewhere else, start with a /. It seems like you want /img/menu/Start_Game.png here.
This trick is an easy way to get an idea of what you're doing:
class MyClass {
public static void main(String[] args) {
System.out.println(MyClass.class.getResource("MyClass.class"));
}
}
and you'll figure it out with that output.

Tomcat webclassloader fails to find a class

In a Tomcat 7 I have a pretty standar jar file on WEB-INF/lib. Inside this jar I have this class called Parser, and next to it (on the same dir) I have another one called AutomaticLocalLoader. Compilation gives no problem at all. In run time the AutomaticLoader class is found, and when It needs the Parser class, I get a NoClassDefFoundError
The Parser and AutomaticLoader class have been working without this problem for 15 years!! in many diferent vers of java and tomact; and now out of the blue, I am getting this NoClassDefFoundError, only for the Parser class. I already put a copy on a directory inside the WEB-INF/classes path and still got the same error. I already created my own ClassLoader to see if I get some error loading the class from the WEB-INF/classes directory by myself, but I can load it without problems.
log.info("Leer " + aFlInstructions[i].getAbsolutePath());
LoaderTest A = new LoaderTest();
A.test("com.hds.resolve.model.aguila.AutomaticLocalLoader");
LoaderTest B = new LoaderTest();
B.test("com.hds.resolve.model.aguila.Parser");
if(!bOverrideInputDir)
Psr = new Parser(aFlInstructions[i]);
else
Psr = new Parser(aFlInstructions[i], new String[] { StrLocalDirectory } );
The LoaderTest class, try to create the Class Object for the given name using Class.forName. If NoClassDefFoundError, then try to load the class using my own classloader and then create the class.
For the AutomaticLoader, it succed at the first try. For the Parser class if fails, then successfully load it with the custom classloader. Of course when the code reach the "new Parser" part, the old webclassloader still fails and throws the NoClassDefFoundError.
Both Parser and AutomaticLocalLoader belong to the same package and are stored on the same jar inside WEB-LIB.
Funny enough, the error does always happen on production... but never in my machine. I do not use customs classloaders except for doing this debug. Also, trying an old version of the software seems to fix the error. No idea why.
I think I can hack a solution messing with the tomcat's webclassloader, but I really would prefer to understand what is going wrong with this code.

File path (JAVA EE)

I'm working in a web project and I'm having troubles with files(java.io.File). The problem is only when I run as web application(tomcat 7), if I run as Java Application, the problem doesn't exist.
When I instantiate a file, new File("dir");, its path become C://Windows/System32/dir, this way, i can't do anything, maybe cause don't have Windows privilegies.
"I solved the problem" passing new File("C://Users/user/dir"), but I don't like this solution. I wanted to do this automatically, get the app path, for example. I'm coding in my machine, and after the deploy.... i don't know.
Any tips?
That's the part of the project that I'm having the problem, a jsf bean. My view calls the method addFile() to save the file that I receive from my view. It's working, but i have to pass the path like I said before, like is on the code below. The path goes to the Windows dir System32
Bean.java
#ManagedBean
#ViewScoped
public class Bean {
//ATTRIBUTES AND METHODS
public void addFile() {
File temporaryFile = new File("temporary");
//...
//...
//...
}
}
Sorry for my english, i'm brazillian.
There is a method in the File class that does exactly what you're looking for: https://docs.oracle.com/javase/8/docs/api/java/io/File.html#createTempFile-java.lang.String-java.lang.String-
Alternatively you can assemble the file's path yourself:
File myTempFile = new File(System.getProperty("java.io.tmpdir"),"temporary");
you can add folder resources in web folder then add files as you want
i tested it from adding some styles (css) and javascript and call them in jsf page.as example if you create file named x in folder files under web/resources folder
new File("files/x");
wishing the answer helps you .you can tell me if any problem happens again

Understanding java.nio.file.Path.relativize(Path other)

I am trying to familiarize myself with java.nio.file.Path.relativize() to no avail.
I have read the javadocs, and I have seen examples. However, I still cannot get my head around the following example(I use Linux, apologies to window users):
Working directory for program is: /home/userspace/workspace/java8.
With two files: /home/userspace/workspace/java8/zoo.txt and /home/userspace/temp/delete/dictionary.txt
The following program calls Path.relativize():
package certExam.java8.ch9NIO.paths;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Relativize
{
public static void main(String[] args)
{
Path relativePathToZoo = Paths.get("zoo.txt");
Path relativePathToDictionary = Paths.get("../../temp/delete/dictionary.txt");
System.out.println("relativePathToZoo.relativize(relativePathToDictionary): "+relativePathToZoo.relativize(relativePathToDictionary));
System.out.println("relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath(): "+relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath());
System.out.println("relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath().normalize(): "+relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath().normalize());
System.out.println("relativePathToDictionary.relativize(relativePathToZoo): "+relativePathToDictionary.relativize(relativePathToZoo));
System.out.println("relativePathToDictionary.relativize(relativePathToZoo).toAbsolutePath().normalize(): "+relativePathToDictionary.relativize(relativePathToZoo).toAbsolutePath().normalize());
System.out.println();
}
}
The output is:
relativePathToZoo.relativize(relativePathToDictionary): ../../../temp/delete/dictionary.txt
relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath(): /home/userspace/workspace/java8/../../../temp/delete/dictionary.txt
relativePathToZoo.relativize(relativePathToDictionary).toAbsolutePath().normalize(): /home/temp/delete/dictionary.txt
relativePathToDictionary.relativize(relativePathToZoo): ../../../../../zoo.txt
relativePathToDictionary.relativize(relativePathToZoo).toAbsolutePath().normalize(): /zoo.txt
My question, the bit I cannot understand is: Why does relativePathToDictionary.relativize(relativePathToZoo) output ../../../../../zoo.txt?
When normalized, it would make you think that zoo.txt lives in the root directory.
How does relativize() work out such a deep path? I understand that relativize() works in relation to the current working directory, so it adds .. to every path. But I am cannot understand, how it worked out the path to zoo.txt in relation to dictionary.txt.
First of all, the current working directory is completely irrelevant. I could reproduce your problem even under Windows, not having any of these files and directories on my system, the only difference being the use of \\ instead of /.
What should relativize do? If you have a path like foo bar baz and ask for relativizing foo bar hello, you’ll get .. hello as that’s the path, relative to foo bar baz to get to foo bar hello, i.e Paths.get("foo", "bar", "baz").resolve(Paths.get("..", "hello")).normalize() produces the same path as Paths.get("foo", "bar", "hello"), regardless of any real file system structure.
Now you ran into the bug JDK-6925169, as suggested by the user Berger in a comment. The Path implementation does not handle . and .. components correctly in relativize, but treats them like any other path component.
So whether you use Paths.get("..", "..", "temp", "delete", "dictionary.txt") or Paths.get("a", "b", "c", "d", "e"), it makes no difference, in either case, the implementation treats it as five nonmatching path components that have to be removed to resolve to Paths.get("zoo.txt"). This applies to both, Windows and Linux. You may verify it with the following platform-independent code:
Path relative = Paths.get("zoo.txt");
Path base1 = Paths.get("..", "..", "temp", "delete", "dictionary.txt");
Path base2 = Paths.get("a", "b", "c", "d", "e");
Path relativized1 = base1.relativize(relative);
System.out.println("relativized1: "+relativized1);
Path relativized2 = base2.relativize(relative);
System.out.println("relativized2: "+relativized2);
Path resolved1 = base1.resolve(relativized1).normalize();
System.out.println("resolved1="+resolved1);
Path resolved2 = base2.resolve(relativized2).normalize();
System.out.println("resolved2="+resolved2);
Since relatize incorrectly treats all component the same, the relativized paths are the same, but since the normalize operation does handle the .. path components, the first resolved path will exhibit the problem whereas the second resolves to the expected zoo.txt.
It might be important for the understanding, that all path components, including dictionary.txt, are treated like directories. The documentation of relativize doesn’t mention that explicitly, but you can derive it from the documented relationship to resolve, whose documentation says “… this method considers this path to be a directory”.
Given the example paths below:
Path p1 = Paths.get("java/temp/zoo.txt");
Path p2 = Paths.get("java/bin/elephant.bin");
Path p1Top2 = p1.relativize(p2);
System.out.println(p1Top2);
We want to get from zoo.txt to elephant.bin in this example.
So, let's start at zoo.txt and ask ourselves: how do I get from zoo.txt to elephant.bin. First I have to go up a directory, so I use ".." Now I'm in temp. (Trace the steps with your finger if it helps!). I have to go up one more to java so, I use ".." again. Now I'm in java. The directory bin is in java, so, I go down to it using "/bin". Once more I go down using "/elephant.bin". We have arrived at our destination.
Put all of the above steps we took together and you get the output:
../../bin/elephant.bin

Loading image from source folder returned as null

Hello I have a problem with importing an image from my resources folder. I have looked all over google (or so I think) and I have no idea what I am doing wrong.
All help is appreciated thanks
Here is the picture of my java project:
Here is my Game Code:
public Game(){
handler = new Handler();
this.addKeyListener(new KeyInput(handler));
new Window(WIDTH, HEIGHT, "Testing", this);
BufferedImageLoader loader = new BufferedImageLoader();
level = loader.loadImage("/level.png");
hud = new HUD();
spawn = new Spawn(handler, hud);
r = new Random();
walls = new WallsMap(handler);
cam = new Camera(0, 0);
walls.render();
handler.addObject(new Player(WIDTH/2-32, HEIGHT/2-32, ID.Player, handler));
}
Finally here is my BufferedImageLoader class:
public class BufferedImageLoader {
private BufferedImage image;
public BufferedImage loadImage(String path){
try {
image = ImageIO.read(getClass().getClassLoader().getResourceAsStream(path));
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
}
To solve your particular problem, either of these two options should work so that the resource can be properly located:
Remove the call to getClassLoader() from your loadImage method so that the call is just getClass().getResourceAsStream(path) -OR-
Remove the slash from "/level.png" so that your call to loadImage looks like loader.loadImage("level.png")
However, in general, I agree with mastercork889, that it is better practice to organize your resources into packages as well.
EDIT:
In response to mastercork889's comment saying that my answer should be AND instead of OR, I thought I should elaborate on why it is indeed exclusive OR. I would have just commented, but I'm still too new to stack overflow to be allowed to comment, and this is quite a bit of information anyway :)
Removing the call to getClassLoader() works because then you're using the getResourceAsStream() method from the Class class, which does extra work before delegation to the getResourceAsStream() method from the ClassLoader class.
From the Java API:
Before delegation, an absolute resource name is constructed from the given resource name using this algorithm:
If the name begins with a '/' ('\u002f'), then the absolute name of the resource is the portion of the name following the '/'.
Since your resource isn't in a package, and is at the top level of a source folder (it looks like res is an "Eclipse Source Folder"), the level.png portion following the slash will adequately identify the location of the resource in an absolute way.
OR
Removing the slash from "/level.png" also works because then when the object's class loader (which should be the system class loader) looks for the resource, it will attempt to resolve your resource in an absolute way. The special handling of the slash at the beginning is behavior that is specific to the getResourceAsStream() method in Class, not ClassLoader.
The reason that AND won't work, is because if you call the getResourceAsStream() method from Class and remove the slash, then it will attempt to locate the resource in the same package that the associated class is located in. If you choose to go with the AND option, then you would need to move level.png into the com.plat.gfx package.
As a final point, I have built a small test program that followed the same format as your example, and once I followed one of the two suggestions, it worked for me.
The subtleties of resources, classes, and class loaders can be quite tricky. Good luck with your project!
Don't worry about putting images in a specific folder. Instead put them also in the src folder under a specific package: com.plat.res
I find that putting images in a specific package makes the package hierarchy look much more efficient, and less spaghetti-like.
Also a note on package conventions: domain-extension.domain.main-program.etc. My package hierarchy looks like this:
com.brennytizer.jumg
com.brennytizer.jumg.res
com.brennytizer.jumg.engine
com.brennytizer.jumg.level
com.brennytizer.jumg.level.maps
If you don't have a domain, write in what you think your domain would be (if you were to buy it in the future), or just use your (backwards) name:
My name is Jarod Brennfleck, writing program foobar, my package would be: brennfleck.jarod.foobar.
Once in there use the ImageIO class: ImageIO.read(Game.class.getResourceAsStream("/com/plat/res/leve.png"));

Categories