Altuğ Ceylan
Altuğ Ceylan

Reputation: 93

JavaFX program cannot run python script after it's deployed

I have written a JavaFX program that runs a python script that uses google console search api to get data. It works fine before I deploy it as a standalone program (.exe). After I install the program it runs fine until I click the button that runs the script; it does nothing.

After the button is clicked it succesfully checks if the python is installed or not, after that the problem occurs when it tries the run the script. I have specified the path like this, "./src/com/fortunamaritime/" and I think this might be the problem.

private static final String ANALYTICS_PATH ="./src/com/fortunamaritime/";

inside the method

//set up the command and parameter
String[] cmd = new String[3];
cmd[0] = "python"; 
cmd[1] = "analytics.py";
cmd[2] = "https://fortunamaritime.com.tr";
String command = cmd[0] + " " + cmd[1] + " " + cmd[2] + " " + 
startDate + " " + endDate;
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "cd " + new 
File(ANALYTICS_PATH).getAbsolutePath() + " && " + command);
builder.redirectErrorStream(true);
Process p = builder.start();

I have redirected console output to a .txt file to see what was happening and there's only one line that said "system cannot find the path specified".


I have switched from absolute path to relative path and it produced this error: The filename, directory name, or volume label syntax is incorrect. I also printed this line to console

this.getClass().getResource("/com/fortunamaritime/analytics.py")

and the result is:

jar:file:/D:/IdeaProjects/FortunaWebTracker/out/artifacts/FortunaWebTracker/FortunaWebTracker.jar!/com/fortunamaritime/analytics.py

Is it possible to access the inside of the jar file and run the script from there via cmd through stripping parts of this URL?

Upvotes: 2

Views: 214

Answers (2)

dan1st
dan1st

Reputation: 16383

Copy the script to a (maybe temporary) file and run it from that file.

You can get the script as InputStream with Main.class.getResourceAsStream(String resc) (relative to main) or Main.class.getClassLoader().getResourceAsStream(String resc) (relative to root)

You may use java.nio.file.Files#createTempFile(String,String and delete that file on exit.

You can also copy the script into the user home or relative to the exe (and don't delete it).

For example, you could do this:

File dir=new File("./resc");
if(!dir.exists()) {
    dir.mkdirs();
}
File analyticsFile=new File(dir,"analytics.py");
if(!analyticsFile.exists()) {
    /*
     * alternative:
     * this.getClass().getResourceAsStream("com/fortunamaritime/analytics.py")
     */
    try(InputStream analyticsIn = this.getClass().getClassLoader().getResourceAsStream("analytics.py")){
        Files.copy(analyticsIn, analyticsFile.toPath());
    }
}
/*
 * alternative: String command=String.join(" ",new String[]{"python",analyticsFile.getAbsolutePath(),"https://fortunamaritime.com.tr"});
 */
String command="python "+analyticsFile.getAbsolutePath()+" https://fortunamaritime.com.tr";
/*
 * alternative (without error redirection): Process p=Runtime.getRuntime().exec(command);
 */
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process p=builder.start();

Upvotes: 1

Altuğ Ceylan
Altuğ Ceylan

Reputation: 93

I have solved my problem. Here's the code sample first, explanation will follow;

String path =  new 
File(Main.class.getProtectionDomain().getCodeSource().getLocation()
     .toURI()).getPath();
path=path.substring(0,path.length()-21);
// set up the command and parameter
String[] cmd = new String[3];
cmd[0] = "python";
cmd[1] = "analytics.py";
cmd[2] = "https://fortunamaritime.com.tr";
String command0="jar xf FortunaWebTracker.jar" +                   
"com/fortunamaritime/analytics.pycom/fortunamaritime/client_secrets.json" +
" com/fortunamaritime/webmasters.dat";
String command1 = cmd[0] + " " + cmd[1] + " " + cmd[2] + " " + startDate + " " + 
endDate;
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "cd " + path + " && " + 
command0+"&&"+"cd "+path+"\\com\\fortunamaritime"+" && "+command1);
builder.redirectErrorStream(true);
Process p = builder.start();

My first mistake was to use absolute path, and the second problem arose when I got the path I wanted via:

File(Main.class.getProtectionDomain().getCodeSource().getLocation()
     .toURI()).getPath();
//Jar's name is 21 characters long, minus that and I get the directory path
path=path.substring(0,path.length()-21);

The second problem was unpacking elements inside the jar so I used this command in cmd:

jar xf FortunaWebTracker.jar
com/fortunamaritime/analytics.py com/fortunamaritime/client_secrets.json com/fortunamaritime/webmasters.dat

then I could get it to work.

Upvotes: 0

Related Questions