I want to run a method every 22 minutes on a servlet running on Tomcat. So I'm using this code:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
try {
update();
} catch (SQLException | NamingException | InterruptedException e1) {
e1.printStackTrace();
}
}
}, 22 * 60 * 1000, 22 * 60 * 1000);
I've got a feeling this is a terrible way to do it as I'm getting errors all the time regarding timers, and whenever I uploaded a new version of the servlet I don't think it stops the previous timer. I then get database connection warnings. If I reset everything and start fresh its fine.
javax.naming.NameNotFoundException: Name comp is not bound in this Context
at org.apache.naming.NamingContext.lookup(NamingContext.java:770)
at org.apache.naming.NamingContext.lookup(NamingContext.java:153)
at org.apache.naming.SelectorContext.lookup(SelectorContext.java:152)
at javax.naming.InitialContext.lookup(InitialContext.java:411)
at my.app.database.DatabaseManager.connect(DatabaseManager.java:44)
at my.app.database.DatabaseManager.returnInfo(DatabaseManager.java:133)
at my.app.genParse.Generate.updateHistory(Generate.java:89)
at my.app.MyServer$1.run(MyServer.java:52)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
And also on re-launch with the new version:
SEVERE: The web application [/myApp] appears to have started a thread named [Timer-7] but has failed to stop it. This is very likely to create a memory leak.
Whats a better way to achieve or avoid this?
An alternative to using timer tasks has been discussed here. Using the ScheduledThreadpoolExecutor class MAY help with the problem of having multiple threads still running when you upload a new version however I cannot say for sure that it will. This class is also preferred over the Timer class for various reasons discussed in the javadoc.
You shouldnt really use a Timer within a container - Timer spawn/reuse a thread thats managed outside of the container and this can cause problems.
Note too that as Timer uses a single thread if one instance of it takes too long the others accuracy can suffer.
Finally, if a Timer throws an unchecked exception the Timer thread is terminated.
For these (and other) reasons it has largely fallen out of favour - ScheduledThreadPoolExecutor is a better choice.
Again though, user managed threads within a container can be tricky. JSR-236 (Concurrency Utilities for the Java EE platform) will provide a mechanism to do so in the future, but for now its best avoided.
You can try schedule repeatable tasks via cron perhaps that could in turn call a dedicated servlet (or similar) on a regular basis
Use a ServletContextListener to start and stop your Timer when the web application starts and stops.
Related
I'm developing a JavaFX app with Java 8 and for api requests I'm using retrofit 2.1.0 with converter-gson 2.1.0.
If I make the synchronous request:
Patient p = Core.api.getPatient(2).execute().body();
Everything works fine, but if I do the asynchronous version:
Core.api.getPatient(2).enqueue(new Callback<Patient>() {
#Override
public void onResponse(Call<Patient> call, Response<Patient> response) {
System.out.println("DONE");
}
#Override
public void onFailure(Call<Patient> call, Throwable t) {
// Nothing
}
});
Everything also works out correctly (it prints "DONE"). However when I quit the application using the standard JavaFX call Platform.exit() the UI closes but the application lingers open still and will only exit after ~40 seconds.
If I just do System.exit(0) everything works as intended so I'm guessing this might be some threading issue but I'm not sure.
Anyone have an idea on what might be wrong?
EDIT:
I found out that after doing Platform.exit() a few threads, with names like RMI TCP Connection(2) keep alternating and using 100% of the CPU.
OkHttp uses two thread pools that keep threads alive for 60 seconds after use. You can shut em down with force by calling shutdown on the dispatcher's executor and by calling evictAll on the connection pool.
I am having some problems when I try to implement a new function in my working servlet.
Now I have a servlet in which mobile phones can register. Mobile phones use rest to register against this servlet. And it works perfect. Anytime you try to register a phone, it works.
But now, I need to add a new functionality. I want to register this server against other component of my infrastructure.
I want that registration done at the very beggining. I mean, when the servlet starts, make the registration and forget about it, just work as it did before.
This is the error tomcat gives me:
Grave: The web application [/servletRegister] appears to have started a thread named [Timer-8] but has failed to stop it. This is very likely to create a memory leak.
This is my start class:
#Override
public Set<Class<?>> getClasses() {
//-------------------------------
//Set registration here
//GatewayRegistrationHandler reg = GatewayRegistrationHandler.getInstance();
//reg.registerDevice();
//-------------------------------
//register on a new thread due to process time
new Thread (new RegisterGatewayOnBackground()).start();
//Next are the working servlet code
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(PublicationsResource.class); /
classes.add(DeviceResource.class);
return classes;
}
}
I tried the commented lines firstly. Then I got a memory leak and I tried to execute them in a new thread trying to avoid the leak. But the behavior is the same.
The background function is this:
public class RegisterGatewayOnBackground implements Runnable {
public RegisterGatewayOnBackground() {
}
public void run() {
registerDevice();
}
private void registerDevice() {
GatewayRegistrationHandler reg = GatewayRegistrationHandler.getInstance();
reg.registerDevice();
}
}
GatewayRegistrationHandler works fine because when I run the servlet, it executes, makes the registration and then, after that, crash. I thought it was a time problem and background would solve it but I am stuck here since background does the same.
I don't know any way to check where to find my memory leak. I am looking for advice or any tools which might help me solve the problem.
When you start your thread like that, it will not be named "Timer-x". Therefore, this was probably a thread started elsewhere.
The message tomcat is giving you indicates that the webapp is somehow being undeployed (and then it checks for threads which are still there, and complains if there is). I'm not sure why the undeploy is happening, but if it's because you are stopping the webapp., you may not need to fix this unless you do (lots of) hot-deploys (deploying and undeploying while keeping the tomcat running). This is because, if it's leaking memory right before you are going to kill the process anyways, the memory leak won't have any harm and it would be waste of time to fix it.
If you want to fix it, one easy way is to hook a profiler and see who started this "Timer" thread.
I'm not quite sure whether this is more of an Openbravo issue or more of a Quartz issue, but we have some manual processes that run on schedules via Openbravo ProcessRequest objects (OB v2.50MP24), but it seems that the processes are running twice, at the exact same time. Openbravo extends the Quartz platform for their scheduling. I've tried to resolve this issue on my own by ensuring that my process classes extend this class:
import java.util.List;
import org.openbravo.dal.service.OBDal;
import org.openbravo.model.ad.ui.ProcessRequest;
import org.openbravo.scheduling.ProcessBundle;
import org.openbravo.service.db.DalBaseProcess;
public abstract class RBDDalProcess extends DalBaseProcess {
#Override
protected void doExecute(ProcessBundle bundle) throws Exception {
org.quartz.Scheduler sched = org.openbravo.scheduling.OBScheduler
.getInstance().getScheduler();
int runCount = 0;
synchronized (sched) {
List<org.quartz.JobExecutionContext> currentlyExecutingJobs = (List<org.quartz.JobExecutionContext>) sched
.getCurrentlyExecutingJobs();
for (org.quartz.JobExecutionContext jec : currentlyExecutingJobs) {
ProcessRequest processRequest = OBDal.getInstance().get(
ProcessRequest.class, jec.getJobDetail().getName());
if (processRequest == null)
continue;
String processClass = processRequest.getProcess()
.getJavaClassName();
if (bundle.getProcessClass().getCanonicalName()
.equals(processClass)) {
runCount++;
}
}
}
if (runCount > 1) {
System.out.println("Process "
+ bundle.getProcessClass().getSimpleName()
+ " is already running. Cancelling.");
return;
}
doRun(bundle);
}
protected abstract void doRun(ProcessBundle bundle);
}
This worked fine when I tested by requesting the process to run immediately twice at the same time. One of them cancelled. However, it's not working on the scheduled processes. I have S.o.p's set up to log when the processes start, and looking at the logs shows each line of the output twice, each line one right after the other.
I have a sneaking suspicion that it's because the processes are either running in two completely different threads that don't know about each others' processes, however, I'm not sure how to verify my suspicions or, if I am correct, what to do about it. I've already verified that there is only one instance of each of the ProcessRequest objects stored in the database.
Has anyone else experienced this, know why they might be running twice, or know what I can do to prevent them from simultaneously running?
The most common reasons for a double Job execution are the following:
EDITED:
Your application is deployed in a clustered environment and you have not configured Quartz to run in a cluster environment.
Your application is deployed more than once. There are many cases where the application is deployed twice especially in Tomcat server. As a consequence the QuartzInitializerListener is invoked twice and the Jobs are executed twice. In case you use Tomcat server and you are defining contexts explicitly in server.xml, you should turn off automatic application deployment or specify deployIgnore. Both the autoDeploy set to true and the context element existence in server.xml, have as a consequence the twice deployment of the application. Set autoDeploy to false or remove the context element from the server.xml.
Your application has been redeployed without unscheduling the current processes.
I hope this helps you.
Quartz uses a thread pool for the jobs execution. So as you suspect, the RBDDalProcess will probably have separate instances a in separate thread and the counter check will fail.
One thing you can do is list the jobs registered in the Scheduler (you can get the Scheduler using the OB API as: OBScheduler.getScheduler()):
// enumerate each job group
for(String group: sched.getJobGroupNames()) {
// enumerate each job in group
for(JobKey jobKey : sched.getJobKeys(groupEquals(group))) {
System.out.println("Found job identified by: " + jobKey);
}
}
If you see the same job added twice, check out org.quartz.spi.JobFactory and the org.quartz.Scheduler.setJobFactory method for controlling jobs instantiations.
Also make sure you have only one entry for this process in the 'Report and Process' table in Openbravo.
I have used DalBaseProcess in Openbravo 3.0 and I cannot confirm this behavior you're describing. Having this in mind it would be probably a good idea to checkout the reported bugs for Openbravov2.50MP24 and Quartz or post a thread in Openbravo Forge forums with your problem.
This question already has an answer here:
Spawning threads in a JSF managed bean for scheduled tasks using a timer
(1 answer)
Closed 7 years ago.
I am developing a web application where I need to run a thread for 60 seconds which needs to check for response coming from a webservice. If the response arrives within 60 seconds I will forward to success othewise I will forward to a time out page after 60 seconds. I am using JSF 2.0?
I have thought of using the Timer but not sure whenther I can run the timer for sprcefic amount of time only.
Is there any smart solution for this ??
Yes, youre able to create a timer which expires after a certain amount of time. See this link http://docs.oracle.com/javaee/1.4/api/javax/ejb/TimerService.html.
Java < vers. 6
Create Session- or MessageDriven-Bean
Inject TimerService
#Ressource
TimerService ts;
Create Timer
...
// create Timer which starts after 10s every 10s
Timer timer = ts.createTimer(10000, 10000, "Test-Timer");
...
Important: Timer Interval has to be >7sec, see Java Specs
Create Method to be executed when timer fires
#Timeout //marks Method to be executed by Timer
public void timerFired(Timer timer) {
// your code here
}
Java > vers. 6
Much comfortable with the #Schedule-Annotation
#Schedule(second="*/45", minute="*", hour="*", persistent="false")
public void scheduler() {
// your code here
}
The above code implements a timer which gets fired every 45s of every minute of every hour.
Have a look at wikipedia for more information about cron syntax.
Both methods implement the Serializable-Interface, so they are both thread-safe.
if you would like to extend this rudimental functionality you should take a look at Quartz.
Hope this helped! Have Fun!
Do absolutely not use Timer for this! It's funny for one-time-run desktop applications, but it has severe potential problems when used in a lifetime long running Java EE web application.
Rather use the executors from the java.util.concurrent package. Here's a kickoff example:
ExecutorService executor = Executors.newSingleThreadExecutor(); // An application wide thread pool executor is better.
Callable<InputStream> task = new Callable<InputStream>() {
#Override
public InputStream call() throws Exception {
// Do here your webservice call job.
return new URL("http://stackoverflow.com").openStream();
}
};
try {
InputStream input = executor.invokeAny(Arrays.asList(task), 60, TimeUnit.SECONDS);
// Successful! Forward to success page here.
} catch (TimeoutException e) {
// Timeout occurred. Forward to timeout page here.
}
It sounds like you should just sit in a loop for 60 seconds and sleep for a second between checks. Once 60 seconds has passed or the request came in let the code continue and forward the user to the appropriate page.
This is the simplest way. You could also use an ajax polling system which would be more user friendly because you can update the user interface with a countdown.
long startTime = System.currentTimeMillis();
boolean success = false;
while (System.currentTimeMillis() < startTime + 60000) {
// do check
success = checkSucceeds();
if (success) break;
try {
Thread.sleep(1000);
} catch (InterruptedException interruptedException) {
// ignore
}
}
if (success)
// forward to success page
;
else
// forward to error page
;
I'm developing an application that should execute some task periodically (10 seconds) in the background. For this I use Service and Timer. Actual jobs to be done in timer are:
1) collecting data from the phone (using ContentResolver) into the SQLite database,
2) sending this data to remote server synchronously using HttpPost method.
The problem is next: after some iterations (ammount of these iterations changes every execution of the app) timer changes its period and start to perform all the tasks with 1-3 seconds (sometimes up to 9, but it always lower than 10 secs) delay, which is way too fast in my case and I can't find the reason.
Has anyone faced similar behavior before?
I've tried to use different threads for uploading and collecting inside the timer task, but it didn't solve the problem.
Here's my code snippets:
public class DataForward extends Service{
private Context con = getBaseContext();
private Timer timer = new Timer();
<...>
#Override
public void onStart(Intent intent, int startId) {
timer.schedule(new TimerTask(){
#Override
public void run() {
try {
updateData();
NetworkManager network = new NetworkManager(con);
if(network.isConnectedToTheInternet())
uploadData();
} catch (Exception e) {
e.printStackTrace();
}
}}, 0, 10000);
}
}
<...>
}
Or maybe there's another way to do this without actual Timer?
Any Ideas?
The reason could be, since you told its running on a service, its so possible that your
backgroundTask(Service) may get killed when android OS finds its going low on RAM inorder to keep its
foreGround Applications running.. And again when it gets Free Ram it Restarts the Service Again, so
it may be restarting timer again and again.
for more Read THis ..SERVICE
First execution of your time is 0 millis and subsequent execution is after 10 millis.But android os may stop your service for internal task management.So,again when your service start s after some time then it reset timer again.So,it will execute your task immediately.thats the reason of your problem.
So you can set a time minimum time for your first execution or can use repeating Alarm.