Java Class Loader not able to read resource - java

I have a file in structure. projectName/src/config/keyfiles/file and my code is in folder projectName/src/main/java/customProject/package/filename.java
I am trying to read my file with class loader like.
URL url = CommonUtil.class.getClassLoader().getResource(filename);
but every time I am getting url as null. passed filename is ./keyfiles/file.
Please let me know where I am going wrong

To make sure "where you are" in the directory tree, do the following:
URL url = YourMainClass.class.getClassLoader().getResource(".");
System.out.printf("%s\n", url);
Then you will know why you can't get your file

Related

Why can I get a valid url from getClass().getResource(), but the url that is returned creates a file that doesn't exist

I am trying to load some data into an AWS lambda and am using getClass().getResource() to do so. This returns a nice URL that in logs seemingly prints out a plausible url; however, when I try and make a file based on that path, I get a file that when I call .exists() returns false.
If I run the code bellow, the first print statement gives "returns exists: false"
Meanwhile, the second print statement gives something around the lines of "test path: /file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end
File test = new File(cFile);
System.out.println("exists: " + test.exists());
System.out.println("test path: " + test.getAbsolutePath());
Not sure why this would be. If Java finds a file, then I would assume that the file exists...
Short answer: don't assume that the "path" of a URL is a file system pathname.
I am trying to load some data into an AWS lambda and am using getClass().getResource() to do so. This returns a nice URL that in logs seemingly prints out a plausible url;
Yes. (It would be nice if you showed us what the original URL looks like ... though I can guess.)
However, when I try and make a file based on that path, I get a file that when I call .exists() returns false.
OK, unless the URL has the protocol "file:", I would NOT expect that to work.
The path in a URL is a path that is intended for the protocol handler to resolve. The idea is that you use URL::openStream to open a stream to the resource named by the URL and then read it. The protocol handler takes care of interpreting the path (etc) and setting up the stream.
For a "file:" URL, the protocol handler will resolve the path in the file system, and provide you a stream to read the file.
For a "http:" URL, the protocol handler establishes a connection to the server, sends a GET request, and returns you a stream to read the response body.
For a "jar:" URL, the protocol handler opens the JAR file, finds the entry within the JAR file, and hands you a stream to read it.
And so on.
If you look at these, it is only in the "file:" case that there is a reasonable expectation that treating the path component of the URL as a file system pathname could work.
Looking at the pathname in your question:
file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end
I surmise that the original URL was:
jar:file:/var/task/lib/MyLambda-1.0.jar!/com/my/package/folders/file.end
So what that says to the "jar:" protocol handler is:
Find the resource identified by the URL "file:/var/task/lib/MyLambda-1.0.jar"
Open it as a JAR file stream
Find the entry "/com/my/package/folders/file.end" in the JAR file's namespace
Open a stream to read that entry's content.
The JAR file protocol handler knows how to do that. But (clearly) the File class doesn't ... because that "path" is not a file system pathname.
How you solve this depends on what you really need.
If you just need a stream to read the resource, use getClass().getResourceAsStream(...) instead.
If it must be a file in the file system, you may have to get hold of the stream (see above), copy it to a temporary file, and use a File for the temporary file.
If you are doing the because you want to write to the "file", I would suggest that you give up on that idea. It is a bad idea for an application to try to update its resources. And in some cases it simply won't / cannot work.
Is your File test = new File(cFile), Is your cFile made correctly with a proper path? Maybe the last print statement is just picking up on the incorrect path you made? But in reality you don't actually have a file there. Have you checked manually?

Read a .json file in portlet

