EntityManagerFactory not found in JNDI when injected in Quartz JobListener
ssarver Apr 1, 2010 8:08 PMDescription:
When Quartz tries to lookup the entityManager in the job listener, the following exception occurs:
java.lang.IllegalArgumentException: EntityManagerFactory not found in JNDI : java:comp/env/test/pu
Also, the modification to the remoteJob entity next date is not being persisted in the database, despite calling merge:
9:23:07,113 INFO [RemoteJobHome] ***BEFORE: remoteJobManager.scheduleJob(remoteJob): remoteJob: com.test.model.RemoteJob[id=31, host=com.test.model.Host@1830e49, enabled=true, active=false, failed=false, min=0, max=0, next=Mon Feb 09 12:00:00 PST 2009, start=Thu Apr 01 02:00:00 PST 2010, stop=Fri Apr 30 12:00:00 PDT 2010] 09:23:07,204 INFO [RemoteJobHome] *** AFTER: remoteJobManager.scheduleJob(remoteJob): remoteJob: com.test.model.RemoteJob[id=31, host=com.test.model.Host@1830e49, enabled=true, active=false, failed=false, min=0, max=0, next=Thu Apr 01 02:00:00 PST 2010, start=Thu Apr 01 02:00:00 PST 2010, stop=Fri Apr 30 12:00:00 PDT 2010]
Is there a better place to call merge than in the manager?
Flow:
RemoteJobHome.scheduleJob --> RemoteJobManager.scheduleJob(remoteJob) --> RemoteJobListener.jobWasExecuted(...)
Log:
09:23:07,108 INFO [STDOUT] Hibernate: insert into RemoteJob (active, enabled, failed, host_id, max, min, next, start, stop) values (?, ?, ?, ?, ?, ?, ?, ?, ?) 09:23:07,110 INFO [STDOUT] ***PASSWORD HASH: Ss/jICpf9c9GeJj8WKqx1hUClEE= 09:23:07,110 INFO [STDOUT] ***PASSWORD HASH: Ss/jICpf9c9GeJj8WKqx1hUClEE= 09:23:07,113 INFO [RemoteJobHome] ***BEFORE: remoteJobManager.scheduleJob(remoteJob): remoteJob: com.test.model.RemoteJob[id=31, host=com.test.model.Host@1830e49, enabled=true, active=false, failed=false, min=0, max=0, next=Mon Feb 09 12:00:00 PST 2009, start=Thu Apr 01 02:00:00 PST 2010, stop=Fri Apr 30 12:00:00 PDT 2010] 09:23:07,204 INFO [RemoteJobHome] *** AFTER: remoteJobManager.scheduleJob(remoteJob): remoteJob: com.test.model.RemoteJob[id=31, host=com.test.model.Host@1830e49, enabled=true, active=false, failed=false, min=0, max=0, next=Thu Apr 01 02:00:00 PST 2010, start=Thu Apr 01 02:00:00 PST 2010, stop=Fri Apr 30 12:00:00 PDT 2010] 09:23:17,028 INFO [JobStoreCMT] Handling 1 trigger(s) that missed their scheduled fire-time. 09:23:17,246 ERROR [SimpleThreadPool] Error while executing the Runnable: java.lang.IllegalArgumentException: EntityManagerFactory not found in JNDI : java:comp/env/test/pu at org.jboss.seam.persistence.ManagedPersistenceContext.getEntityManagerFactoryFromJndiOrValueBinding(ManagedPersistenceContext.java:245) at org.jboss.seam.persistence.ManagedPersistenceContext.initEntityManager(ManagedPersistenceContext.java:78) at org.jboss.seam.persistence.ManagedPersistenceContext.getEntityManager(ManagedPersistenceContext.java:107) at sun.reflect.GeneratedMethodAccessor924.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.jboss.seam.util.Reflections.invoke(Reflections.java:22) at org.jboss.seam.util.Reflections.invokeAndWrap(Reflections.java:144) at org.jboss.seam.Component.callComponentMethod(Component.java:2249) at org.jboss.seam.Component.unwrap(Component.java:2275) at org.jboss.seam.Component.getInstance(Component.java:2041) at org.jboss.seam.Component.getInstance(Component.java:1983) at org.jboss.seam.Component.getInstance(Component.java:1977) at org.jboss.seam.Component.getInstanceInAllNamespaces(Component.java:2349) at org.jboss.seam.Component.getValueToInject(Component.java:2301) at org.jboss.seam.Component.injectAttributes(Component.java:1736) at org.jboss.seam.Component.inject(Component.java:1554) at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:61) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:44) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:118) at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:185) at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:103) at com.test.action.RemoteJobListener_$$_javassist_seam_10.getName(RemoteJobListener_$$_javassist_seam_10.java) at org.quartz.core.QuartzScheduler.notifyJobListenersToBeExecuted(QuartzScheduler.java:1849) at org.quartz.core.JobRunShell.notifyListenersBeginning(JobRunShell.java:335) at org.quartz.core.JobRunShell.run(JobRunShell.java:173) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:546) Caused by: javax.naming.NameNotFoundException: env not bound at org.jnp.server.NamingServer.getBinding(NamingServer.java:771) at org.jnp.server.NamingServer.getBinding(NamingServer.java:779) at org.jnp.server.NamingServer.getObject(NamingServer.java:785) at org.jnp.server.NamingServer.lookup(NamingServer.java:396) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:726) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:833) at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:686) at javax.naming.InitialContext.lookup(InitialContext.java:392) at org.jboss.seam.persistence.ManagedPersistenceContext.getEntityManagerFactoryFromJndiOrValueBinding(ManagedPersistenceContext.java:241) ... 28 more
File: RemoteJobHome.java
package com.test.action; import com.test.model.Host; import com.test.model.RemoteJob; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.web.RequestParameter; import org.jboss.seam.faces.FacesMessages; import org.jboss.seam.framework.EntityHome; import org.jboss.seam.log.Log; @Name("remoteJobHome") public class RemoteJobHome extends EntityHome<RemoteJob> { @Logger private Log log; @RequestParameter private Long remoteJobId; @In private RemoteJobManager remoteJobManager; @In(create = true) HostHome hostHome; public void setRemoteJobId(Long id) { setId(id); } public Long getRemoteJobId() { return (Long) getId(); } @Override protected RemoteJob createInstance() { RemoteJob remoteJob = new RemoteJob(); return remoteJob; } public void load() { if (isIdDefined()) { wire(); } } public void wire() { getInstance(); Host host = hostHome.getDefinedInstance(); if (host != null) { getInstance().setHost(host); } } public boolean isWired() { return true; } public RemoteJob getDefinedInstance() { return isIdDefined() ? getInstance() : null; } @Override public Object getId() { return remoteJobId; } @Transactional public String scheduleJob() throws Exception { String result = persist(); RemoteJob remoteJob = getInstance(); log.info("***BEFORE: remoteJobManager.scheduleJob(remoteJob): remoteJob: #0", remoteJob); remoteJobManager.scheduleJob(remoteJob); log.info("*** AFTER: remoteJobManager.scheduleJob(remoteJob): remoteJob: #0", remoteJob); return result; } @Transactional public void cancel() throws Exception { RemoteJob remoteJob = getInstance(); remoteJobManager.cancel(remoteJob); FacesMessages.instance().add("Deleted job: RemoteJob(" + remoteJob.getId() + ")"); } }
File: RemoteJobManager.java
package com.test.action; import com.test.model.RemoteJob; import javax.naming.Context; import javax.naming.InitialContext; import javax.persistence.EntityManager; import org.jboss.seam.annotations.AutoCreate; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.log.Log; import org.quartz.impl.StdScheduler; import org.quartz.JobDetail; import org.quartz.jobs.NoOpJob; import org.quartz.Scheduler; import org.quartz.SimpleTrigger; @Name("remoteJobManager") @AutoCreate public class RemoteJobManager { @Logger private Log log; @In private EntityManager entityManager; @In(create=true) private RemoteJobListener remoteJobListener; public void cancel(RemoteJob remoteJob) throws Exception { remoteJob.setActive(false); // Explicitly remove job InitialContext ctx = new InitialContext(); StdScheduler scheduler = (StdScheduler) ctx.lookup("Quartz"); scheduler.deleteJob(remoteJob.getId().toString(), Scheduler.DEFAULT_GROUP); remoteJob.setActive(false); entityManager.merge(remoteJob); } public void scheduleJob(RemoteJob remoteJob) { try { // Update remote job entity remoteJob.setNext(remoteJob.getStart()); // Lookup quartz scheduler Context ctx = new InitialContext(); StdScheduler scheduler = (StdScheduler) ctx.lookup("Quartz"); // Create quartz job JobDetail jobDetail = new JobDetail( remoteJob.getId().toString(), Scheduler.DEFAULT_GROUP, NoOpJob.class ); SimpleTrigger trigger = new SimpleTrigger( "trigger" + remoteJob.getId().toString(), Scheduler.DEFAULT_GROUP, remoteJob.getStart(), null, 0, 0); // Set up the quartz job listener scheduler.addJobListener(remoteJobListener); // Associate listener with the job jobDetail.addJobListener(remoteJobListener.getName()); // Schedule the job to run scheduler.scheduleJob(jobDetail, trigger); entityManager.merge(remoteJob); } catch (Exception e) { log.error("***e: #0", e); e.printStackTrace(); } } }
File: RemoteJobListener.java
package com.test.action; import com.test.model.RemoteJob; import java.util.Date; import javax.persistence.EntityManager; import org.jboss.seam.annotations.AutoCreate; import org.jboss.seam.annotations.In; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.log.Log; import org.quartz.JobDetail; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.JobListener; import org.quartz.SchedulerException; import org.quartz.Scheduler; import org.quartz.SimpleTrigger; @Name("remoteJobListener") @AutoCreate public class RemoteJobListener implements JobListener { @In(create=true) private EntityManager entityManager; @Logger private Log log; public String getName() { return getClass().getName(); } public void jobToBeExecuted(JobExecutionContext jec) { try { log.info("***jobToBeExecuted"); } catch (Exception e) { e.printStackTrace(); } } public void jobExecutionVetoed(JobExecutionContext jec) { try { log.info("***jobExecutionVetoed"); } catch (Exception e) { e.printStackTrace(); } } public void jobWasExecuted(JobExecutionContext jec, JobExecutionException jee) { log.info("***jobWasExecuted"); try { // Lookup job JobDetail jobDetail = jec.getJobDetail(); log.info("***entityManager: #0", entityManager); RemoteJob remoteJob = entityManager.find(RemoteJob.class, new Long(jobDetail.getName())); log.info("***remoteJob: #0", remoteJob); // Compute random delay RandomIntervalDuration random = new RandomIntervalDuration(remoteJob.getMin(), remoteJob.getMax()); Long delay = random.nextLongMillis(); Date date = new Date(System.currentTimeMillis() + delay); // Only shedule new quartz job if before end date. log.info("***date: " + date + ", stop: " + remoteJob.getStop()); if (date.before(remoteJob.getStop())) { // Update remote job entity remoteJob.setNext(date); entityManager.merge(remoteJob); log.info("***true == date.before(stop): Updating remoteJobote job w/ next start time: #)", remoteJob); // Create trigger SimpleTrigger trigger = new SimpleTrigger( "trigger" + jobDetail.getName().toString(), Scheduler.DEFAULT_GROUP, date, null, 0, 0 ); // schedule the job to run! try { jec.getScheduler().scheduleJob(jobDetail, trigger); } catch (SchedulerException e) { log.warn("***Unable to schedule " + jobDetail.getName()); e.printStackTrace(); } } else { // Deactivate job remoteJob.setActive(false); entityManager.merge(remoteJob); log.info("***Job completed: #0", jobDetail.getName()); } } catch (Exception e) { log.error("***e: #0", e); e.printStackTrace(); } } }