I think, I have a solution for that problem. My problem was also, that the timer was deleted, if EJB/JPA errors occurred.
I've just tried to solve this problem with CDI Events, because I wanted the Exception, that could be thrown to be at another place, so the @Schedule
doesn't get touched. I thought using cdi events will decouple the @Schedule
from the startSomeEvent
-Method. It does not. (I don't know, why programming is such a stone age science sometimes) But the trick does the @Asynchronous
-Annotation on the startSomeEvent
-Method.
So, I've implemented a @Singleton
TimerService
, which is used for all the timers I have in my application:
@Singleton
public class TimerService implements Serializable {
@Inject
private Event<SomeEvent> someEvent;
@Schedule(hour = "*", second = "0", minute = "*", persistent = false)
public void fireSomeEvent() {
someEvent.fire(new SomeEvent());
}
}
The SomeEvent
-Event is observed by the method, which actually is doing the stuff you want. Here in example it is creating a Person
with a username
. The username
is UNIQUE
, so the second time the event fires it will throw a MySQLIntegrityConstraintViolationException: Duplicate entry 'uniqueUsername' for key 'USERNAME'
. This would kill our @Schedule
, but it does not, because we have the @Asynchronous
-Annotation.
@Singleton
public class TimerTestService {
@PersistenceContext(unitName = "VWMam3PU")
private EntityManager entityManager;
@Asynchronous
public void startSomeEvent(@Observes SomeEvent event) {
Person p = new Person();
p.setUsername("uniqueUsername");
entityManager.persist(p);
}
}
The SomeEvent
-Class is a simple POJO:
public class SomeEvent {
}
So, I was looking for a solution to that for long time. Now it is working for me. It fires exception and is trying that again and again and again.