Link to home
Start Free TrialLog in
Avatar of Amit
AmitFlag for United States of America

asked on

Triggering a shell command from a java servlet 30 minutes after the http call

Hi,

I want to run a shell process from a servlet. But in the url I can get a delay parameter

http://server//myservlet/executecommand?delay=30 

so depending upon the delay the shell process will be called if it's 10 then 10 minutes after the URL call and if it's 30 then 30 minutes after the URL Call

Any pointers for me to get started
SOLUTION
Avatar of Am P
Am P
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of dpearson
dpearson

Or if you'd rather not pull in a separate library you can use the built in ScheduledThreadPoolExecutor class:

ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(1);
threadPool.schedule(new MyTask(), interval, TimeUnit.MINUTES);

and then execute the command inside MyTask (which is a Runnable).

Doug
Bear in mind that suggestions to use the existing JDK classes could tie the thread of the task to the thread(s) of the context in which it's started, which is problematic.
Avatar of Amit

ASKER

Hi

@CEHJ I will be looking into quartz in the evening in the mean time

the attached file is not sending the email after the delay and I am also getting null exceptions in apache logs (because my runnable is returning a null)

So to test what dpearson has suggested I create a simple send mail program that should send email 2 minutes after the http call. But the email is getting sent instantaneously

amit i will try yours too but dpearson's implementation seemed very simple to test

could the experts please take a look at attached file
SendMail.java
You almost have it.   Your code here:
threadPool.schedule(sendEmail("mail sent", "mail sent"), interval, TimeUnit.MINUTES);

is actually calling the "sendEmail" method immediately.

What you want is to create a new instance of an object which has a "run" method and then the run method will be called in 2 minutes.

Also you should make this
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(1);

a member variable - so it doesn't get garbage collected.

Here's a small example app that shows all of the ideas:

public class ScheduledTest {
        // Static variable so not garbage collected
	private static ScheduledThreadPoolExecutor m_executor = new ScheduledThreadPoolExecutor(1);

	private static class Task implements Runnable {
                // run method will be called later
		public void run() {
			System.out.println("Time is    " + new Date());
		}
	}

	public void start() {
		System.out.println("Started at " + new Date());
		m_executor.schedule(new Task(), 1, TimeUnit.MINUTES);
	}

	public static void main(String[] args) throws InterruptedException {
		ScheduledTest test = new ScheduledTest() ;
		test.start();

		// This is just so the main method doesn't exit while we're waiting for the
		// schedule to run.  You don't need this in a web app since there's no main...
		Thread.sleep(5 * 60 * 1000);
	}
}

Open in new window


Should produce this output:
Started at Thu Oct 29 21:03:07 PDT 2015
Time is    Thu Oct 29 21:04:07 PDT 2015     <-- note: 1 minute later

Hope that helps,

Doug
Bear in mind that suggestions to use the existing JDK classes could tie the thread of the task to the thread(s) of the context in which it's started, which is problematic.
CEHJ - can you say a bit more about your concern here?  I'm assuming the task will execute on a thread from the executor's pool.  Do you see an issue with that?

Doug
Avatar of Amit

ASKER

@Doug thanks a lot for that

@CEHJ I still cannot find a good example of quartz being used for doing a one time delayed task

Here's what I did (see the 2 attached file)

but here while I need the delayed "Hello Quartz" what I don't need is to start the job as soon as it creates the job object

So I don't need the first "Hello Quartz" printed immediately as that will defeat my purpose of needing a delay
SimpleTriggerExample.java
HelloJob.java
Avatar of Amit

ASKER

@doug and @amit how can I do one more thing if in the url parameters I have (this can be n number of delays which I will handle by looking at request array)

delay1=10
delay2=20
delay3=30

then how can I do it without creating multiple threads
CEHJ - can you say a bit more about your concern here?  I'm assuming the task will execute on a thread from the executor's pool.  Do you see an issue with that?
That would be OK if the pool has come from the container. But what if it comes from the servlet the container is executing? I'm thinking of issues like prevention of the servlet being unloaded. It could be OK but i think a division of responsibility is clearer. Spring scheduling might be a better option
Avatar of Amit

ASKER

@CEHJ do you want me to create another thread for the quartz scheduler question i posted above
You can if you want. It might attract more with Quartz experience
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Amit

ASKER

Hi Doug,

How many concurrent requests I can send in this scenario. What I mean to say is that in terms of several requests coming at the same time. Can this code handle it or it needs to be more sophisticated for those kind of scenarios

thanks
-anshu
Each concurrent request (coming in as an HTTP request to the web server) can add a task to the queue.  Adding the task will take almost no time, so there's no limit there on the maximum concurrency.

Later, the scheduled executor will start processing each of those requests (to send off an email).  Currently there is one thread doing this work (the sending of the emails) because we chose a thread pool size of 1:
private static ScheduledThreadPoolExecutor m_executor = 
           new ScheduledThreadPoolExecutor(1);

Open in new window

If you increase this to a larger number, then you could send out more emails at the same time as each "send email" task would execute in parallel on a different thread.

Make sense?

Doug
Avatar of Amit

ASKER

it does make sense, and the thread concurrency etc will be handled by apache/tomcat and my delayed task will fire at the right delayed moment without any issues right !!!
Yep you should be all set to go to massive scale.
Avatar of Amit

ASKER

Hi Doug and CEHJ

I have posted another question in reference to this

https://www.experts-exchange.com/questions/28808959/How-to-create-java-threads-with-multiple-start-and-run-signatures.html

thanks
-anshu