How To Call A Method After A Certain Period - java

I have a MySQL database running on my localhost. To this database I have JDBC-connection. Over a RESTful WebService a softwareagent puts results into this database. I implemented a garbage collector in Java and want to execute that garbage collector after a certain period. My aim is that I do not have too many entries in the table.
The Garbage Collector looks as follows:
public void collectGarbageResults() {
ArrayList<Integer> ids = new ArrayList<Integer>();
ResultSet rs = this.execQuery("SELECT * FROM results");
try {
while (rs.next()) {
if ( (System.currentTimeMillis()) - (Timestamp.valueOf(rs.getString("tmstmp")).getTime()) > Long.parseLong(appconfigs.get("resultstableactuality")) ) {
ids.add(rs.getInt("id"));
}
}
for (Integer i : ids) {
this.deleteResultsWhereId(i);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
The method I call looks as follows:
private void deleteResultsWhereId(int id) {
retint = this.updateQuery("DELETE FROM results WHERE id=" + id + ";");
}
I am using JSF in an Eclipse's Dynamic Web Project and these methods are implemented in a managed bean. I am going to store the interval in an XML-file which I use for my application's configuration. Over the variable appconfigs I call the method 'get' and ask for the node containing my interval.
Now my question:
How can I call the method of the garbage collector after a certain period in my WebApp?
If you have any questions do not hesitate to comment.
My Solution :
#WebListener
public class BackgroundJobManager implements ServletContextListener{
private ScheduledExecutorService scheduler;
#Override
public void contextInitialized(ServletContextEvent event) {
long delayToStart = 0;
long numberOfUnits = 60;
TimeUnit tu = TimeUnit.SECONDS;
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new ExecuteGarbageCollector(), delayToStart, numberOfUnits, tu);
}
#Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
The class I call implements Runnable as follows:
public class ExecuteGarbageCollector implements Runnable{
#Override
public void run() {
DAO dao = new DAO();
dao.collectGarbageResults();
}
}

You could use ScheduledExecutorService or Quartz
Quartz has a lot of facilities, but If you choose ScheduledExecutorService you don't have to add any new dependencies to your project. and as you just want this scheduled task, it's simple.
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(...);
Take a look at some comments about both in: Quartz vs. ScheduledExecutorService in Java web application

Check out a scheduler library. You can use Quartz for example.
Call Java from MySQL. You could either have this kicked off by a job or trigger
Just stick to SQL and ignore running this in Java. Probably the easiest if you are good at SQL. Then you can encapsulate this in a SPROC or trigger.
It's your choice whether this should live in your web-app or in your database. I've used both methods for executing timed SQL calls and tend to prefer the code oriented approach

The actual question could have well been how to call a function after a specific interval of time?
Take a look at :
How to call a method after some specific interval of time in Java
and
java: run a function after a specific number of seconds

Related

How to isolate 2 schedulers?

I have a Java application that runs several scheduler to get and provide data to an external application. I will have to add another scheduler to get data from another external application. That would be the exact same process as one of the scheduler already existing for the first application.
So roughly it would be something like this:
However I have small confidence in the formatting of the data of this second application, I know that they have less verifications that the fist application and I might get funny things. I will obviously put plenty of null/bad format check on my side, but I have to make sure that if they ever send me bad data this doesn't impact my others schedulers.
#EnableScheduling
public class myApp{
#Scheduled(fixedRate = 1000)
public void externalApp1() {
do stuff...
commonMethod();
}
#Scheduled(fixedRate = 1000)
public void externalApp2() {
do stuff...
commonMethod();
}
public void commonMethod(){
doStuff...
}
}
One of my first idea is to put dedicated threads to each scheduler, so that if they send bad data and it ends up killing the thread for whatever reason, it only impacts their own process and not the schedulers for the first external application. I have done this for now based on what I found, I suppose this should work as intended:
#Configuration
#EnableAsync
#EnableScheduling
public class MyApp{
#Scheduled(fixedRate = 1000)
#Async(value = "threadPool1")
public void externalApp1() {
dostuff...
commonMethod();
}
#Scheduled(fixedRate = 1000)
#Async(value = "threadPool2")
public void externalApp2() {
dostuff...
commonMethod();
}
public void commonMethod(){
doStuff...
}
#Bean
public Executor threadPool1() {
return Executors.newFixedThreadPool(1);
}
#Bean
public Executor threadPool2() {
return Executors.newFixedThreadPool(1);
}
}
(actual code would be with beans properly separated from main class)
But I am wondering if there is any other way to fully ensure the processes are totally independant from one another?
EDIT: I precise that the data I get from the second application are not used for any process of the first application. It has a process on its own and data are not shared between those 2 external applications

How do I manage hibernate transactions in a timertask?

I am currently trying to make a hibernate query inside of a TimerTask (Runnable). This task makes no saves or updates to the database. It just retrieves a list of jobs. Anytime I run this task, I get HibernateException: Unable to locate current JTA transaction.
I believe this has to do with the fact that it's being started from a runnable because I use this same query outside of this TimerTask.
I can't share the code I am working with because it is for work and proprietary. My research on this issue has only really led me to solutions with Spring, but I am not able to use Spring for this work.
I will attempt to make some pseudo code.
public class JobManager extends TimerTask {
#Override
public void run() {
...
List<String> jobs = Handler.getJobs();
...
}
}
public class Handler {
public static List<String> getJobs() {
return DAO.getJobs();
}
}
public class DAO {
public List<Object> getJobs() {
try {
session = HibernateManager.getSessionFactory().getCurrentSession();
Query myQuery = session.createQuery("query string");
List = myQuery.list();
} catch(HibernateException he) {
log.error(he);
}
return list;
}
}
The exception occurs when the runnable calls getJobs(). This method work everywhere else outside of the TimerTask.
I understand that this is limited information to work with. I can try to accommodate for any other information if it is needed.
I believe every transaction has some time out, so you can not put the regular timer task code inside the running transaction. As it is just reading the data you wont need to start the transaction, just session is enough
I have encountered the same problem and solved by creating the new session
session = sessionFactory.openSession();
EDIT
session.getCurrentSession() takes the current session from the current thread, so it wont work inside timer task. Use openSession()

Reset mysql colum values to default after specific using Servlet

I am new to web development I am making some web services using java servlets, and I am stuck in so many How to do it? stuff :(
I am developing an application in which I need to reset the mysql table column values back to default values at some time let's say we need to reset the counter # every Sunday 10:00 pm.
is there any thing like alarm manager in Java or mysql that can run all the time in background and trigger # specific time.
Thanks,
Java has a good interface ScheduledExecutorService.
You can try this code
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
//every day to execute
long everyDayDelay = 24*60*60*1000;
//first time to execute, it can be your special date
//for example 5 seconds after launch
long timeToExecute = System.currentTimeMillis()+5*1000;
service.scheduleWithFixedDelay(new Task(), getTimeToLaunch(timeToExecute), everyDayDelay, TimeUnit.MILLISECONDS);
where
//return difference between now and timeToExecute
public static long getTimeToLaunch(long timeToExecute){
long current = System.currentTimeMillis();
return timeToExecute - current;
}
class Task implements Runnable{
#Override
public void run() {
System.out.println("Run task!");
}
}
UPDATE: Class to execute your sql-tasks
public class SqlExecutionService1 {
public static final long everyDayDelay = 24*60*60*1000;
public SqlExecutionService1(){
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
//every day to execute
//first time to execute
//for example 5 seconds after launch
long timeToExecute = System.currentTimeMillis()+5*1000;
service.scheduleWithFixedDelay(new SqlTask1(), getTimeToLaunch(timeToExecute), everyDayDelay, TimeUnit.MILLISECONDS);
}
private long getTimeToLaunch(long timeToExecute){
long current = System.currentTimeMillis();
return timeToExecute - current;
}
}
class SqlTask1 implements Runnable{
#Override
public void run() {
//your sql tasks
}
}
To create this class, when your app server starts - use method init() in one of your main servlets.
Example -
public class MainInitServlet extends HttpServlet {
public void init() {
new SqlExecutionService1();
}
}
The Data of a Database should be the basis for calculation, not the result of calculations. In example Bills wont ever be successfully revised.
I guess this fact will ever be a clash between Programmers and Architects.
you might also use the event scheduling mechanism of mysql
this depends on the version of mysql and whether it is enabled or not
is there any thing like alarm manager in Java or mysql that can run all the time in background and trigger # specific time.
look at a API called Quartz , where your program can schedule Jobs and it will run it at that time.
use method execute(JobExecutionContext jobExecution) use to fire trigger.
EG:
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
// Retrieve scheduler
Scheduler scheduler = null;
try {
scheduler = schedulerFactory.getScheduler();
}
catch (SchedulerException e) {
e.printStackTrace();
}
//this is a job
JobDetail job = new JobDetail("jobDetail", "jobDetailGroup", ImplementedJob.class);
SimpleTrigger trigger = new SimpleTrigger("Trigger Name","defaultGroup", DATE);
// schedule
scheduler.scheduleJob(job, trigger);
// start the scheduler
scheduler.start();

Schedule task depending on its response

I'm trying to schedule a task depending on it's response. The task is something like:
public Date scheduledTask() {
Date nextRun;
// ...
nextRun = something();
// ...
return nextRun;
}
How can I make sure that the same task is called again when reaching the nextRun?
Thank you.
This is very simple with standard Quartz scheduler API. Inside your Job compute nextRun time and create a trigger with startAt() defined:
public class ScheduledJob implements Job {
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
final Date nextRun = something();
Trigger trigger = newTrigger().
startAt(nextRun).
forJob(context.getJobDetail()).
build();
context.getScheduler().scheduleJob(trigger);
}
}
Tested, works like a charm.
Follow the ideas mentioned here, then you should be able to have:
public class GuaranteeSchedule implements Trigger {
private Future<?> resultForNextRun;
private TaskScheduler scheduler;
public void scheduledTask() {
// 'this' is this trigger that is used by the scheduler
// and the method `nextExecutionTime` is automatically called by the scheduler
resultForNextRun = scheduler.schedule(theTask, this);
// theTask is the object that calls something()
}
// Implementing Trigger to add control dynamic execution time of this trigger
#Override
public Date nextExecutionTime(TriggerContext tc) {
// make sure the result for the previous call is ready using the waiting feature of Future
Object result = resultForNextRun.get();
// Use tc or other stuff to calculate new schedule
return new Date();
}
}
The rest, you should follow the configuration mentioned in the reference. I believe this would resolve the problem of depending the next call of a trigger on the result of the previous. You may also need to be careful about the first call of scheduledTask to make sure resultForNextRun != null.

Spring Tests : transaction not rolling back after test method executed

I'm trying to create integration tests for a legacy application deployed on Weblogic 8.1 using a subclass of AbstractTransactionalJUnit4SpringContextTests.
My test method has the following annotations :
#Test
#Rollback(true)
public void testDeployedEJBCall throws Exception {...}
My test class also references beans of type org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean, which proxy the EJBs deployed on my weblogic server.
When I call methods on this proxy bean in a sequencial manner in my test method, the transaction rolls back correctly at the end of the test.
e.g. :
#Test
#Rollback(true)
public void testDeployedEJBCall throws Exception {
Long result1 = myejb.method(100L);
Long result2 = myejb.method(200L);
...
}
However, I would like to make 2 parallel calls to the same EJB method. Therefore I've made an inner class that implements Callable, in order to call my methods in 2 different Threads and hope to run those in parallel.
However, doing this seems to make the ejb methods to be called outside my transaction, and nothing is rolled back.
Here is what the full test class would like when I run the method calls in parallel :
import org.springframework.test.annotation.*;
#RunWith(SpringJUnit4ClassRunner.class)
#Transactional
#ContextConfiguration(locations = {"classpath:path/to/tests-config.xml"})
#TransactionConfiguration(defaultRollback=true)
public final class IntegrationTests extends AbstractTransactionalJUnit4SpringContextTests {
#Autowired
protected JndiTemplate jndiTemplate;
#Resource
protected Proxy myEJB;
public IntegrationTests() {
super();
this.logger = Logger.getLogger(IntegrationTests.class);
}
#Test
#Rollback(true)
public void testDeployedEJBCall() throws Exception {
// Create a thread pool for parallel execution.
ExecutorService exec = Executors.newFixedThreadPool(2);
// Prepare the tasks for parallel execution
List<CallEJBTask> tasks = new ArrayList<CallEJBTask>();
tasks.add(new CallEJBTask(100L, this.myEJB));
tasks.add(new CallEJBTask(200L, this.myEJB));
// Execute all pending tasks in the exec Threadpool
List<Future<Long>> results = exec.invokeAll(tasks);
// Get the results of each task
Long result1 = results.get(0).get();
Long result2 = results.get(1).get();
...
}
}
private class CallEBJTask implements Callable<Long> {
private final Long valueToTest;
private final MyEJB myEJB;
public CallEJBTask(Long valueToTest, Proxy myEJBProxy)
this.valueToTest = valueToTest;
this.myEJB = (MyEJB)myEJBProxy;
}
public Long call() throws Exception {
return getResult();
}
public Long getResult() {
Long result = null;
try {
result = this.myEJB.method(this.patient);
} catch (Exception e) {
...
}
return result;
}
}
Is there a way to make this rollback ???
Thanks for your help.
Regards,
Philippe
Not automatically, no. The problem is that the two extra threads don't participate in the transaction, hence their actions don't rollback.
What is the purpose of the two parallel executions? You will unlikely be able to test for concurrency issues with this approach, if that is what you're aiming for.
Edit: The problem is that testing for concurrency issues is very hard, because your tests are, at best, probabilistic ­­­­– success or failure depend on subtle timing issues that may only surface on the billionth run. See this Serverside article for a good summary of the basics.
The rule of thumb should be to avoid hand-coding threading whenever possible, as it is hard to get right and difficult to test. If you can, avoid shared state between threads, and if there is no way around it, rely on the concurrent data structures and asynchronous executors from the java.util.concurrent package.

Categories