Although @Chris' answer@Chris' answer helped me understand a bit more about EntityManager (thus the tick), I worked out the real problem - ManagedScheduledExecutorService does not necessarily auto-kill its threads on application termination - this appears to be true for Glassfish 4.0 also. So, although my underlying application had terminated, the thread still had an EntityManager from the dead app's EntityManagerFactory (I think), so when the timer ticked it spewed out the error I described above.
I fixed the problem by getting the ScheduledFuture and calling future.cancel(false) in my contextDestroyed().
Furthermore, it seems that Timer Tick beans and EntityManager don't mix, so I had to do this:
@Stateless public class TimerTick implements TimerTickAbs, Runnable { @EJB private RealTimerTick realTick; @Override public void run() { realTick.run(); } @Override public Runnable runner() { return this; } } and:
@Stateless public class RealTimerTick implements TimerTickAbs, Runnable { @PersistenceContext private EntityManager entityManager; @Override public void run() { Query q = entityManager.createQuery("SELECT blah..."); } @Override public Runnable runner() { return this; } } This now works perfectly, including automatic persistence of changes made to values returned from the Query, as far as I can tell, but I cannot explain it!