I want to read a static json file (for testing) through portlet.
I've placed it in /json folder. So when the portlet is deployed, the folder is available in \webapps folder.
The complete path: webapps\myPortlet\json\op.json
In the processAction method -
#Override
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, IOException {
JSONParser parser = new JSONParser();
try {
JSONObject jsonObject = (JSONObject) parser.parse(new FileReader
(request.getContextPath() + "/json/op.json"));
.
.
.
}
I'm getting FileNotFoundException.
Can someone please point me a correct way to access this file.
First of all you can help yourself with some nice System.out's (but please remove it afterwards, so it does not pollute the logfile).
If you print this information
System.out.println( "request.getContextPath(): " + request.getContextPath() );
System.out.println( "new File(request.getContextPath()) : " + new File(request.getContextPath()).getAbsolutePath() );
you will find a little surprise. More information you will gain from
System.out.println( "new File() : " + new File().getAbsolutePath() );
If you really need to load a static file you should ask yourself why you are doing this and what you will get from it. Don't programm some stuff you don't need later on. Maybe you can find a better solution - even a better (automatically) testable solution.
If you really need a static file (like an image) you can place it into a jar near your Class:
#see How to get a path to a resource in a Java JAR file
If you need the content file as some kind of configuration file you should rethink your architecture and find the path to the file from some configurable parameters (like from your web.xml).
Remember: don't build something you don't need. Don't waste your time with something you will remove later on what is integrated in your software. Try to get rid of dependencies - even for testings.
Most likely you are using separators the wrong way, resulting in a wrong path. You could check this by debugging or even logging.
Try getting the actual file's full path from your computer's explorer, and compare it with the path you are creating on runtime
About using the Separator, you can try something like this:
String SEPARATOR = System.getProperty("file.separator");
ServletContext ctxt = FacesService.getHttpServletRequest().getSession().getServletContext();
String filepath = ctxt.getRealPath("json"+SEPARATOR+"op.json");
System.out.println("File path = "+ filepath);
Firstly you should try including the file or the folder altogether in src directory along with the file accessing it.
URL url = getClass().getResource("op.json");
Use sops to ensure that there are no special characters in the file path(no spaces in folder names,which are substituted for special characters).Hence forth,you can access the file.

"Access Denied" when trying to access file in web app

I have an xslt file stored in the folder Project/tools. (I'm using Netbeans IDE.)
I try to access this file in my code, but at run time, I get an AccessControlException: access denied.
The code is:
java.net.URI xsltURI = new java.net.URI(myUtil.getUri("xsltFile.xslt"));
Transformer transformer = factory.newTransformer(new StreamSource(new File(xsltURI)));
The myUtil instance must be used to access the URI for reasons not important here. I printed its output, and it correctly gives the relative path of the file.
I have tried to prefix the relative path with file:/// and file:///[fulldomain], but in each of these cases, it actually tries to access a hard drive on the server, even though I did not give a drive name anywhere. (!) It tries to access C:[relative-path], which isn't even where the file is anyway.
If I omit file:/// then I get that the URI is not absolute, and if I just give the full web address of the file I get a NullPointerException.
Any help at all would be greatly appreciated.
UPDATE: Following my comment below, my code resembles
java.net.URI xsltURI = new java.net.URI("https://host" + myB2U.getUri("xsltFile.xslt"));
java.net.URL xsltURL = xsltURI.toURL();
java.net.URLConnection myConnection = xsltURL.openConnection();
myConnection.connect(); //AccessControlException: access denied ("java.net.SocketPermission"...
java.io.InputStream xsltStream = myConnection.getInputStream();
Transformer transformer = factory.newTransformer(new StreamSource(xsltStream));
Is there something obvious that is wrong?
The file:// protocol tells Java to use file access to open the stream. If you don't want file access you should use a different protocol such as http://.
If you're using a relative path the URI should look something like file://./My/Relative/Path. The 3rd slash means that it is relative to the root.
From what I've gathered, I'm supposed to instantiate a URL object with the path of the file. From there, I'm supposed to be able to initialize a URLConnection from the URL. After I call the URL's connect() method, I'm supposed to be able to obtain an InputStream by calling the getInputStream() method.

How to read a file in another jar file?

I am running a GUI application (A.jar). Then I add a plugin (B.jar) to this GUI(A.jar).
Now I want to access the manifest.mf file in B.jar. I tried B.class.getResourceAsInputStream("/META-INF/MANIFEST.MF"). However, what I got is the manifest.mf in A.jar, not in B.jar.
Anyone can give me some hints on this problem? Thanks so much.
It is the case that the general class loader will take the path the comes first on the class path, and evidently A.jar comes first, before B.jar.
String someUniqueResourceInBJar = "...";
URL url = B.class.getResource(someUniqueResourceInBJar);
url = new URL(url.getPath().replaceFirst(someUniqueResourceInBJar + "$", "")
+ "META-INF/MANIFEST.MF";
url.openStream();
The url will be something like "jar:file://.../B.jar!META-INF/MANIFEST.MF".
Alternatively getting the class URL:
URL url = b.class.getProtectionDomain().getCodeSource().getLocation();

Creating a URL object with a relative path

I am creating a Swing application with a JEditorPane that should display an HTML file named url1.html stored locally in the page folder in the root folder of the project.
I have instantiated the following String object
final String pagePath = "./page/";
and in order to be displayed by the JEditorPane pane I have created the following URL object:
URL url1 = new URL("file:///"+pagePath+"url1.html");
However when the setPage() method is called with the created URL object as a parameter:
pagePane.setPage(url1);
it throws me a java.io.FileNotFoundException error.
It seems that there is something wrong with the way url1 has been constructed. Anyone knows a solution to this problem?
The solution is to find an absolute path to url1.html make an object of java.io.File on it, and then use toURI().toURL() combination:
URL url1 = (new java.io.File(absolutePathToHTMLFile)).toURI().toURL();
Assuming if the current directory is the root of page, you can pass a relative path to File:
URL url1 = (new java.io.File("page/url1.html")).toURI().toURL();
or
URL url1 = (new java.io.File(new java.io.File("page"), "url1.html")).toURI().toURL();
But this will depend on where you run the application from. I would make it taking the root directory as a command-line argument if it is the only configurable option for the app, or from a configuration file, if it has one.
The another solution is to put the html file as a resource into the jar file of your application.
To load a resource from the classpath (as khachik mentioned) you can do the following:
URL url = getClass().getResource("page/url1.html");
or from a static context:
URL url = Thread.currentThread().getContextClassLoader().getResource("page/url1.html");
So in the case above, using a Maven structure, the HTML page would be at a location such as this:
C:/myProject/src/main/resources/page/url1.html
I would try the following
URL url = new URL("file", "", pagePath+"url1.html");
I believe by concatenating the whole string, you are running into problems. Let me know, if that helped

Categories