How to implement Queue in Java? - java

I have a folder with 1 ThMapInfratab1-2.exe file and 3 .txt files. If you run .exe file in any way(through command prompt,just double click and through any language) one Icon will be appear on Taskbar.
My .exe will be run 2-3 minutes.
Know I want to run these .exe file using Java.I found How to run .exe from Java technology.
My concept was, first I will find .txt file Names from the directory.finally I will get like this.
List<File> fileNames={"File1.txt","File2.txt","File3.txt"};
Know I want to run my .exe file 3 times because my fileNames length is equals to 3.For this I wrote the following code.
//ExeFileProcess Function
public void ExeternalFileProcessing(String DirectoryPath,String exeFileName,String inputFileName) throws IOException
{
String executableFileName = DirectoryPath+"/"+exeFileName;
String inputFile=inputFileName;
ProcessBuilder processBuilderObject=new ProcessBuilder(executableFileName,inputFile);
File absoluteDirectory = new File(DirectoryPath);
processBuilderObject.directory(absoluteDirectory);
processBuilderObject.start();
//processBuilderObject.wait();
}
//Main Function code.
public static void main(String[] args) throws IOException
{
ExternalFileExecutions ExternalFileExecutionsObject=new ExternalFileExecutions();
for (int fileIndex = 0; fileIndex < fileNames.size(); fileIndex++)
{
ExternalFileExecutionsObject.ExeternalFileProcessing("C:/Users/Infratab Bangalore/Desktop/Rod","ThMapInfratab1-2.exe",fileNames[fileIndex ]);
}
}
I evaluated above code, at a time 3 .exe processes are started.But I don't want like that. I want to run .exe file one by one(we need to monitor, whether the previous .exe process was done or not. once it's done it allows to next Iteration).
I tried with Wait().but it's not working.
I guess, for this I need to add some code in my ExeternalFileProcessing(). But I didn't get anything.
can anyone suggest me.
I hope, you understand, what My problem.

ProcessBuilder.start method returns an instance of Process class. YOu can use waitFor method to wait until created process stops:
...
Process process = processBuilderObject.start();
process.waitFor();
}
processBuilderObject.wait() is a invocation of Object's wait method. It is used for concurrency and doesn't relate to processes at all.

Related

Java Process object fails to execute given command

I am trying to run a piece of Python code via a Java application. The command when put directly into Command Prompt cd'd to the working directory runs exactly as intended. However, my attempts to use the Runtime and ProcessBuilder classes in conjunction with the Process class has yielded no sign of correct function which would be the creation of a CSV file for every call of the code.
I am running this program using Intellij on Windows 10. I have added each directory I am using to my environmental PATH variable as well as attempting full paths in my commands and just file names. The only source of life I can find is that if I include a .waitFor() method a .isAlive() method will return true before the .waitFor() method is called.
I have searched through various similar questions and concluded that using a ProcessBuilder object is the best way to go and that the biggest issue is probably the structure of my command. However, I have made many iterations and have found nothing that changes the caught error to anything useful.
Here is the privacy augmented code that I have been running, I wrote out the command in full in the process builder as that is the last iteration I have attempted.
for (int y = 1; y < iterator; y++) {
try {
String command =
"C:\\Users\\myName\\AppData\\Local\\Programs\\Python\\Python37\\python C:\\Users\\myName\\IdeaProjects\\projectApplication\\script.py ";
String pythonInputPath = " C:\\Users\\myName\\IdeaProjects\\projectApplication\\bin\\output" + y + ".wav ";
ProcessBuilder pb = new ProcessBuilder(command+Arrays.toString(pythonCommandString).replaceAll("\\s","")+pythonInputPath+Integer.toString(y));
Process p = pb.start();
//Process checks
System.out.println(p.isAlive());
p.waitFor();
System.out.println(p.isAlive());
//Destroying process once complete to ensure smooth iterations
p.destroy();
} catch (Exception ex) {
System.out.println("Problems with python script execution: " + ex);
}
}
They python code takes in a WAV file (pythonInputPath) that is a product of earlier part of the application, an Integer[] that usually includes ~20 values (pythonCommandString), and a single iteration integer (y).
The first call to .isAlive() is true and the second is false as expected however the script normally creates a CSV that should be output to a bin file that exists in the working director and that fails to occur when running from Java. From other examples I expected using the Process builder as opposed to the Runtime stream to work, however, there is no difference in my implementation.
Do not concatenate the program with its arguments. Quoting Oracle ProcessBuilder docs
Each process builder manages these process attributes: a command, a
list of strings which signifies the external program file to be
invoked and its arguments, if any
and
ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
Just use the constructor you use, but pass each argument as a separate string, otherwise the OS will try to find an application that is named as a whole command line you gave, and obviously there is no such program

