Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper packaging of runnable Jar project in netbeans

Tags:

java

jar

netbeans

So my task is to create a small program that displays a list of media files and run these media files with default OS media player separately.

My current solution was to create a package that holds all media files, something like:

-com.media
       |_a.mp4
       |_b.mp4

The following code copies to a temp dir the selected mp4, then runs the default os media player:

public File copyTempMedia(File tempAppFolder, String videoName) {

    URL f = getClass().getResource(String.format("%s/%s", Constants.MEDIA_LOCATION, videoName));
    File from = new File(f.getPath());
    File to = new File(tempAppFolder.getAbsolutePath());

    try {
        FileUtils.copyFileToDirectory(from, to);
    } catch (IOException ex) {
        Logger.getLogger(MediGUIModel.class.getName()).log(Level.SEVERE, null, ex);
    }
    System.out.println("Temp video copied: "  +  to.getAbsolutePath() + "/" + to.getName());
    return to;
}

public void triggerMediaPlayer(String fileLocation) {
    System.out.println("Triggering media player: " + fileLocation);
    try {
        if (OPERATIN_SYSTEM.contains("Linux")) {
            Runtime.getRuntime().exec("sh -c " + fileLocation);
        } else if (OPERATIN_SYSTEM.contains("Windows")) {

            Runtime.getRuntime().exec("cmd /c " + fileLocation);
        }
    } catch (IOException ex) {
        Logger.getLogger(MediGUIModel.class.getName()).log(Level.SEVERE, null, ex);
        ex.printStackTrace();
    }
}

When I run the program through Netbeans it works as espected, but when I do a clean/build the run the .jar created from the build, the media file doesn't seem to be read, so my questions are:

  1. Why does it work through Netbeans and not through build .jar ?
  2. Is this the best solution to this problem ?
  3. Should I package the media differently ?

Thanks in advance.

Edit

So after running through console instead of double clicking jar, is get a null pointer exception in the line where I read the file:

URL f = getClass().getResource(String.format("%s/%s", Constants.MEDIA_LOCATION, videoName));

Why does it work in Netebeans but not on build/jar ?

Is there another place in the jar I could place the media files, so that they are read with no problem through getResource or getResourceAsStream ?

like image 341
shep Avatar asked May 21 '17 17:05

shep


3 Answers

When you run the project in NetBeans, it isn't running the executable jar like java -jar yourproject.jar. Instead it sets the classpath to build/classes sort of like java -cp build/classes com.media.YourMainClass. This means your video files are actual files located in yourproject/build/classes/com/media, and they can be accessed as normal files in the filesystem and copied like a normal file. When you run from the jar, the files are packed in the jar file and can't be copied using simple file copy commands.

Instead of getting the URL by calling getClass().getResource(), try getting an InputStream by calling getClass().getResourceAsStream(). You can then write a simple loop to copy the bytes from the input stream to your temporary file.

like image 146
Corey Avatar answered Oct 02 '22 13:10

Corey


This snippet may be helpful:

    BufferedInputStream result = (BufferedInputStream) getClass().getResourceAsStream("/com/media/a.mp4");
    byte[] bytes = new byte[4098];
    try {
        result.read(bytes);
    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println(new String(bytes));

You'll need to read the bytes in a loop or something but that should work without needing a separate jar.

like image 43
Sam Avatar answered Oct 02 '22 13:10

Sam


I think it's not a good idea to put your media files in the jar because you need to rebuild the project if you want to change one and the jar size will grow.

Use:

File from = new File(String.format("%s/%s", Constants.MEDIA_LOCATION,videoName));

To load your files from the same folder as the jar.

If you want to keep the medias in the jar, create a Maven project and put the mp4 in src/main/resources. Use maven to create a fat jar and the src/main/resources will be included in the jar. See 'maven-shade-plugin' to configure the pom.xml and https://www.mkyong.com/maven/create-a-fat-jar-file-maven-shade-plugin/

Then you can use the others maven's great properties!

See Reading a resource file from within jar

Edit

After some tries, i can't get it right with 'getResource' from the jar. The path you get from within the jar is like:file:/C:/.../JavaApplication4/dist/JavaApplication4.jar!/test.txt and not recognized as a valid filesystem path.

You can use 'getResourceAsStream' and copy the file from the jar to the local folder.

InputStream in;
OutputStream out;
IOUtils.copy(in,out);
in.close();
out.close();
like image 39
Tokazio Avatar answered Oct 02 '22 12:10

Tokazio