From the documentation of java.util.Timer
class:
Corresponding to each Timer object is a single background thread.
And peeking to the inner code of the java.util.Timer
class, we can see that it basically instantiates the thread by invoking new Thread()
.
Meanwhile, from App Engine's documentation about the use of threads in their Java sandbox:
You must use one of the methods on ThreadManager to create your threads. You cannot invoke new Thread() yourself or use the default thread factory.
So what happened here is the Timer
object instantiated their own thread, which then executes the Objectify queries, but since threads instantiated outside ThreadManager does not have the proper App Engine API environment set up for them, it throws an exception.
You need to refactor your code to avoid using the Timer and TimerTask classes and use basic threads instead. For example, instead of using:
import java.util.Timer;
import java.util.TimerTask;
...
Timer timer = new Timer();
timer.schedule( new TimerTask()
{
@Override
public void run()
{
// Objectify query here.
}
}, 5000 );
You could instead use:
import com.google.appengine.api.ThreadManager;
...
final long tScheduleDelay = 5000;
ThreadManager.createThreadForCurrentRequest( new Runnable()
{
@Override
public void run()
{
try
{
Thread.sleep( tScheduleDelay );
}
catch ( InterruptedException ex )
{
// log possible exception
}
// Objectify query here.
}
} ).start();