Create a stoppable java program (daemon)

Starting a java command line application is easy, you only have to write the following line in a command prompt (in the directory where the app is located).
java myApp.java
However, to stop the application in the right way, so that you ensure that all unmanaged resources are cleaned (and anything that must be done before stop, will be done) requires custom code.
The app will run in a debian system with no GUI as a daemon (it will run in background).
Here below I write the skeleton of the code.
public class MainClass {
public static void main(String[] args) throws Exception {
boolean stop = false;
while(!stop){
doSomething();
}
stop();
}
private static void doSomething(){
//Main code of app here
}
private static void stop(){
beforeStop();
System.exit(0);
}
private static void beforeStop(){
clean();
//Code to do anything you have to do before stop
}
private static void clean(){
//Code to clean unmanaged resources
}
}
As you can see, the app will run 24/24 and won't stop until you don't stop it.
Killing the process (as some people suggest) is not a good solution, because (for example) some unmanaged resources might not be cleaned properly.
I need a code which makes possible to alter the boolean variable "stop" from OUTSIDE.
The best solution is the one which makes possible to stop the app with a command similar to the start command, see pseudo code below (executed in a command prompt, in the directory where myApp.java is located).
myApp.java stop=true
But if it's not possible, the second option would be to have an other java command line app, which stops myApp.java, so that I could stop myApp.java with the following code
java stopMyApp.java
Is someone able to suggest a useful code example?
You can use a text file with one word. Your program reads it every x seconds and depending on that word it will autostop.
You can change the file text content by hand or with another program you can run whenever you want.
Even better you can use WatchService API (Java 7) or VFS API from Apache Commons to be notified when the file changes.
If you use a DB you can use it instead of a plain file.

Running external executable file (.exe) and waiting for it to finish

I have been trying to run an executable file and waiting for it to finish running and it's in a loop so it runs multiple times. I just can't get it running and waiting. I have tried to add a buffer to my program as well stacktrace.
The file I want to run is an executable in my C drive as you can see below in my code. The executable grabs inputs from another text file, which is what I am modifying before I run the executable. The text file has more than 100 chemical species and over a thousand reactions that are ran through the executable. What I want to do is modify the inputs with the outputs produced from the executable. The funny thing is is that the executable outputs to the same file.
That was just to give some background on what the executable file does. That is why I have it in a loop because I am running these reactions at fractions of a second where I will grab the outputs and place them into another text file for later data analysis. But at the current moment it seems that all the methods and codes I have tried to get the executable just doesn't work, and it might even be because of the waitFor function. I just honestly don't know what else to do, and I don't know how to be more specific with my problem. I am a java newbie and need some guidance in what I will need to do to further my progress.
while(finalTime < 1.0){
try{
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("C:file",
null, new File("C:file"));
int exitVal = pr.waitFor();
System.out.println("Exited with error code "+exitVal + "intital:" + initialTime + ", finalTime:" + finalTime);
pr.destroy() ;
}catch(IOException | InterruptedException pr){
pr.printStackTrace()
}
initialTime+= 0.10;
finalTime+=0.10;
updateTime();
}
any suggestions?
Take a look at http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
You probably fill up the buffer.

Eclipse program arguments not working (java)?

I usually run this program via a command line like so:
java Program <TestClass.java
Which as I understand, forces the contents of TestClass.java to the console as user input.
i.e. It would be like executing
java Program
and then typing what ever is in TestClass.java
My problem is getting this happening in Eclipse. I can't figure out how to do it.
I would have thought that adding
<TestClass.java
to the program arguments in the run configuration would work, but it seems not.
Any suggestions?
How about adding this on top of your main.
InputStream in;
if (args.length > 0) {
in = new FileInputStream(args[0]);
} else {
// fallback
in = System.in;
}
And then you add the filename as an argument, as if you're running java Program TestClass.java. This way, it will work whether you run it as before or using the filename as an argument.

How can I restart a Java application?

