I'm making an application (Windows) using Haskell to implement numerical methods to solve problems and Java for the GUI and to process user input. For inter-process communication, I'm having them both read from and write to a mutual JSON file. It all works, but when attempting to execute the program by having Java communicate with cmd and run the GHCi, I can't seem to load and run the Haskell file once the compiler is running. There is no error message, but my Java program seems to often end up in what I think is deadlock. Any ideas? Here's my code:
try {
// Serialize dataMap to JSON and write to file
String jsonString = objectMapper.writeValueAsString(dataMap);
FileWriter fileWriter = new FileWriter("newtonRaphson.json");
fileWriter.write(jsonString);
fileWriter.close();
// Read JSON file
File jsonFile = new File("newtonRaphson.json");
JsonNode rootNode = objectMapper.readTree(jsonFile);
// Extract solution from JSON
Iterator<Map.Entry<String, JsonNode>> fields = rootNode.fields();
Map.Entry<String, JsonNode> secondEntry = fields.next();
JsonNode solutionOut = secondEntry.getValue();
String solutionText = solutionOut.asText();
// Display equation on GUI
Text messageTextFxn = new Text(equation);
messageTextFxn.setFont(new Font("System", 15));
fxnPane.getChildren().add(messageTextFxn);
// Display solution on GUI
Text messageTextSol = new Text(solutionText);
messageTextSol.setFont(new Font("System", 15));
solPane.getChildren().add(messageTextSol);
// Launch Haskell REPL and interact with it
String haskellPath = "path\\to\\hsFile";
ProcessBuilder builder = new ProcessBuilder("stack", "repl");
builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
builder.redirectError(ProcessBuilder.Redirect.INHERIT);
Process process = builder.start();
OutputStream outputStream = process.getOutputStream();
PrintWriter writer = new PrintWriter(outputStream);
// Load Haskell module
writer.println(":l " + haskellPath + "\\newtonRaphson");
writer.flush();
System.out.println("Haskell module loaded successfully.");
// Execute Haskell function
writer.println("nr");
writer.flush();
System.out.println("Haskell function executed successfully.");
// Close writer and wait for process to terminate
writer.close();
int exitCode = process.waitFor();
if (exitCode == 0) {
System.out.println("Process completed successfully.");
} else {
System.out.println("Process terminated with an error.");
}
I've tried using different ways to actually communicate with the terminal including processBuilder and Runtime exec(), but I'm thinking this is probably the wrong approach, just not sure what to do at this point.
See the discussion on the OP for details, but eliminating the methods using INHERIT and instead using bufferedWriter worked:
try {
// Serialize dataMap to JSON and write to file
String jsonString = objectMapper.writeValueAsString(dataMap);
FileWriter fileWriter = new FileWriter("newtonRaphson.json");
fileWriter.write(jsonString);
fileWriter.close();
// Read JSON file
File jsonFile = new File("newtonRaphson.json");
JsonNode rootNode = objectMapper.readTree(jsonFile);
// Extract solution from JSON
Iterator<Map.Entry<String, JsonNode>> fields = rootNode.fields();
Map.Entry<String, JsonNode> secondEntry = fields.next();
JsonNode solutionOut = secondEntry.getValue();
String solutionText = solutionOut.asText();
// Display equation on GUI
Text messageTextFxn = new Text(equation);
messageTextFxn.setFont(new Font("System", 15));
fxnPane.getChildren().add(messageTextFxn);
// Display solution on GUI
Text messageTextSol = new Text(solutionText);
messageTextSol.setFont(new Font("System", 15));
solPane.getChildren().add(messageTextSol);
// Launch Haskell REPL and interact with it
String haskellPath = "C:\\Users\\cezar\\Desktop\\AcademicResources\\Engineering\\Java\\JavaFX_VS\\chemesolver\\haskell\\nr\\src";
ProcessBuilder builder = new ProcessBuilder("stack", "repl");
Process process = builder.start();
OutputStream outputStream = process.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
// Load Haskell module
writer.write(":l " + haskellPath + "\\newtonRaphson");
writer.flush();
System.out.println("Haskell module loaded successfully.");
// Execute Haskell function
writer.write("nr");
writer.flush();
System.out.println("Haskell function executed successfully.");
// Close writer and wait for process to terminate
writer.close();
int exitCode = process.waitFor();