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
anshumaEngineeringAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Amitkumar PSr. ConsultantCommented:
Many ways to do so. Below is the simple and basic, not the best.

Initiate a thread that will remain in sleep for specified duration (based on the parameter) prior to invoke a shell process.

Pseudocode would be like below (assuming doGet will invoke shell process):


public class YourServlet implements HttpServlet() {

    public void doGet(request, response) {
       int interval = get parameter from request;

       Runnable shellProcessor = new ShellProcessor(interval);
        Thread t = new Threand(shellProcesser);
        t.start();
    }
}

class ShellProcessor implements Runnable {

    int _interval = 0;
    public ShellProcessor(int interval) {
        this._interval = interval;
    }


    public void run() {
        Thread.sleep(this._interval);
        // invoke shell process here.
    }
}


Hope it helps.
CEHJCommented:
Better not reinvent the wheel. Use a scheduler

http://www.quartz-scheduler.org/
dpearsonCommented:
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
Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

CEHJCommented:
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.
anshumaEngineeringAuthor Commented:
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
dpearsonCommented:
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
dpearsonCommented:
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
anshumaEngineeringAuthor Commented:
@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
anshumaEngineeringAuthor Commented:
@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
CEHJCommented:
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
anshumaEngineeringAuthor Commented:
@CEHJ do you want me to create another thread for the quartz scheduler question i posted above
CEHJCommented:
You can if you want. It might attract more with Quartz experience
dpearsonCommented:
then how can I do it without creating multiple threads
You can submit multiple tasks (from the array) all at the same time and it will call them back at the correct time.  No need for multiple threads.

Here's an example where the start method now schedules 3 tasks all at once and they happen later.

public class ScheduledTest {
	private static ScheduledThreadPoolExecutor m_executor = new ScheduledThreadPoolExecutor(1);

	private static class Task implements Runnable {
		private String m_Name ;

		public Task(String name) {
			m_Name = name ;
		}

		public void run() {
			System.out.println("Time for " + m_Name + " is " + new Date());
		}
	}

	public void start() {
		System.out.println("Started at         " + new Date());
		// Note that the order of these doesn't matter - so we'll schedule the third task first
		// but it will execute last - because it has the longest delay
		m_executor.schedule(new Task("Third "), 30, TimeUnit.SECONDS);
		m_executor.schedule(new Task("First "), 10, TimeUnit.SECONDS);
		m_executor.schedule(new Task("Second"), 20, TimeUnit.SECONDS);
	}

	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 - each happening after the expected delay and all setup at the start with no need for extra threads:

Started at         Fri Oct 30 15:37:15 PDT 2015
Time for First  is Fri Oct 30 15:37:25 PDT 2015
Time for Second is Fri Oct 30 15:37:35 PDT 2015
Time for Third  is Fri Oct 30 15:37:45 PDT 2015

Doug

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
anshumaEngineeringAuthor Commented:
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
dpearsonCommented:
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
anshumaEngineeringAuthor Commented:
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 !!!
dpearsonCommented:
Yep you should be all set to go to massive scale.
anshumaEngineeringAuthor Commented:
Hi Doug and CEHJ

I have posted another question in reference to this

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

thanks
-anshu
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.