3 Replies Latest reply on Nov 23, 2006 5:57 AM by Ola Hamfors

    EJB 2.1 problems with EJB 3.0

    Jonathan Beer Newbie

      Hi,

      I've been racking my head for days on this, any help would be appreciated.

      I am using quartz for scheduling. I am using the EJBInvoker (if you don't know about this, don't worry it's not that important) to invoke an EJB when a trigger is fired. Quartz's EJBInvoker job requires EJB 2.1 syntax, and requires me to lookup the remoteHome interface: "EarName/TestBean/remoteHome"

      I have the following EJB & interfaces:

      @Local
      public interface Test {
      public void doThisWhenFired();
      }


      public interface TestRemote extends EJBObject, Test {}


      public interface TestRemoteHome extends EJBHome {
      public TestRemote create() throws java.rmi.RemoteException, javax.ejb.CreateException;
      }


      @Stateless(name="TestBean")
      @RemoteHome(TestRemoteHome.class)
      @Remote(TestRemote.class)
      @Local
      public class TestBean implements Test {
      public TestBean() {}

      public void doThisWhenFired() {
      System.out.println("Job executed!");
      }

      public void ejbCreate() throws CreateException {}
      }


      I have tried a number of packaging/deployment approaches, and I get the following error (full stack trace at the bottom of this message):

      Caused by: java.lang.ClassNotFoundException: No ClassLoaders found for: com.blah.TestRemoteHome (no security manager: RMI class loader disabled)

      Currently, I package all of these together into an ejb3 (the interfaces and the Stateless bean), which is inside the .ear (and referenced in the application.xml file ...), without any success.


      If anybody can point me in the right direction, or sees any flaws in what I'm doing (I'm fairly new to all of this), I would really appreciate some direction. I have been working on this for days.

      Thanks,
      Jonathan


      org.quartz.JobExecutionException: javax.naming.CommunicationException [Root exception is java.lang.ClassNotFoundException: No ClassLoaders found for: com.blah.TestRemoteHome (no security manager: RMI class loader disabled)] [See nested exception: javax.naming.CommunicationException [Root exception is java.lang.ClassNotFoundException: No ClassLoaders found for: com.blah.TestRemoteHome (no security manager: RMI class loader disabled)]]
      at org.quartz.jobs.ee.ejb.EJBInvokerJob.execute(EJBInvokerJob.java:156)
      at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
      at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)
      * Nested Exception (Underlying Cause) ---------------
      javax.naming.CommunicationException [Root exception is java.lang.ClassNotFoundException: No ClassLoaders found for: com.blah.TestRemoteHome (no security manager: RMI class loader disabled)]
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:713)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:572)
      at javax.naming.InitialContext.lookup(InitialContext.java:351)
      at org.quartz.jobs.ee.ejb.EJBInvokerJob.execute(EJBInvokerJob.java:154)
      at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
      at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)
      Caused by: java.lang.ClassNotFoundException: No ClassLoaders found for: com.texadasoftware.server.infra.reporting.TestRemoteHome (no security manager: RMI class loader disabled)
      at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:531)
      at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628)
      at org.jboss.system.JBossRMIClassLoader.loadProxyClass(JBossRMIClassLoader.java:70)
      at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
      at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:238)
      at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1494)
      at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1457)
      at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1693)
      at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
      at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339)
      at java.rmi.MarshalledObject.get(MarshalledObject.java:135)
      at org.jnp.interfaces.MarshalledValuePair.get(MarshalledValuePair.java:57)
      at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:637)
      ... 5 more

        • 1. Re: EJB 2.1 problems with EJB 3.0
          Jonathan Beer Newbie

          I'm running JBoss 4.0.3SP1 with EJB3.0 RC5

          Jonathan

          • 2. Re: EJB 2.1 problems with EJB 3.0
            Ola Hamfors Newbie

            I have written a EJB3InvokerJob.

            ----------------- EJB3Invoker.java --------------------------
            import java.lang.reflect.InvocationTargetException;
            import java.lang.reflect.Method;
            import java.util.Hashtable;

            import javax.naming.Context;
            import javax.naming.InitialContext;
            import javax.naming.NamingException;

            import org.apache.log4j.Logger;
            import org.quartz.JobDataMap;
            import org.quartz.JobDetail;
            import org.quartz.JobExecutionContext;
            import org.quartz.JobExecutionException;
            import org.quartz.StatefulJob;
            /**
            *
            * @author ola.hamfors@diabol.se
            *
            */
            public class EJB3InvokerJob implements StatefulJob{
            @SuppressWarnings("unused")
            private final static String RCS_ID = "$Id: EJB3InvokerJob.java,v 1.6 2006/08/18 08:04:37 STNO Exp $";

            public static final String EJB_JNDI_NAME_KEY = "ejb";

            public static final String EJB_METHOD_KEY = "method";

            public static final String EJB_INTERFACE_CLASS = "interfaceClass";

            public static final String EJB_ARG_TYPES_KEY = "argTypes";

            public static final String EJB_ARGS_KEY = "args";

            public static final String INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial";

            public static final String PROVIDER_URL = "java.naming.provider.url";

            Logger logger = Logger.getLogger(getClass().getName());

            public EJB3InvokerJob() {
            super();
            }

            public void execute(JobExecutionContext context)
            throws JobExecutionException {
            JobDetail detail = context.getJobDetail();
            JobDataMap dataMap = detail.getJobDataMap();
            String ejb = dataMap.getString(EJB_JNDI_NAME_KEY);
            String method = dataMap.getString(EJB_METHOD_KEY);
            String interfaceClass = dataMap.getString(EJB_INTERFACE_CLASS);
            logger.debug("Trying to execute {ejb=" + ejb + ",method="
            + method + ",intefaceClass=" + interfaceClass + "}");
            Object[] arguments = (Object[]) dataMap.get(EJB_ARGS_KEY);
            if (arguments == null) {
            arguments = new Object[0];
            }
            if (ejb == null) {
            throw new JobExecutionException();
            }
            InitialContext jndiContext = null;

            try {
            jndiContext = getInitialContext(dataMap);
            } catch (NamingException ne) {
            throw new JobExecutionException(ne);
            }
            Object value = null;
            try {
            value = jndiContext.lookup(ejb);
            } catch (NamingException ne) {
            throw new JobExecutionException(ne);
            }
            Class beanClass;
            try {
            beanClass = Class.forName(interfaceClass);
            } catch (ClassNotFoundException e) {
            throw new JobExecutionException(e);
            }

            Method methodExecute = null;
            Class[] argTypes = (Class[]) dataMap.get(EJB_ARG_TYPES_KEY);
            if (argTypes == null) {
            argTypes = new Class[arguments.length];
            for (int i = 0; i < arguments.length; i++) {
            argTypes = arguments.getClass();
            }
            }
            // get all interfaces
            Class[] interfaces = beanClass.getInterfaces();
            for (int i = 0; i < interfaces.length; i++) {
            try {
            // try to find the method and use the first interface if we do
            methodExecute = interfaces.getDeclaredMethod(method,
            argTypes);
            break;
            } catch (NoSuchMethodException nsme) {
            // do nothing
            }
            throw new JobExecutionException("No interface with method "
            + method + " declaired. Your Bean {" + beanClass.getName()
            + "} has to implement the Local interface");
            }

            try {
            methodExecute.invoke(value, arguments);
            } catch (IllegalAccessException iae) {
            throw new JobExecutionException(iae);
            } catch (InvocationTargetException ite) {
            throw new JobExecutionException(ite);
            }
            }

            @SuppressWarnings("unchecked")
            private InitialContext getInitialContext(JobDataMap jobDataMap)
            throws NamingException {
            Hashtable params = new Hashtable(2);
            String initialContextFactory = jobDataMap
            .getString(INITIAL_CONTEXT_FACTORY);
            if (initialContextFactory != null) {
            params.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory);
            }
            String providerUrl = jobDataMap.getString(PROVIDER_URL);
            if (providerUrl != null) {
            params.put(Context.PROVIDER_URL, providerUrl);
            }
            return new InitialContext(params);
            }

            }
            -----------------------------

            ---------------- CronJobListener ---------------

            import java.util.Date;

            import javax.naming.InitialContext;
            import javax.naming.NamingException;

            import org.apache.log4j.Logger;
            import org.quartz.JobDataMap;
            import org.quartz.JobDetail;
            import org.quartz.JobExecutionContext;
            import org.quartz.JobExecutionException;
            import org.quartz.JobListener;

            import com.omxgroup.cds.entity.batch.CronJob;
            import com.omxgroup.cds.entity.util.JndiNameCreator;
            import com.omxgroup.cds.server.api.CronJobApi;
            import com.omxgroup.cds.server.api.CronJobApiBean;

            /**
            * A CronJobListener that updates the lastexecutiondate of the cronjob
            *
            * @author ola.hamfors@diabol.se
            *
            */
            public class CronJobListener implements JobListener {
            @SuppressWarnings("unused")
            private final static String RCS_ID = "$Id: CronJobListener.java,v 1.6 2006/11/22 18:02:25 JAJH Exp $";

            public static final String CDS_JOB_LISTENER_NAME = "CDS CronJob Listener";

            public static final String CDS_CRON_JOB_ID = "cronjobid";

            public String getName() {
            return CDS_JOB_LISTENER_NAME;
            }

            private Logger logger = Logger.getLogger(getClass().getName());


            public void jobToBeExecuted(JobExecutionContext ctx) {
            // do nothing
            }

            public void jobExecutionVetoed(JobExecutionContext ctx) {
            // do nothing
            }

            public void jobWasExecuted(JobExecutionContext ctx,
            JobExecutionException exception) {
            JobDetail jobDetail = ctx.getJobDetail();
            JobDataMap map = jobDetail.getJobDataMap();
            long cronJobId = map.getLong(CDS_CRON_JOB_ID);
            InitialContext jndiCtx;
            try {
            jndiCtx = new InitialContext();
            CronJobApi cronJobApi = (CronJobApi) jndiCtx
            .lookup(JndiNameCreator.getLocalJndiName(CronJobApiBean.class));
            CronJob job = cronJobApi.getCronJob(cronJobId);
            if (job != null) {
            job.setLastExecution(new Date());
            cronJobApi.update(job);
            }
            } catch (NamingException e) {
            logger.warn("Couldn't lookup CronJobApiBean", e);
            }

            }

            }
            -----------------------------

            And this is how I use it.

            public String startAllCronJobs() throws SchedulerException {

            List list = cronJobApi.getAllCronJobs();
            logger.info("Starting " + list.size() + " "
            + ((list.size() == 1) ? "cronjob" : "cronjobs"));
            Scheduler sched = StdSchedulerFactory.getDefaultScheduler();
            sched.addJobListener(new CronJobListener());
            for (CronJob job : list) {

            logger.info("Starting job " + job);
            CronJobDetail jd = new CronJobDetail(job.toString(), job
            .getDescription(), EJB3InvokerJob.class);
            jd.addJobListener(CronJobListener.CDS_JOB_LISTENER_NAME);
            Class beanClass = null;
            try {
            beanClass = Class.forName(job.getQualifiedBeanClassName());
            } catch (ClassNotFoundException e) {
            logger.error("Cron Job class "
            + job.getQualifiedBeanClassName() + "not found", e);
            continue;
            }
            String jndiName = JndiNameCreator.getLocalJndiName(beanClass);
            jd.getJobDataMap().put(EJB3InvokerJob.EJB_JNDI_NAME_KEY, jndiName);
            jd.getJobDataMap().put(EJB3InvokerJob.EJB_METHOD_KEY,
            job.getMethod());
            jd.getJobDataMap().put(EJB3InvokerJob.EJB_INTERFACE_CLASS,
            job.getQualifiedBeanClassName());
            Object[] jdArgs = new Object[0];
            jd.getJobDataMap().put(EJB3InvokerJob.EJB_ARGS_KEY, jdArgs);
            jd.getJobDataMap()
            .put(CronJobListener.CDS_CRON_JOB_ID, job.getId());

            String jobName = job.toString();
            String group = "CDS Quartz Group";

            CronTrigger cronTrigger = new CronTrigger(jobName, group);
            try {
            cronTrigger.setCronExpression(job.getCronExpression());
            // cronTrigger.addTriggerListener(CronJobTriggerListener.CRON_TIGGER_NAME);
            } catch (ParseException e) {
            logger.warn("Invalid syntax on cron expression", e);
            continue;
            }
            sched.scheduleJob(jd, cronTrigger);
            logger.info("Job " + job + " scheduled");
            }

            sched.start();
            return "Started";
            }


            • 3. Re: EJB 2.1 problems with EJB 3.0
              Ola Hamfors Newbie

              You might need the cronjob entity as well..


              import java.io.Serializable;
              import java.util.Date;

              import javax.persistence.Basic;
              import javax.persistence.Column;
              import javax.persistence.Entity;
              import javax.persistence.Table;

              import org.apache.commons.lang.builder.ToStringBuilder;

              import com.omxgroup.cds.entity.CdsBaseEntity;
              /**
              * Entity representing a CronJob.
              * @author olhm
              *
              */
              @Entity
              @Table(name = "CDS_CRON_JOB")
              public class CronJob extends CdsBaseEntity implements Serializable {
              @SuppressWarnings("unused")
              private final static String RCS_ID = "$Id: CronJob.java,v 1.5 2006/11/22 18:02:50 JAJH Exp $";
              private static final long serialVersionUID = 1L;

              private String description;

              private String qualifiedBeanClassName;

              private String cronExpression;

              private String method;

              private Date lastExecution;

              @Override
              public String toString() {
              return new ToStringBuilder(this).append("id", getId()).append(
              "description", getDescription()).append("qualifiedBeanClassName",
              getQualifiedBeanClassName()).append("method", getMethod()).append(
              "cronExpression", getCronExpression()).toString();
              }

              @Basic
              @Column(name = "CRON_EXPRESSION")
              public String getCronExpression() {
              return cronExpression;
              }

              public void setCronExpression(String cronExpression) {
              this.cronExpression = cronExpression;
              }

              @Basic
              @Column(name = "DESCRIPTION")
              public String getDescription() {
              return description;
              }

              public void setDescription(String description) {
              this.description = description;
              }

              @Basic
              @Column(name = "LAST_EXECUTION")
              public Date getLastExecution() {
              return lastExecution;
              }

              public void setLastExecution(Date lastExecution) {
              this.lastExecution = lastExecution;
              }

              @Basic
              @Column(name = "QUALIFIED_BEAN_CLASSNAME")
              public String getQualifiedBeanClassName() {
              return qualifiedBeanClassName;
              }

              public void setQualifiedBeanClassName(String qualifiedBeanClassName) {
              this.qualifiedBeanClassName = qualifiedBeanClassName;
              }

              @Basic
              @Column(name = "METHOD")
              public String getMethod() {
              return method;
              }

              public void setMethod(String method) {
              this.method = method;
              }

              }