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();
}
}
}