ClassCastException with Quartz Servlet and EJBInvokerJob in Jboss 6
julieh Jan 30, 2012 1:51 AMHi All.
I am currently trying to get a Scheduled Quartz Job to run within JBoss 6.1.0.Final.
I initially had Quartz running as a service in JBoss, however after many days of trying to get it running correctly(class loading issues), I decided to try removing the Quartz service and distribute Quartz within my application ear.
I am initiating the Scheduler via a servlet, which seems to be working ok.
My problem arises when the Job I try to schedule is in an EJB.
I can successfully schedule a job which is NOT in an EJB. (I just have a simple class which implements the Job class), but when attempting to schedule a job which is in an EJB, then I get the following ClassCastException :
2012-01-30 15:46:00,055 ERROR [org.quartz.core.ErrorLogger] (DefaultQuartzScheduler_Worker-3) Job (My Test Job.Test Quartz Job threw an exception.: org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.ClassCastException] at org.quartz.core.JobRunShell.run(JobRunShell.java:234) [:] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549) [:] Caused by: java.lang.ClassCastException at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:229) [:1.6.0_16] at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:137) [:1.6.0_16] at org.quartz.jobs.ee.ejb.EJBInvokerJob.execute(EJBInvokerJob.java:163) [:] at org.quartz.core.JobRunShell.run(JobRunShell.java:223) [:] ... 1 more Caused by: java.lang.ClassCastException: $Proxy149 cannot be cast to org.omg.CORBA.Object at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:212) [:1.6.0_16] ... 4 more
Here is the init method of the servlet :
public void init(ServletConfig config) throws ServletException { System.out.println("ChannelToolsSchedulingServlet - Scheduling Job .."); try { String ejbJNDI = config.getInitParameter("EJBJNDI"); System.out.println("ChannelToolsSchedulingServlet - EJBJNDI = " + ejbJNDI); String ejbMethod = config.getInitParameter("EJBMethod"); System.out.println("ChannelToolsSchedulingServlet - EJBMethod = " + ejbMethod); JobDetail jd = new JobDetail("Test Quartz Job","My Test Job",EJBInvokerJob.class); jd.getJobDataMap().put("ejb", ejbJNDI); jd.getJobDataMap().put("method", ejbMethod); Object[] jdArgs = new Object[0]; jd.getJobDataMap().put("args", jdArgs); CronTrigger cronTrigger = new CronTrigger("CronTrigger1", "CronTrigger1"); String cronExpr = null; // Get the cron Expression as an Init parameter cronExpr = config.getInitParameter("CronExpression"); System.out.println("ChannelToolsSchedulingServlet - CronExpression = " + cronExpr); cronTrigger.setCronExpression(cronExpr); Scheduler sched = StdSchedulerFactory.getDefaultScheduler(); sched.scheduleJob(jd, cronTrigger); System.out.println("ChannelToolsSchedulingServlet - Job scheduled now .."); } catch (Exception e) { e.printStackTrace(); } }
Here is the relevant bits from my web.xml
<servlet> <servlet-name>QuartzInitializer</servlet-name> <display-name>Quartz Initializer Servlet</display-name> <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class> <init-param> <param-name>shutdown-on-unload</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>start-scheduler-on-load</param-name> <param-value>true</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- schedule the EJB job --> <servlet> <servlet-name>ResendSchedulingServlet</servlet-name> <display-name>ResendSchedulingServlet</display-name> <servlet-class>com.company.channels.tools.ChannelToolsSchedulingServlet</servlet-class> <init-param> <param-name>CronExpression</param-name> <param-value>0 0/1 * * * ?</param-value> </init-param> <init-param> <param-name>EJBMethod</param-name> <param-value>processRetryDirectory</param-value> </init-param> <init-param> <param-name>EJBJNDI</param-name> <param-value>AMIResend/remote</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <!-- schedule the NON-EJB job --> <servlet> <servlet-name>TestSchedulingServlet</servlet-name> <display-name>TestSchedulingServlet</display-name> <servlet-class>com.company.channels.tools.TestSchedulingServlet</servlet-class> <init-param> <param-name>CronExpression</param-name> <param-value>0 0/1 * * * ?</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet>
I have tried using both the remote and local interface of my EJB, both are installed as per following Jboss logging :
2012-01-30 15:44:49,224 INFO [org.jboss.ejb3.session.SessionSpecContainer] (Thread-2) Starting jboss.j2ee:ear=Channels.ear,jar=Channels-Ejb.jar,name=AMIResend,service=EJB3 2012-01-30 15:44:49,240 INFO [org.jboss.ejb3.EJBContainer] (Thread-2) STARTED EJB: com.company.channel.ejb.process.AMIResendEJB ejbName: AMIResend 2012-01-30 15:44:49,506 INFO [org.jboss.ejb3.proxy.impl.jndiregistrar.JndiSessionRegistrarBase] (Thread-2) Binding the following Entries in Global JNDI: AMIResend/remote - EJB3.x Default Remote Business Interface Channels/AMIResend/remote-com.company.channel.ejb.process.interfaces.AMIResendRemote - EJB3.x Remote Business Interface AMIResend/local - EJB3.x Default Local Business Interface Channels/AMIResend/local-com.company.channel.ejb.process.interfaces.AMIResendLocal - EJB3.x Local Business Interface
Here is the EJB class and relevant interfaces
package com.company.channel.ejb.process; import javax.ejb.Stateless; import javax.ejb.TransactionManagement; import javax.ejb.TransactionManagementType; import org.jboss.ejb3.annotation.LocalBinding; import org.jboss.ejb3.annotation.RemoteBinding; import com.company.channel.ejb.process.interfaces.AMIResendRemote; import com.company.channel.ejb.process.interfaces.AMIResendLocal; import javax.ejb.EJBException; @LocalBinding(jndiBinding="AMIResend/local") @RemoteBinding(jndiBinding="AMIResend/remote") @Stateless (name="AMIResend" ,mappedName="ejb/company/axis/AMIResend") @TransactionManagement(TransactionManagementType.BEAN) public class AMIResendEJB implements AMIResendRemote,AMIResendLocal { private javax.ejb.SessionContext mySessionCtx; public AMIResendEJB() { System.out.println("Calling AMIResendEJB constructor"); } public javax.ejb.SessionContext getSessionContext() { return mySessionCtx; } public void setSessionContext(javax.ejb.SessionContext ctx) { mySessionCtx = ctx; } public void processRetryDirectory() throws EJBException { System.out.println("running the processRetryDirectory method of AMIResendEJB"); } }
package com.company.channel.ejb.process.interfaces; import javax.ejb.Local; @Local public interface AMIResendLocal extends AMIResend { }
package com.company.channel.ejb.process.interfaces; import javax.ejb.Remote; @Remote public interface AMIResendRemote extends AMIResend { }
package com.company.channel.ejb.process.interfaces; import javax.ejb.EJBException; public interface AMIResend { public void processRetryDirectory() throws EJBException; }
The non-ejb job which works is just a simple 'Hello World' class, so I didn't include the code.
The output from my logging is as follows :
2012-01-30 15:44:52,474 INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/channel]] (Thread-2) QuartzInitializer: Quartz Initializer Servlet loaded, initializing Scheduler... 2012-01-30 15:44:52,490 INFO [org.quartz.impl.StdSchedulerFactory] (Thread-2) Using default implementation for ThreadExecutor 2012-01-30 15:44:52,490 INFO [org.quartz.simpl.SimpleThreadPool] (Thread-2) Job execution threads will use class loader of thread: Thread-2 2012-01-30 15:44:52,521 INFO [org.quartz.core.SchedulerSignalerImpl] (Thread-2) Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl 2012-01-30 15:44:52,521 INFO [org.quartz.core.QuartzScheduler] (Thread-2) Quartz Scheduler v.1.8.6 created. 2012-01-30 15:44:52,521 INFO [org.quartz.simpl.RAMJobStore] (Thread-2) RAMJobStore initialized. 2012-01-30 15:44:52,521 INFO [org.quartz.core.QuartzScheduler] (Thread-2) Scheduler meta-data: Quartz Scheduler (v1.8.6) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED' Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads. Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered. 2012-01-30 15:44:52,521 INFO [org.quartz.impl.StdSchedulerFactory] (Thread-2) Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties' 2012-01-30 15:44:52,521 INFO [org.quartz.impl.StdSchedulerFactory] (Thread-2) Quartz scheduler version: 1.8.6 2012-01-30 15:44:52,521 INFO [org.quartz.core.QuartzScheduler] (Thread-2) Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started. 2012-01-30 15:44:52,521 INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/channel]] (Thread-2) QuartzInitializer: Scheduler has been started... 2012-01-30 15:44:52,521 INFO [org.apache.catalina.core.ContainerBase.[jboss.web].[localhost].[/channel]] (Thread-2) QuartzInitializer: Storing the Quartz Scheduler Factory in the servlet context at key: org.quartz.impl.StdSchedulerFactory.KEY 2012-01-30 15:44:52,552 INFO [STDOUT] (Thread-2) TestSchedulingServlet - Scheduling Job .. 2012-01-30 15:44:52,552 INFO [STDOUT] (Thread-2) TestSchedulingServlet - CronExpression = 0 0/1 * * * ? 2012-01-30 15:44:52,677 INFO [STDOUT] (Thread-2) TestSchedulingServlet - Job scheduled now .. 2012-01-30 15:44:52,693 INFO [STDOUT] (Thread-2) ChannelToolsSchedulingServlet - Scheduling Job .. 2012-01-30 15:44:52,693 INFO [STDOUT] (Thread-2) ChannelToolsSchedulingServlet - EJBJNDI = AMIResend/remote 2012-01-30 15:44:52,709 INFO [STDOUT] (Thread-2) ChannelToolsSchedulingServlet - EJBMethod = processRetryDirectory 2012-01-30 15:44:52,709 INFO [STDOUT] (Thread-2) ChannelToolsSchedulingServlet - CronExpression = 0 0/1 * * * ? 2012-01-30 15:44:52,709 INFO [STDOUT] (Thread-2) ChannelToolsSchedulingServlet - Job scheduled now .. 2012-01-30 15:44:52,803 INFO [org.apache.coyote.http11.Http11Protocol] (Thread-2) Starting Coyote HTTP/1.1 on http-127.0.0.1-8080 2012-01-30 15:44:52,818 INFO [org.apache.coyote.ajp.AjpProtocol] (Thread-2) Starting Coyote AJP/1.3 on ajp-127.0.0.1-8009 2012-01-30 15:44:52,818 INFO [org.jboss.bootstrap.impl.base.server.AbstractServer] (Thread-2) JBossAS [6.1.0.Final "Neo"] Started in 2m:769ms 2012-01-30 15:44:53,521 DEBUG [org.quartz.utils.UpdateChecker] (Timer-1) Checking for available updated version of Quartz... 2012-01-30 15:45:00,021 DEBUG [org.quartz.simpl.SimpleJobFactory] (DefaultQuartzScheduler_QuartzSchedulerThread) Producing instance of Job 'SampleJob.SampleJob', class=com.company.channels.tools.SampleJob 2012-01-30 15:45:00,037 DEBUG [org.quartz.core.JobRunShell] (DefaultQuartzScheduler_Worker-1) Calling execute on job SampleJob.SampleJob 2012-01-30 15:45:00,068 DEBUG [org.quartz.simpl.SimpleJobFactory] (DefaultQuartzScheduler_QuartzSchedulerThread) Producing instance of Job 'My Test Job.Test Quartz Job', class=org.quartz.jobs.ee.ejb.EJBInvokerJob 2012-01-30 15:45:00,053 INFO [STDOUT] (DefaultQuartzScheduler_Worker-1) Hello World! - Mon Jan 30 15:45:00 EST 2012 2012-01-30 15:45:00,100 DEBUG [org.quartz.core.JobRunShell] (DefaultQuartzScheduler_Worker-2) Calling execute on job My Test Job.Test Quartz Job 2012-01-30 15:45:00,459 ERROR [org.quartz.core.JobRunShell] (DefaultQuartzScheduler_Worker-2) Job My Test Job.Test Quartz Job threw an unhandled Exception: : java.lang.ClassCastException at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:229) [:1.6.0_16] at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:137) [:1.6.0_16] at org.quartz.jobs.ee.ejb.EJBInvokerJob.execute(EJBInvokerJob.java:163) [:] at org.quartz.core.JobRunShell.run(JobRunShell.java:223) [:] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549) [:] Caused by: java.lang.ClassCastException: $Proxy149 cannot be cast to org.omg.CORBA.Object at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:212) [:1.6.0_16] ... 4 more 2012-01-30 15:45:00,459 ERROR [org.quartz.core.ErrorLogger] (DefaultQuartzScheduler_Worker-2) Job (My Test Job.Test Quartz Job threw an exception.: org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.ClassCastException] at org.quartz.core.JobRunShell.run(JobRunShell.java:234) [:] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549) [:] Caused by: java.lang.ClassCastException at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:229) [:1.6.0_16] at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:137) [:1.6.0_16] at org.quartz.jobs.ee.ejb.EJBInvokerJob.execute(EJBInvokerJob.java:163) [:] at org.quartz.core.JobRunShell.run(JobRunShell.java:223) [:] ... 1 more Caused by: java.lang.ClassCastException: $Proxy149 cannot be cast to org.omg.CORBA.Object at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:212) [:1.6.0_16] ... 4 more 2012-01-30 15:46:00,008 DEBUG [org.quartz.simpl.SimpleJobFactory] (DefaultQuartzScheduler_QuartzSchedulerThread) Producing instance of Job 'My Test Job.Test Quartz Job', class=org.quartz.jobs.ee.ejb.EJBInvokerJob 2012-01-30 15:46:00,039 DEBUG [org.quartz.core.JobRunShell] (DefaultQuartzScheduler_Worker-3) Calling execute on job My Test Job.Test Quartz Job 2012-01-30 15:46:00,039 DEBUG [org.quartz.simpl.SimpleJobFactory] (DefaultQuartzScheduler_QuartzSchedulerThread) Producing instance of Job 'SampleJob.SampleJob', class=com.company.channels.tools.SampleJob 2012-01-30 15:46:00,039 DEBUG [org.quartz.core.JobRunShell] (DefaultQuartzScheduler_Worker-4) Calling execute on job SampleJob.SampleJob 2012-01-30 15:46:00,039 INFO [STDOUT] (DefaultQuartzScheduler_Worker-4) Hello World! - Mon Jan 30 15:46:00 EST 2012 2012-01-30 15:46:00,055 ERROR [org.quartz.core.JobRunShell] (DefaultQuartzScheduler_Worker-3) Job My Test Job.Test Quartz Job threw an unhandled Exception: : java.lang.ClassCastException at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:229) [:1.6.0_16] at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:137) [:1.6.0_16] at org.quartz.jobs.ee.ejb.EJBInvokerJob.execute(EJBInvokerJob.java:163) [:] at org.quartz.core.JobRunShell.run(JobRunShell.java:223) [:] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549) [:] Caused by: java.lang.ClassCastException: $Proxy149 cannot be cast to org.omg.CORBA.Object at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:212) [:1.6.0_16] ... 4 more 2012-01-30 15:46:00,055 ERROR [org.quartz.core.ErrorLogger] (DefaultQuartzScheduler_Worker-3) Job (My Test Job.Test Quartz Job threw an exception.: org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.ClassCastException] at org.quartz.core.JobRunShell.run(JobRunShell.java:234) [:] at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549) [:] Caused by: java.lang.ClassCastException at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:229) [:1.6.0_16] at javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:137) [:1.6.0_16] at org.quartz.jobs.ee.ejb.EJBInvokerJob.execute(EJBInvokerJob.java:163) [:] at org.quartz.core.JobRunShell.run(JobRunShell.java:223) [:] ... 1 more Caused by: java.lang.ClassCastException: $Proxy149 cannot be cast to org.omg.CORBA.Object at com.sun.corba.se.impl.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:212) [:1.6.0_16] ... 4 more
So as can be seen, the scheduler seems to be running.
It says that it has scheduled the jobs, and does attempt to run them both every minute.
The non-EJB job runs successfully, yet the EJB job gets the class cast exception.
Any pointers on how to solve this issue, or things to try would be greatly appreciated.
Thanks.
Julie