I am currently trying to create a scheduled task, that runs my Jar file every minute. the command line code to create the task looks like this:
schtasks /Create /tn Testname /sc Minute /tr C:\Users\MyUser\Desktop\Program.jar
no matter how long I wait, nothing happens. The Scheduled Task GUI shows that the result of my task is (0x1)
Howwever if I run C:\Users\MyUser\Desktop\Program.jar in the CMD everything works fine
What am I doing wrong?
I was able to create the scheduled task via Java, I dont know if this will help somebody in the future, but just in case I am gonna post my code anyway:
private void createScheduledTask(String taskName) {
List<String> commandList = new ArrayList<String>();
commandList.add("schtasks.exe");
commandList.add("/Create");
commandList.add("/tn");
commandList.add(taskName);
commandList.add("/sc");
commandList.add("Minute");
commandList.add("/tr");
commandList.add("java -jar C:\\Users\\MyUser\\Desktop\\Program.jar REPLACE_WITH_ARGUMENT");
try {
int returnValue = executeCMDStatement(commandList);
if(returnValue == 0){
//everything should have worked out
} else {
//there was an error
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static int executeCMDStatement(List<String> commandList) throws InterruptedException, IOException {
ProcessBuilder builder = new ProcessBuilder(commandList);
Process process = builder.start();
process.waitFor(3, TimeUnit.SECONDS);
return process.exitValue();
}
Related
I have a batch file which is running through windows task scheduler and it will he execute the jar file every 10 hours repeately.
Now, I'm trying to run the same batch file using spring boot batch process as a task scheduler. but i didn't get solution for this.
How can i resolve the this issue?
In your schedule method, try like this:
Runtime.getRuntime().exec("file.bat");
Did you try this https://spring.io/guides/gs/scheduling-tasks/
Spring Boot scheduler can schedule your tasks and accepts CRON like expression to scheduling recurring tasks.
You can use Java ProcessBuilder API to trigger your batch (.bat) file
You can implement simple Spring scheduling tasks as following
#Component
public class RunCommandScheduledTask {
private final ProcessBuilder builder;
private final Logger logger; // Slf4j in this example
// inject location/path of the bat file
#Inject
public RunCommandScheduledTask(#Value("${bat.file.path.property}") String pathToBatFile) {
this.builder = new ProcessBuilder(pathToBatFile);
this.logger = LoggerFactory.getLogger("RunCommandScheduledTask");
}
// cron to execute each 10h
#Scheduled(cron = "0 */10 * * *")
public void runExternalCommand() {
try {
final Process process = builder.start();
if (logger.isDebugEnabled()) {
// pipe command output and proxy it into log
try (BufferedReader out = new BufferedReader(
new InputStreamReader(process.getInputStream(), StandardCharsets.ISO_8859_1))) {
String str = null;
for (;;) {
str = out.readLine();
if (null == str)
break;
logger.debug(str);
}
}
}
process.waitFor();
} catch (IOException exc) {
logger.error("Can not execute external command", exc);
} catch (InterruptedException exc) {
Thread.currentThread().interrupt();
}
}
}
.....
#SpringBootApplication
#EnableScheduling
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class);
}
}
I have a java program:
public class ProcessMain {
public static final void main(String[] args) throws Exception {
Scanner keyboard = new Scanner(System.in);
boolean exit = false;
do
{ if(keyboard.hasNext()){
String input = keyboard.next();
System.out.println(input);
if( "abort".equals(input)){
ABORT();
exit = true;
}
}else{
System.out.println("Nothing");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}while (!exit);
}
private static void ABORT(){
System.out.println("ABORT!!!!");
}
}
In Linux, a script:
rm testfifo
mkfifo testfifo
cat > testfifo &
echo $!
java -cp "Test.jar" com.example.ProcessMain < testfifo
Terminal A runs the script, "Nothing" can be printed every 5 seconds.
And then Terminal B execute echo "abort" >testfifo, but the program cannot display ABORT, it still displays Nothing every 5 seconds.
Please help!!
If you only need an external trigger to stop current processing. You might create a semaphore file and stop as soon it is created by another process.
See the following snippet.
// it will check for the file in the current directory
File semaphore = new File("abort.semaphore");
semaphore.deleteOnExit();
System.out.println("run until exist: " + semaphore);
while (!semaphore.exists()) {
System.out.println("Nothing");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("ABORT!!!!");
As long the file abort.semaphore does not exist, the program will print to the console and wait five seconds.
edit On Linux you might use a signal handler and send an SIGABRT to the running process.
the following snippet uses an internal proprietary API
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class SigAbrt {
private static volatile boolean abort = false;
public static void main(String[] args) throws Exception {
Signal.handle(new Signal("ABRT"), new SignalHandler () {
public void handle(Signal sig) {
System.out.println("got a SIGABRT");
abort = true;
}
});
for(int i=0; i<100; i++) {
Thread.sleep(1000);
System.out.print('.');
if (abort) {
System.out.println("ABORT");
break;
}
}
}
}
run it
session one
java SigAbrt
session two
// first find the PID of SigAbrt
jps
example output of session two
2323 Jps
4242 SigAbrt
now send a SIGABRT to the SigAbrt process
kill -s SIGABRT 4242
example output of session one
...........got a SIGABRT
.ABORT
Program not printing on console might be because of your testfifo file is empty.
Try this:
printf "Hello\nMy\nFriend\nabort" > testfifo
java -cp "Test.jar" com.example.ProcessMain < testfifo
It will work.
This question already has an answer here:
How to show a progress bar while downloading in javafx
(1 answer)
Closed 7 years ago.
Hello Guys I have a question that how to run the task in background in Javafx
Currently the situation is that I have created a Copy Function in javafx, it is working absolutely fine, but if we have more files, then it goes in not responding mode till the process completes, Logs are also not printed in my textarea, Every file is being copied in the respected folder, but the problem is its hanged till the process completes,
And One more question how to run this program forever means whenever a new file comes in source directory it automatically goes to the destination directory.
Here is my code
try
{
sourceFile = new File(sourcePath).listFiles();
syslog.appendText("\nTotal Files in the Directory : " + sourceFile.length);
for(int i = 0; i<sourceFile.length;i++)
{
if(sourceFile[i].isFile())
{
String file = sourceFile[i].getName();
String extension = Files.getFileExtension(file);
if(!new File(destinationPath+"/"+extension.toUpperCase()).exists())
{
if(new File(destinationPath+"/"+extension.toUpperCase()).mkdir())
{
syslog.appendText("\nDirectory Created : " + destinationPath+"/"+extension.toUpperCase());
try
{
if(!new File(destinationPath+"/"+extension.toUpperCase()+"/"+file).exists())
{
syslog.appendText("\nFile "+file+" is processing to copy to "+destinationPath+"/"+extension.toUpperCase());
copyFile(sourceFile[i],new File(destinationPath+"/"+extension.toUpperCase()+"/"+file));
syslog.appendText("\nFile "+file+" is successfully copied to "+destinationPath+"/"+extension.toUpperCase());
if(sourceFile[i].delete())
syslog.appendText("\nFile "+file+" is successfully deleted from "+sourcePath);
else
syslog.appendText("\nError in deleting File "+file+" from "+sourcePath);
}
}
catch(Exception e)
{
e.printStackTrace();
syslog.appendText("\nSome Error Occurred while copying the File : "+sourceFile[i]);
}
}
}
else
{
try
{
if(!new File(destinationPath+"/"+extension.toUpperCase()+"/"+file).exists())
{
syslog.appendText("\nFile "+file+" is processing to copy to "+destinationPath+"/"+extension.toUpperCase());
copyFile(sourceFile[i],new File(destinationPath+"/"+extension.toUpperCase()+"/"+file));
syslog.appendText("\nFile "+file+" is successfully copied to "+destinationPath+"/"+extension.toUpperCase());
if(sourceFile[i].delete())
syslog.appendText("\nFile "+file+" is successfully deleted from "+sourcePath);
else
syslog.appendText("\nError in deleting File "+file+" from "+sourcePath);
}
}
catch(Exception e)
{
e.printStackTrace();
syslog.appendText("\nSome Error Occurred while copying the File : "+sourceFile[i]);
}
}
}
}
syslog.appendText("\nFinished..........");
}
catch (Exception e)
{
e.printStackTrace();
}
And this is the copy Function
private static void copyFile(File source, File destination)
throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(destination).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
} finally {
inputChannel.close();
outputChannel.close();
}
}
You need to create a Task and add it to a new thread. It looks like this:
Task<T> backgroundTask = new Task<T>() {
#Override
protected T call() throws Exception {
return null;
}
#Override
public void run() {
try {
copyFile(source,destination); //or any other operation you want to have in a thread.
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
Thread backgroundThread = new Thread(backgroundTask);
backgroundThread.setDaemon(true); //true if you want to have it running excuslivly when having your parent-threat running
You can call and run this thread once with
backgroundThread.run();
Futher you can check the state of the thread with
backgroundThread.state();
which could be helpful if you want to check e.g. if your thread is still in process.
Consider collisions with your javafx-thread. If you want to alter a object which is accessed by the javafx-thread you need to perform a
Platform.runLater(new Runnable() {/*your impact on javafx*/});
I Would sugest to use a Task, something like this:
public class CopyFileTask<Void> extends Task<Void> {
#Override
protected void succeeded() {
super.succeeded();
// e.g. show "copy finished" dialog
}
#Override
protected void running() {
super.running();
// e.g. change mouse courser
}
#Override
protected void failed() {
super.failed();
// do stuff if call threw an excpetion
}
#Override
protected Void call() {
// do expensive the expensive stuff
copyStuff(source, destination)
return null ;
}
}
The convenience methods succeeded, running and failed are executed in the JavaFX GUI thread, while the stuff in call is executed in another thread. To run the Task, I would suggest to submit it to an ExecuterService
ExecutorService exService = Executors.newSingleThreadExecutor();
exService.submit(new CopyFileTask());
i want to run a specified file (.exes) in background...
File file = new File ("C:\\Documents and Settings\\INTEL\\My Documents\\NetBeansProjects\\demo\\calc.exe");
Desktop.getDesktop().open(file);
what if i use Runtime stuff
Executes the specified string command in a separate process.
Process process = Runtime.getRuntime().exec("C:\\Documents and Settings\\INTEL\\My Documents\\NetBeansProjects\\demo\\calc.exe");
You could execute your process in another thread
Thread thread = new Thread(){
public void run(){
try {
Runtime.getRuntime().exec("...");
} catch (Exception e) { ... }
}
}
thread.start();
I have a thread in Java which starts a HttpService.
ProcessBuilder pb = new ProceeBuilder(command);
Process process = pb.start();
process.waitFor();
I have another thread which checks if the service is started.
while (result != 0) {
ServerSocket socket = new ServerSocker(port);
socket.close();
result = 0
catch (BindException be) {
result = 1;
}
}
Now I need to somehow get information about whether the service has failed to start or it's successfully started. I need to get this back to the Main class which started both of these threads in order to proceed. Something like
while (!started || !failed) {
wait for getting information from the threads.
}
What can you advise?
Thank you.
How about using a callback that you pass to both threads?
(omitted try-catches)
public class MyCallback {
private Boolean processSuccess;
private Boolean serviceSuccess;
public synchronized void notifyProcessStart(boolean success) {
this.processSuccess = success;
this.notifyAll();
}
public synchronized void notifyServiceCheck(boolean success) {
this.serviceSuccess = success;
this.notifyAll();
}
public synchronized void waitForResult() {
while(processSuccess == null || serviceSuccess == null) {
this.wait();
}
// ... do something good
}
}
I am very sorry but I am afraid that your code that checks that service is started has bug.
This code is running very quickly, starts server socket and immediately closes it. If you mean that this thread should exit when process is started listening to the same port it is wrong. Your process has 50% of chance to start successfully and other 50% to fail because when it is trying to start listening to the port your watch dog is listening to the same port itself.
So, I believe that you should try to run process using ProcessBulder (exactly as you are doing) and then start delayed watchdog task that tries to connect to this port, i.e.
private boolean isServiceRunning() {
int port = 123;
try {
new Socket("localhost", port).close();
return true;
} catch (IOException e) {
return false;
}
}
This method should be called from separate thread. The best way to implement thread is to use some tool that does it for you. In this case java.util.Timer is the best choice. I am suggesting to run periodic task that will call our method isServiceRunning() and cancel itself if result is true:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
if(isServiceRunning()) {
this.cancel();
}
}
}, new Date(), 10000);
But if this solution is not good for you I'd suggest you to implement interthread communication using wait() and notfify(). Do not forget that both must be in synchronized block.
Good luck!
You can try using boolean flags. Adapting your example code:
Thread 1:
ProcessBuilder pb = new ProcessBuilder(command);
Process process = pb.start();
process.waitFor();
if(!wasConnectionEstablished()) {
setConnectionFailed(true);
}
Thread 2:
while ((result != 0) && (!isConnectionFailed())) {
ServerSocket socket = new ServerSocker(port);
socket.close();
result = 0
catch (BindException be) {
result = 1;
wait(timeout);
}
}
if(isConnectionFailed())
throw new ConnectionFailedException();
else setConnectionEstablished(true);
//continue normal execution