javaamazon-web-servicesfileaws-lambdagetresource

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...


Solution

  • 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.

    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:

    1. Find the resource identified by the URL "file:/var/task/lib/MyLambda-1.0.jar"
    2. Open it as a JAR file stream
    3. Find the entry "/com/my/package/folders/file.end" in the JAR file's namespace
    4. 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 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.