coderodde
coderodde

Reputation: 977

Java: Cannot load a JPG image as a resource in a JAR file

In the following code snippet:

InputStream inputStream = 
            ClassLoader.getSystemClassLoader()
                       .getResource("pics/logo.jpg")
                       .openStream();

either getResource or openStream returns null. How can I mitigate this issue?

Upvotes: 3

Views: 1700

Answers (5)

Dan M
Dan M

Reputation: 4377

I created a Java with Ant application in Netbeans with this:

public class Main {
    public static void main(String[] args){
        System.out.println(ClassLoader.getSystemClassLoader().
                getResource(".").getPath());
    }
}

When I ran it from within Netbeans I got:

/Users/enta/NetBeansProjects/JavaFrontEnd/JavaApplication47/build/classes/

But if I run it from the command line with

java -jar "/Users/enta/NetBeansProjects/JavaFrontEnd/JavaApplication50/dist/JavaApplication50.jar"

I got

Exception in thread "main" java.lang.NullPointerException at Main.main(Main.java:13)

Strange; I didn't get to the bottom of it. Then I created a Java with Maven application, also in Netbeans, with the exact same code and when I run it, both inside and outside of Netbeans, I get the right answer. From within Netbeans:

------------------------------------------------------------------------
Building JavaApplication46 1.0-SNAPSHOT
------------------------------------------------------------------------

--- exec-maven-plugin:1.5.0:exec (default-cli) @ JavaApplication46 ---
/Users/enta/NetBeansProjects/JavaFrontEnd/JavaApplication46/target/classes/
------------------------------------------------------------------------

From the command line: enter image description here

Knowing where you are in terms of a path should help you place the resource in the right spot.

Upvotes: 0

user11141611
user11141611

Reputation:

To load *.jpg image (or any other) from a *.jar file use this schema:

  1. Create a project, which then be compiled to the *.jar file

    project-with-resources
    │
    ├── src
    │   └── main
    │       ├── java
    │       │   ├── . . .
    │       │   └── Project.java
    │       └── resources
    │           ├── . . .
    │           └── image1.jpg
    └── pom.xml
    
  2. Configure maven-resources-plugin (there may be several resources folders)

    <build>
        <defaultGoal>package</defaultGoal>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <targetPath>resources</targetPath>
            </resource>
            . . .
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
            . . .
        </plugins>
    </build>
    
  3. In Java code use ImageIO class to read pictures to the BufferedImage objects

    public class Project {
        public static void main(String[] args) throws IOException {
            BufferedImage image =
                ImageIO.read(Project.class
                    .getResourceAsStream("/resources/image1.jpg"));
        }
    }
    
  4. Prepare getters, if necessary

    public class Project {
        private BufferedImage image;
        . . .
        public BufferedImage getImage() {
            return image;
        }
    }
    
  5. Build project to the *.jar file using Maven package goal in your IDE

    Maven Lifecycle

Upvotes: 2

tquadrat
tquadrat

Reputation: 4054

There is difference in the interpretation of the resource name between java.lang.Class.getResource() and java.lang.ClassLoader.getResource(): for the first, the given name is relative to the package of the class unless it starts with a '/', the name given to the second is always "absolute".

That means when you call java.lang.String.class.getResource( "resource/Doc.jpg" ), it will be looking for /java/lang/resource/Doc.jpg, while the call to java.lang.String.class.getClassLoader().getResource( "resource/Doc.jpg" ) tries to find /resource/Doc.jpg.

Both are not really 'pathes' (in the sense of a location on the filesystem), they determine locations relative to the CLASSPATH. That can be a location on the filesystem (in case the resource is not inside a JAR file …), but it could be also a reference to a database record, provided as a URI, depending on the implementation of the class loaders involved.

Upvotes: 0

JohannesB
JohannesB

Reputation: 2308

You may not have sufficient permissions depending on whether your application is running with a SecurityManager and it's security policy.

If I correctly Read The Fine Manual

It also offers guidance and explanation on the subtle differences between the different methods at your disposal.

Upvotes: 0

roninjoe
roninjoe

Reputation: 361

You need to put 'logo.jpg' in the 'pics' directory,relative to the root of your CLASSPATH, otherwise, ClassLoader.getResource() will return null, resulting in NPE when you try to open an InputStream based on it.

So, using an eclipse workspace with this code...

import java.io.InputStream;
import java.net.URL;

public class GetResource {
    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        URL resource = classLoader.getResource("pics/logo.jpg");
        System.out.println("resource is " + resource);
        InputStream inputStream = resource.openStream();
        System.out.println("The inputStream was not null");
    }
}

It will return...

resource is null
Exception in thread "main" java.lang.NullPointerException
    at GetResource.main(GetResource.java:9)

if "pics/logo.jpg" is not found relative to CLASSPATH root. Create the "logo.jpg" file in the right location (in this case the "src/pics" folder of the Eclipse project, which will automatically put it into the "bin/pics" folder), and the output is...

resource is file:/home/joe/workspace/Play/bin/pics/logo.jpg
The inputStream was not null

Normally the resources would be bundled inside your jar, so the "logo.jpg" should be in the "/pics" directory at the root of the jar.

Upvotes: 0

Related Questions