I am playing around with EJB timers but I've run into trouble when trying to run both timers and persistent entities in the same project. In my initial setup I only had timers and these fired as expected:
@Stateless
public class TimerHandler {
@Resource
protected TimerService mTimerService;
@PostConstruct
public void init() {
// could do cool stuff but choose not to
}
public Timer start(long aDuration) {
TimerConfig conf = new TimerConfig();
conf.setPersistent(false); // don't want the timer to be saved
return mTimerService.createSingleActionTimer(aDuration, conf);
}
@Timeout
public void timeOutAction(Timer aTimer) {
// does fancy stuff
System.out.println("So fancy :)");
}
}
I had a bit of trouble getting the timers to run but I went the bruteforce way and reinstalled Payara (Glassfish). After this using the Timer was fine. I could start and cancel it as so:
@Stateful
public class MyClass {
@EJB
private TimerHandler mTimerHandler;
private Timer mTimer;
public void startTimer(int aDuration) {
mTimer = mTimerHandler.start(aDuration);
}
public void stopTimer() {
try {
mTimer.cancel();
} catch (NoSuchObjectLocalException | NullPointerException ex) {
System.out.println("There is no timer running.");
}
}
}
However, the problem arose after I tried to add Entities to my project. My entity looks like this:
@Entity
public class TestEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String testValue;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTestValue() {
return testValue;
}
public void setTestValue(String value) {
testValue = value;
}
// removed standard code for @Override of equals(),
// hashCode() & toString()
}
Which I manipulate through my controller bean:
@Stateless
public class TestDBController {
@PersistenceContext(unitName = "TimerTestWithDBPU")
private EntityManager em;
public long saveValue(String value) {
TestEntity entity = new TestEntity();
entity.setTestValue(value);
em.persist(entity);
em.flush();
return entity.getId();
}
public String getValue(long aId) {
TestEntity entity = em.find(TestEntity.class, aId);
return entity.getTestValue();
}
}
and I have my Persistence Unit (persistence.xml) set up in the following way:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="TimerTestWithDBPU" transaction-type="JTA">
<jta-data-source>jdbc/timer_test_pool</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action"
value="create"/>
</properties>
</persistence-unit>
</persistence>
After adding this Entity and Persistence Unit I get the following error:
EJB Timer Service is not available.
Timers for application with id [XYZ] will not be deleted
Why is this? Can't you run an application with both ejb timers and persistent entities?