Avinash D Avinash D - 4 months ago 19
PHP Question

How to give input to java program and continue with execution using PHP?

I want to execute java programs using php code. When i write the below code, the program written in the editor is getting compiled and executed successfully.

putenv('path=C:\Program Files\Java\jdk1.8.0_73\bin');

echo shell_exec("javac $output 2>&1"); // for compiling and creating class file

echo exec("java $check 2>&1"); // for executing generated class file and prints output


Note:
$output
and
$check
variables contains required input to compile & run

But, when I try to execute java programs where we need to input some data to contine with the execution, the above code doesn't works. For example, consider the
JavaScannerExample
in the link: http://alvinalexander.com/java/edu/pj/pj010005

To execute the program in the link, I guess I need some interactive console to accept the input and continue with program execution. Please suggest me how to achieve this using php?

Update:

@Chris.. Tried
proc_open
command as suggested. See my code below:

PHP Code

<?php

$JAVA_HOME = "C:\Java\jdk1.7.0_79";
$PATH = "$JAVA_HOME\bin";
putenv("JAVA_HOME=$JAVA_HOME");
putenv("PATH=$PATH");
$result = shell_exec("javac JavaScannerExample.java 2>&1");
if ($result == ""){
$options = ["bypass_shell" => true];
$proc=proc_open("java JavaScannerExample",
array(
array("pipe","r"),
array("pipe","w"),
array("pipe","w")
),
$pipes,NULL,NULL,$options);
if (is_resource($proc)) {
fwrite($pipes[0], 'Mark');
fwrite($pipes[0], 32);
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
}

}
else{
echo $result;
}
?>


Java Code

import java.util.Scanner;

public class JavaScannerExample
{

public static void main (String[] args)
{
// create a scanner so we can read the command-line input
Scanner scanner = new Scanner(System.in);

// prompt for the user's name
System.out.print("Enter your name: ");

// get their input as a String
String username = scanner.next();

// prompt for their age
System.out.print("Enter your age: ");

// get the age as an int
int age = scanner.nextInt();

System.out.println(String.format("%s, your age is %d", username, age));

}

}


PHP Output

Enter your name: Enter your age:


Could you please check and let me know where did I went wrong?




Update2:

@Chris.. Thanks for your suggestion. It helped me get the output.

Here is the modified php code:

putenv('path=C:\Program Files\Java\jdk1.8.0_73\bin');
$result = shell_exec("javac JavaScannerExample.java 2>&1");
if ($result == ""){
$options = ["bypass_shell" => true];
$proc=proc_open("java JavaScannerExample",
array(
array("pipe","r"),
array("pipe","w"),
array("pipe","w")
),
$pipes,NULL,NULL,$options);
if (is_resource($proc)) {
fwrite($pipes[0], "Mark\n");
fwrite($pipes[0], "32\n");
fclose($pipes[0]);
echo stream_get_contents($pipes[1]);
fclose($pipes[1]);
}
}
else{
echo $result;
}


This is the result I am getting.

Enter your name: Enter your age: Mark, your age is 32


There are multiple problems with this type of result. First I am trying to build an interactive console. So for the above example, the pipes need to work in parallel. However, I am not able to retrieve pipes[1] until I close pipes[0]. Because if I get the value of pipes[1] earlier in the code the program is hanging. In this scenario. First I need to be able to read the input which is "Enter your name:" Then enter input which is "Mark". Next steps are similar I need to get the text "Enter age:" and enter input "32". finally I need to get the final output which is "Mark, your age is 32" and detect the program is finished and then close both the pipes. Is this possible?

Answer

Use proc_open instead of exec. It can be used to retrieve a pipe to stdin which can be used to provide input to your Java application. The first example on the proc_open manual page demonstrates how to do this.