How can I restart a Java AWT application? I have a button to which I have attached an event handler. What code should I use to restart the application?
I want to do the same thing that Application.Restart() do in a C# application.
Of course it is possible to restart a Java application.
The following method shows a way to restart a Java application:
public void restartApplication()
{
final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
final File currentJar = new File(MyClassInTheJar.class.getProtectionDomain().getCodeSource().getLocation().toURI());
/* is it a jar file? */
if(!currentJar.getName().endsWith(".jar"))
return;
/* Build command: java -jar application.jar */
final ArrayList<String> command = new ArrayList<String>();
command.add(javaBin);
command.add("-jar");
command.add(currentJar.getPath());
final ProcessBuilder builder = new ProcessBuilder(command);
builder.start();
System.exit(0);
}
Basically it does the following:
Find the java executable (I used the java binary here, but that depends on your requirements)
Find the application (a jar in my case, using the MyClassInTheJar class to find the jar location itself)
Build a command to restart the jar (using the java binary in this case)
Execute it! (and thus terminating the current application and starting it again)
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
StringBuilder cmd = new StringBuilder();
cmd.append(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java ");
for (String jvmArg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
cmd.append(jvmArg + " ");
}
cmd.append("-cp ").append(ManagementFactory.getRuntimeMXBean().getClassPath()).append(" ");
cmd.append(Main.class.getName()).append(" ");
for (String arg : args) {
cmd.append(arg).append(" ");
}
Runtime.getRuntime().exec(cmd.toString());
System.exit(0);
}
}
Dedicated to all those who say it is impossible.
This program collects all information available to reconstruct the original commandline. Then, it launches it and since it is the very same command, your application starts a second time. Then we exit the original program, the child program remains running (even under Linux) and does the very same thing.
WARNING: If you run this, be aware that it never ends creating new processes, similar to a fork bomb.
Basically, you can't. At least not in a reliable way. However, you shouldn't need to.
The can't part
To restart a Java program, you need to restart the JVM. To restart the JVM you need to
Locate the java launcher that was used. You may try with System.getProperty("java.home") but there's no guarantee that this will actually point to the launcher that was used to launch your application. (The value returned may not point to the JRE used to launch the application or it could have been overridden by -Djava.home.)
You would presumably want to honor the original memory settings etc (-Xmx, -Xms, …) so you need to figure out which settings where used to start the first JVM. You could try using ManagementFactory.getRuntimeMXBean().getInputArguments() but there's no guarantee that this will reflect the settings used. This is even spelled out in the documentation of that method:
Typically, not all command-line options to the 'java' command are passed to the Java virtual machine. Thus, the returned input arguments may not include all command-line options.
If your program reads input from Standard.in the original stdin will be lost in the restart.
Lots of these tricks and hacks will fail in the presence of a SecurityManager.
The shouldn't need part
I recommend you to design your application so that it is easy to clean every thing up and after that create a new instance of your "main" class.
Many applications are designed to do nothing but create an instance in the main-method:
public class MainClass {
...
public static void main(String[] args) {
new MainClass().launch();
}
...
}
By using this pattern, it should be easy enough to do something like:
public class MainClass {
...
public static void main(String[] args) {
boolean restart;
do {
restart = new MainClass().launch();
} while (restart);
}
...
}
and let launch() return true if and only if the application was shut down in a way that it needs to be restarted.
Strictly speaking, a Java program cannot restart itself since to do so it must kill the JVM in which it is running and then start it again, but once the JVM is no longer running (killed) then no action can be taken.
You could do some tricks with custom classloaders to load, pack, and start the AWT components again but this will likely cause lots of headaches with regard to the GUI event loop.
Depending on how the application is launched, you could start the JVM in a wrapper script which contains a do/while loop, which continues while the JVM exits with a particular code, then the AWT app would have to call System.exit(RESTART_CODE). For example, in scripting pseudocode:
DO
# Launch the awt program
EXIT_CODE = # Get the exit code of the last process
WHILE (EXIT_CODE == RESTART_CODE)
The AWT app should exit the JVM with something other than the RESTART_CODE on "normal" termination which doesn't require restart.
Eclipse typically restarts after a plugin is installed. They do this using a wrapper eclipse.exe (launcher app) for windows. This application execs the core eclipse runner jar and if the eclipse java application terminates with a relaunch code, eclipse.exe restarts the workbench. You can build a similar bit of native code, shell script or another java code wrapper to achieve the restart.
Windows
public void restartApp(){
// This launches a new instance of application dirctly,
// remember to add some sleep to the start of the cmd file to make sure current instance is
// completely terminated, otherwise 2 instances of the application can overlap causing strange
// things:)
new ProcessBuilder("cmd","/c start /min c:/path/to/script/that/launches/my/application.cmd ^& exit").start();
System.exit(0);
}
/min to start script in minimized window
^& exit to close cmd window after finish
a sample cmd script could be
#echo off
rem add some sleep (e.g. 10 seconds) to allow the preceding application instance to release any open resources (like ports) and exit gracefully, otherwise the new instance could fail to start
sleep 10
set path=C:\someFolder\application_lib\libs;%path%
java -jar application.jar
sleep 10 sleep for 10 seconds
Just adding information which is not present in other answers.
If procfs /proc/self/cmdline is available
If you are running in an environment which provides procfs and therefore has the /proc file system available (which means this is not a portable solution), you can have Java read /proc/self/cmdline in order to restart itself, like this:
public static void restart() throws IOException {
new ProcessBuilder(getMyOwnCmdLine()).inheritIO().start();
}
public static String[] getMyOwnCmdLine() throws IOException {
return readFirstLine("/proc/self/cmdline").split("\u0000");
}
public static String readFirstLine(final String filename) throws IOException {
try (final BufferedReader in = new BufferedReader(new FileReader(filename))) {
return in.readLine();
}
}
On systems with /proc/self/cmdline available, this probably is the most elegant way of how to "restart" the current Java process from Java. No JNI involved, and no guessing of paths and stuff required. This will also take care of all JVM options passed to the java binary. The command line will be exactly identical to the one of the current JVM process.
Many UNIX systems including GNU/Linux (including Android) nowadays have procfs However on some like FreeBSD, it is deprecated and being phased out. Mac OS X is an exception in the sense that it does not have procfs. Windows also does not have procfs. Cygwin has procfs but it's invisible to Java because it's only visible to applications using the Cygwin DLLs instead of Windows system calls, and Java is unaware of Cygwin.
Don't forget to use ProcessBuilder.inheritIO()
The default is that stdin / stdout / stderr (in Java called System.in / System.out / System.err) of the started Process are set to pipes which allow the currently running process to communicate with the newly started process. If you want to restart the current process, this is most likely not what you want. Instead you would want that stdin / stdout / stderr are the same as those of the current VM. This is called inherited. You can do so by calling inheritIO() of your ProcessBuilder instance.
Pitfall on Windows
A frequent use case of a restart() function is to restart the application after an update. The last time I tried this on Windows this was problematic. When overwrote the application's .jar file with the new version, the application started to misbehave and giving exceptions about the .jar file. I'm just telling, in case this is your use case. Back then I solved the issue by wrapping the application in a batch file and using a magic return value from System.exit() that I queried in the batch file and had the batch file restart the application instead.
Although this question is old and answered, I've stumbled across a problem with some of the solutions and decided to add my suggestion into the mix.
The problem with some of the solutions is that they build a single command string. This creates issues when some parameters contain spaces, especially java.home.
For example, on windows, the line
final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
Might return something like this:C:\Program Files\Java\jre7\bin\java
This string has to be wrapped in quotes or escaped due to the space in Program Files. Not a huge problem, but somewhat annoying and error prone, especially in cross platform applications.
Therefore my solution builds the command as an array of commands:
public static void restart(String[] args) {
ArrayList<String> commands = new ArrayList<String>(4 + jvmArgs.size() + args.length);
List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
// Java
commands.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
// Jvm arguments
for (String jvmArg : jvmArgs) {
commands.add(jvmArg);
}
// Classpath
commands.add("-cp");
commands.add(ManagementFactory.getRuntimeMXBean().getClassPath());
// Class to be executed
commands.add(BGAgent.class.getName());
// Command line arguments
for (String arg : args) {
commands.add(arg);
}
File workingDir = null; // Null working dir means that the child uses the same working directory
String[] env = null; // Null env means that the child uses the same environment
String[] commandArray = new String[commands.size()];
commandArray = commands.toArray(commandArray);
try {
Runtime.getRuntime().exec(commandArray, env, workingDir);
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
If you realy need to restart your app, you could write a separate app the start it...
This page provides many different examples for different scenarios:
http://www.rgagnon.com/javadetails/java-0014.html
Similar to Yoda's 'improved' answer, but with further improvements (both functional, readability, and testability). It's now safe to run, and restarts for as as many times as the amount of program arguments given.
No accumulation of JAVA_TOOL_OPTIONS options.
Automatically finds main class.
Inherits current stdout/stderr.
public static void main(String[] args) throws Exception {
if (args.length == 0)
return;
else
args = Arrays.copyOf(args, args.length - 1);
List<String> command = new ArrayList<>(32);
appendJavaExecutable(command);
appendVMArgs(command);
appendClassPath(command);
appendEntryPoint(command);
appendArgs(command, args);
System.out.println(command);
try {
new ProcessBuilder(command).inheritIO().start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
private static void appendJavaExecutable(List<String> cmd) {
cmd.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
}
private static void appendVMArgs(Collection<String> cmd) {
Collection<String> vmArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
String javaToolOptions = System.getenv("JAVA_TOOL_OPTIONS");
if (javaToolOptions != null) {
Collection<String> javaToolOptionsList = Arrays.asList(javaToolOptions.split(" "));
vmArguments = new ArrayList<>(vmArguments);
vmArguments.removeAll(javaToolOptionsList);
}
cmd.addAll(vmArguments);
}
private static void appendClassPath(List<String> cmd) {
cmd.add("-cp");
cmd.add(ManagementFactory.getRuntimeMXBean().getClassPath());
}
private static void appendEntryPoint(List<String> cmd) {
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
StackTraceElement stackTraceElement = stackTrace[stackTrace.length - 1];
String fullyQualifiedClass = stackTraceElement.getClassName();
String entryMethod = stackTraceElement.getMethodName();
if (!entryMethod.equals("main"))
throw new AssertionError("Entry point is not a 'main()': " + fullyQualifiedClass + '.' + entryMethod);
cmd.add(fullyQualifiedClass);
}
private static void appendArgs(List<String> cmd, String[] args) {
cmd.addAll(Arrays.asList(args));
}
V1.1 Bugfix: null pointer if JAVA_TOOL_OPTIONS is not set
Example:
$ java -cp Temp.jar Temp a b c d e
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b, c, d]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b, c]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a, b]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp, a]
[/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java, -cp, Temp.jar, Temp]
$
I was researching the subject myself when came across this question.
Regardless of the fact that the answer is already accepted, I would still like to offer an alternative approach for completeness. Specifically, Apache Ant served as a very flexible solution.
Basically, everything boils down to an Ant script file with a single Java execution task (refer here and here) invoked from a Java code (see here). This Java code, which can be a method launch, could be a part of the application that needs to be restarted. The application needs to have a dependency on the Apache Ant library (jar).
Whenever application needs to be restarted, it should call method launch and exit the VM. The Ant java task should have options fork and spawn set to true.
Here is an example of an Ant script:
<project name="applaucher" default="launch" basedir=".">
<target name="launch">
<java classname="package.MasinClass" fork="true" spawn="true">
<jvmarg value="-splash:splash.jpg"/>
<jvmarg value="-D other VM params"/>
<classpath>
<pathelement location="lib-1.jar" />
...
<pathelement location="lib-n.jar" />
</classpath>
</java>
</target>
</project>
The code for the launch method may look something like this:
public final void launch(final String antScriptFile) {
/* configure Ant and execute the task */
final File buildFile = new File(antScriptFile);
final Project p = new Project();
p.setUserProperty("ant.file", buildFile.getAbsolutePath());
final DefaultLogger consoleLogger = new DefaultLogger();
consoleLogger.setErrorPrintStream(System.err);
consoleLogger.setOutputPrintStream(System.out);
consoleLogger.setMessageOutputLevel(Project.MSG_INFO);
p.addBuildListener(consoleLogger);
try {
p.fireBuildStarted();
p.init();
final ProjectHelper helper = ProjectHelper.getProjectHelper();
p.addReference("ant.projectHelper", helper);
helper.parse(p, buildFile);
p.executeTarget(p.getDefaultTarget());
p.fireBuildFinished(null);
} catch (final BuildException e) {
p.fireBuildFinished(e);
}
/* exit the current VM */
System.exit(0);
}
A very convenient thing here is that the same script is used for initial application start up as well as for restarts.
Old question and all of that. But this is yet another way that offers some advantages.
On Windows, you could ask the task scheduler to start your app again for you. This has the advantage of waiting a specific amount of time before the app is restarted. You can go to task manager and delete the task and it stops repeating.
SimpleDateFormat hhmm = new SimpleDateFormat("kk:mm");
Calendar aCal = Calendar.getInstance();
aCal.add(Calendar.SECOND, 65);
String nextMinute = hhmm.format(aCal.getTime()); //Task Scheduler Doesn't accept seconds and won't do current minute.
String[] create = {"c:\\windows\\system32\\schtasks.exe", "/CREATE", "/F", "/TN", "RestartMyProg", "/SC", "ONCE", "/ST", nextMinute, "/TR", "java -jar c:\\my\\dev\\RestartTest.jar"};
Process proc = Runtime.getRuntime().exec(create, null, null);
System.out.println("Exit Now");
try {Thread.sleep(1000);} catch (Exception e){} // just so you can see it better
System.exit(0);
System.err.println("Someone is Restarting me...");
setVisible(false);
try {
Thread.sleep(600);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
setVisible(true);
I guess you don't really want to stop the application, but to "Restart" it. For that, you could use this and add your "Reset" before the sleep and after the invisible window.

Categories

Resources