Executing jar file to load file in classpath - java

My MainClass.java has a main method which contains following code to read an excel file
String xlsxFilename = args[0];
try (InputStream fis = MainClass.class.getClassLoader().getResourceAsStream(xlsxFilename);
Workbook workbook = WorkbookFactory.create(fis);) {
...
This class is contained in a jar file and is placed in folder named lib and I'm executing it using using a shell script
run.sh
#!/bin/sh
CP=lib/*:
java -cp "$CP" in.test.MainClass $1
Now I run the command to execute the sh file
sh run.sh Sample.xlsx
But this throwing an exception,
Exception in thread "main" java.lang.NullPointerException
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:79)
I guess the exception is because the getResourceAsStream is not loading the excel file, and the fis object is null. Is the current directory not visible to getResourceAsStream()? How can I read the xls file inside the current directory in my MainClass.java ?

I think the problem is in this line of code:
InputStream fis = MainClass.class.getClassLoader().getResourceAsStream(xlsxFilename)
The file xlsxFilename will be find by the classloader if and only if your XLS is in the classpath, i.e. in a folder specified by the -classpath option to the JVM, or inside your jar archive. In the first case your line command should became something like this:
java -classpath "your.jar:/path/to/xls/folder" in.test.MainClass $1
Clearly /path/to/xls/folder is the folder where you have to put your xls file.
In the latter case, the XLS file has to be in the root folder of you .class files.
I suggest you to load the XLS file using an absolute file path.

Related

Running yarn job from java program using ProcessBuilder gives file does not exist error

I am trying to run a yarn job from a java wrapper program. The mapreduce jar takes two inputs:
A header file: I dont know the name of the file but the location and file extension and there's only one file at that location
A Input files directory
Apart from these I have an Output directory.
the processbuilder code looks like:
HEADER_PATH = INPUT_DIRECTORY+"/HEADER/*.tsv";
INPUT_FILES = INPUT_DIRECTORY+"/DATA/";
OUTPUT_DIRECTORY = OUTPUT_DIRECTORY+"/";
ProcessBuilder mapRProcessBuilder = new ProcessBuilder("yarn","jar",JAR_LOCATION,"-Dmapred.job.queue.name=name","-Dmapred.reduce.tasks=500",HEADER_PATH,INPUT_DIRECTORY,OUTPUT_DIRECTORY);
System.out.println(mapRProcessBuilder.command().toString());
Process mapRProcess = mapRProcessBuilder.start();
On run, I get the following error:
Exception in thread "main" java.io.FileNotFoundException: Requested
file /input/path/dir1/HEADER/*.tsv does not exist.
But when I run the same command as :
yarn jar jarfile.jar -Dmapred.job.queue.name=name -Dmapred.reduce.tasks=500 /input/path/dir1/HEADER/*.tsv /input/Dir /output/Dir/
It works all fine.
what can be the issue when running the command from java is causing this issue?
The * is being treated as part of the literal string in this case rather than a wildcard. Therefore globbing isn't expanding to your desired path name.
If there is only one file in the directory, why don't you find what its path is and pass that as the argument instead
eg.
File dir = new File(INPUT_DIRECTORY+"/HEADER);
if (dir.list().length > 0)
String HEADER_PATH = dir.list()[0].getAbsolutePath();

Directory not empty java.io.IOException

I need to launch an external app called TeamViewer from my JavaFX application.
So I've TeamViewer.app file which I'm copying to a temporary folder and launching it using:
Runtime.getRuntime().exec("open /path/to/Teamviewer.app");
But this is throwing Directory not empty IOException.
I also tried launching using shell file where I wrote "open /path/to/Teamviewer.app" command to launch.sh and launched launch.sh using process created by ProcessBuilder. if I run launch.sh from terminal, it works. But from java program,
following exception is thrown:
SEVERE: null
java.io.IOException: Cannot run program "sh" (in directory "/Applications/ColorDx.app/Contents/Java"): error=66, Directory not empty
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1047)
at com.sc.colordx.controller.ColorDxSupportController.executeCommand(ColorDxSupportController.java:288)
at com.sc.colordx.controller.ColorDxSupportController.launchSetup(ColorDxSupportController.java:126)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
What could be the reason for directory not empty exception? It has to be non empty as I've copied TeamViewer.app there. Could this be a multi threading issue? Means I'm copying TeamViewer.app first and immediately launching it. Is there a chance that launch command is called before copying is finished?
TIA
As I'd suspected, there was a problem with runtime itself! There's one more JavaFX app that acts as installer for this app (app with Runtime problems). For installation of this app I had used following code to copy contents of .app file:
public static final void copyFile( File source, File destination ) throws IOException {
FileChannel sourceChannel = new FileInputStream( source ).getChannel();
FileChannel targetChannel = new FileOutputStream( destination ).getChannel();
sourceChannel.transferTo(0, sourceChannel.size(), targetChannel);
sourceChannel.close();
targetChannel.close();
}
Above code didn't preserve file attributes while copying. Replacing above method with Files.copy using COPY_ATTRIBUTES option solved the problem.

Error in executing a jar file

I have a jar file named- ParseCSV-0.0.1-SNAPSHOT.jar and the contents of it are -
META-INF/
META-INF/MANIFEST.MF
foo/
foo/ReadCSV.class
META-INF/maven/
META-INF/maven/Test/
META-INF/maven/Test/ParseCSV/
META-INF/maven/Test/ParseCSV/pom.xml
META-INF/maven/Test/ParseCSV/pom.properties
The main class is ReadCSV.class and it takes a CSV file (C:\Testting\ValidaResults.csv) as an input parameter. I am trying to execute the jar file from the command promt by running the following command-
java -jar . ParseCSV-0.0.1-SNAPSHOT.jar "C:\Testting\ValidationResult.csv"
But I am getting an error saying-
Error: Could not find or load main class foo.ReadCSVTest
What is going wrong here.
Why do you have a . between jar and ParseCSV..?
Try this first:
java -jar ParseCSV-0.0.1-SNAPSHOT.jar "C:\Testting\ValidationResult.csv"
If this does not work, then try:
java -cp ParseCSV-0.0.1-SNAPSHOT.jar;. foo.ReadCSV "c:\Testting\ValidationResult.csv"
If this works, then i would inspect the META-INF/MANIFEST.MF file to figure out what the classpath is like, and what the value of Main-Class is. It seems to be running ReadCSVTest instead of ReadCSV.
Your JAR file includes foo/ReadCSV.class, but your MainClass is set to foo.ReadCSVTest. You'll need to fix your Main-Class attribute in META-INF/MAINIFEST.MF

FileNotFoundException when I try to read txt file via Command Line

I built a project in eclipse that uses a txt file. the file is located in the main folder project.
I get the file name as argument via command line, and I get FileNotFoundException. I try to use Scanner Object and get the file name as input from eclipse.. and it's worked. (I insert only the file name : file.txt . not the full path)
so why via the eclipse it's work and with command line not?
thank you!
this is the exception:
java.io.FileNotFoundException: bigMaze.txt (The system cannot find the file spec
ified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:146)
at java.io.FileReader.<init>(FileReader.java:72)
at BFS.BFS.readFile(BFS.java:43)
at BFS.BFS.InsertMaze(BFS.java:57)
at BFS.BFS.StartMain(BFS.java:16)
at search.main(search.java:20)
Exception in thread "main" java.lang.NullPointerException
at BFS.BFS.InsertMaze(BFS.java:62)
at BFS.BFS.StartMain(BFS.java:16)
at search.main(search.java:20)
If you're running from the command line, try placing the file in the same directory as the .class file
ProjectRoot
bin
file.txt
program.class
src
If the program is running from eclispe, then the file should go where you originally had it. directly under the project root.
This is all considering your running the program with String filename = "file.txt";
I think the problem is regarding pathname of your txt file. In case of command prompt you have to provide full path like: "MyComputer://D/yourFile.txt" but using eclipse you can give just "D://yourFile.txt". It will work.

Why can't I access a file within my jar unless I'm in the folder with the Jar when I run it?

I recently created an application and successfully jarred this to c:/my/folder/app.jar. It works like a charm in the following case [Startup #1]:
Open cmd
cd to c:/my/folder
java -jar app.jar
But when I do this, it doesn't work [Startup #2]:
Open cmd
cd to c:/my/
java -jar folder/app.jar
Because app.jar contains a .exe-file which I try to run in my application:
final Process p = Runtime.getRuntime().exec("rybka.exe");
It won't work in example 2 because it can't find the file rybka.exe.
Any suggestions?
Something like this is a better way forward. Copy the exe out of the jar to a temp location and run it from there. Your jar will then also be executable via webstart and so on:
InputStream src = MyClass.class.getResource("rybka.exe").openStream();
File exeTempFile = File.createTempFile("rybka", ".exe");
FileOutputStream out = new FileOutputStream(exeTempFile);
byte[] temp = new byte[32768];
int rc;
while((rc = src.read(temp)) > 0)
out.write(temp, 0, rc);
src.close();
out.close();
exeTempFile.deleteOnExit();
Runtime.getRuntime().exec(exeTempFile.toString());
If the jar will always be in that directory you can use a full path /my/folder/rybka.exe. If not, you can use getClass().getProtectionDomain().getCodeSource().getLocation() to find out the location of the jar and prepend that onto rybka.exe.
Try extracting the exe to
System.getProperty("java.io.tmpdir"));
then run it from this location too should work every time.
Paul

Categories

Resources