Reputation: 31
I am trying to start a command line app through a GUI made in JavaFX. When I run the program in my IDE it all works fine, but when I try to run it by double clicking the compiled .jar file, it doesn't.
I've figured out that it's probably because the PATH or Classpath or working directory or something like that is different from when you run it from the Terminal.
public Button startButton;
public Button clearButton;
public Button minButton;
public Button plusButton;
public Button clearFieldButton;
public Button clearLogButton;
public TextField linkField;
public TextField qualField;
public TextArea errorField;
public ListView<String> historyField;
private String os;
public void initialize(){
os = System.getProperty("os.name");
linkField.setText(null);
qualField.setText(null);
getHistory();
setButtonActions();
Runnable run = new Runnable() {
@Override
public void run() {
linkField.requestFocus();
}
};
Platform.runLater(run);
}
private void setButtonActions(){
historyField.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if(mouseEvent.getClickCount() == 2){
String qual;
if(qualField.getText() == null){
qual = "best";
}
else{
qual = qualField.getText();
}
startStream(historyField.getSelectionModel().getSelectedItem(), qual);
}
}
});
clearButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
clearHistory();
}
});
minButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
delLast();
}
});
plusButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
writeHistory(linkField.getText());
}
});
startButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
startStream(linkField.getText(),qualField.getText());
}
});
clearFieldButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
linkField.clear();
qualField.clear();
}
});
clearLogButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
errorField.clear();
}
});
}
private void delLast(){
LinkedList<String> temp = new LinkedList<>();
try(BufferedReader br = new BufferedReader(new FileReader("history.txt"))){
String line;
while((line = br.readLine()) != null){
temp.add(line);
}
temp.removeLast();
clearHistory();
for (String s : temp) {
writeHistory(s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void clearHistory(){
try(BufferedWriter br = new BufferedWriter(new FileWriter("history.txt"))){
br.write("");
getHistory();
} catch (IOException e) {
e.printStackTrace();
}
}
private void getHistory(){
if(!new File("history.txt").exists()){
try(BufferedWriter wr = new BufferedWriter(new FileWriter("history.txt"))) {
wr.write("");
} catch (IOException e) {
e.printStackTrace();
}
}
else{
historyField.getItems().clear();
ArrayList<String> history = new ArrayList<>();
try(BufferedReader br = new BufferedReader(new FileReader("history.txt"))){
String line;
while((line = br.readLine()) != null){
history.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
historyField.getItems().addAll(history);
}
}
private boolean checkIfInFile(String link){
try(BufferedReader br = new BufferedReader(new FileReader("history.txt"))){
String line;
while ((line = br.readLine()) != null){
if(line.equals(link)){
return true;
}
}
return false;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private void writeHistory(String link){
if(link != null){
try(PrintWriter print = new PrintWriter(new FileWriter("history.txt", true))) {
print.append(link).append("\n");
} catch (IOException e) {
e.printStackTrace();
}
getHistory();
}
}
private void startStream(String link, String quality){
errorField.setText("");
String command = "";
if(!checkIfInFile(link)){
writeHistory(link);
}
if(!os.contains("win")){
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", "/usr/bin/which streamlink");
Map<String, String> env = pb.environment();
env.put("PATH",System.getenv("PATH"));
errorField.appendText(env.get("PATH") + "\n");
try(BufferedReader br = new BufferedReader(new InputStreamReader(pb.start().getInputStream()))) {
command = br.readLine();
errorField.appendText(command);
} catch (IOException e) {
e.printStackTrace();
}
if(quality == null){
command = command + " " + link;
}
else if(link != null){
command = command + " " + link + " " + quality;
}
}
else{
if(link == null){
command = "streamlink";
}
else if(quality == null){
command = "streamlink " + link;
}
else{
command = "streamlink " + link + " " + quality;
}
}
try {
ProcessBuilder pb = new ProcessBuilder("/bin/bash", "-c", command);
Process proc = pb.start();
final InputStream in = proc.getInputStream();
Thread outputThread = new Thread(new Runnable() {
@Override
public void run() {
try(BufferedReader br = new BufferedReader(new InputStreamReader(in))){
String read;
while((read = br.readLine()) != null){
errorField.appendText(read + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
outputThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
Any help will be greatly appreciated.
EDIT: Forgot to mention that double clicking on Windows works perfect.
EDIT 2: **I just found out what the "real" problem was. If you run through terminal or bash script, this is the outcome of echo $PATH: '/Users/Vermeulen/.jenv/shims:/opt/local/bin:/opt/local/sbin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/X11/bi' and when you double click the jar the outcome of echo $PATH is: '/usr/bin:/bin:/usr/sbin:/sbin' **
Upvotes: 3
Views: 1447
Reputation: 23
Can you please share Manifest.mf file in jar? There should be main-class correctly set in it. please check this
Secondly check this as well. I expect jdk is already set properly in properties tab.
Upvotes: 0
Reputation: 852
On my linux machine double clicking uses my home directory as the working directory. Thus, it will fail if you are trying to find some files relative to your jar file.
To work around this behaviour you cant start your jar with a shell-script containing
java -jar myjarfile.jar
You sould than be able to double click the shell script (depending on your linux-distribution)
If you want to work around by code, try this snippet:
CodeSource src = Main.class.getProtectionDomain().getCodeSource();
File pathToJar = new File(src.getLocation().toURI());
System.out.println(pathToJar.getAbsolutePath());
It returns either the directory of your Main-class file or the full path to your jar-file. Depending on how you have started your program. Use this information to find your files.
---------------- Update 1
You haven't described exactly what your are trying to do. If you want to set environment variables like PATH for external commands use the ProcessBuilder.
ProcessBuilder builder = new ProcessBuilder("myprogramm", "firstArg", "secondArg");
Map<String, String> environment = builder.environment();
environment.put("PATH", environment.get("PATH") + ":/my/path");
Process process = builder.start();
OutputStream outputStream = process.getOutputStream();
process.waitFor();
For more information read ProcessBuilder.
Upvotes: 4