1

My Java EE app should have a background thread, which updates DB state. I'd like to use JPA for this purpose. What are the best practices to do it? (Our EE container is prior JSR-236, so ManagedExecutorService is not our choice)


By the way I tried the code bellow, but it didnt work - no exception was thrown, but nothing was saved into DB. Without background thread and using injected EntityManager everything saved:

@Singleton
public class IdentityDao{

    @PersistenceUnit(unitName = "routing")
    private EntityManagerFactory emf;
    @Resource
    private UserTransaction utx;

    @PostConstruct
    protected void startConverter() {
        new Converter();
    }

    private class Converter implements Runnable {
        private Converter() {
            ScheduledExecutorService scheduler = ThreadUtils.newSingleThreadScheduledExecutor("test", true);
            scheduler.scheduleAtFixedRate(this, 5, 5, TimeUnit.SECONDS);
        }

        @Override
        public void run() {
            EntityManager em = emf.createEntityManager();
            try {
                utx.begin();                    
                em.persist(new PersonEntity("123"));
                utx.commit();
            } catch (Exception e) {
                try {
                    e.printStackTrace();
                    utx.rollback();
                } catch (Exception exc) {
                }
            } finally {
                em.close();
            }
        }
    }
}
Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Kivan
  • 1,712
  • 1
  • 14
  • 30
  • 1
    If you have an EntityManager, then why are you using UserTransaction? Use the EntityManager! – Gimby Aug 28 '14 at 13:34
  • The problem with entity manager is that it needs transaction. And when you write "em.getTransaction().begin()", it throws exception like "sorry, but in JTA mode only JTA transactions are possible". And UserTransaction is a JTA transaction, so no exception is thrown in the above code, but DB state does not change anyway. – Kivan Aug 29 '14 at 07:12
  • I don't know what that ThreadUtils does. Is it using a JEE ManagedScheduledExecutorService or is it a standard JSE ScheduledExecutorService? You should use the former in a JEE environment so it is actually container managed. http://stackoverflow.com/questions/25237111/start-stop-a-scheduledexecutorservice-in-jee-environment-using-servlet – Gimby Aug 29 '14 at 07:25
  • It seems our web container is too old to provide JSR-236 functionalities, so we need some older solution. – Kivan Aug 29 '14 at 08:12
  • I agree, you should research that. Possibly the classic EJB timer services http://docs.oracle.com/javaee/6/tutorial/doc/bnboy.html . PS: you should add such important details as running on legacy technology to your actual question. – Gimby Aug 29 '14 at 08:22

1 Answers1

0

Finally I found the simple solution. It is based on usage of ejb timers, as Gimby suggested.

@Singleton
public class IdentityDao{    
    @PersistenceContext
    EntityManager em;

    @Schedule(hour = "*", minute = "*", second = "*/10")
    public void every10Sec() {
         em.persist(new PersonEntity("123"));
    }
}
Kivan
  • 1,712
  • 1
  • 14
  • 30