Quartz中定时调度EJB2.0服务
????????? 在Quartz2.0中提供支持EJB2.0的服务,下面实例为Quartz2.0中EJB2.0的支持。
EJBInvokerJob的源代码如下:
public class EJBInvokerJob implements Job { /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constants. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public static final String EJB_JNDI_NAME_KEY = "ejb"; public static final String EJB_METHOD_KEY = "method"; 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"; public static final String PRINCIPAL = "java.naming.security.principal"; public static final String CREDENTIALS = "java.naming.security.credentials"; /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Constructors. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public EJBInvokerJob() { // nothing } /* * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * Interface. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap dataMap = context.getMergedJobDataMap(); String ejb = dataMap.getString(EJB_JNDI_NAME_KEY); String method = dataMap.getString(EJB_METHOD_KEY); Object[] arguments = (Object[]) dataMap.get(EJB_ARGS_KEY); if (arguments == null) { arguments = new Object[0]; } if (ejb == null) { // must specify remote home throw new JobExecutionException(); } InitialContext jndiContext = null; // get initial context try { jndiContext = getInitialContext(dataMap); } catch (NamingException ne) { throw new JobExecutionException(ne); } try { Object value = null; // locate home interface try { value = jndiContext.lookup(ejb); } catch (NamingException ne) { throw new JobExecutionException(ne); } // get home interface EJBHome ejbHome = (EJBHome) PortableRemoteObject.narrow(value, EJBHome.class); // get meta data EJBMetaData metaData = null; try { metaData = ejbHome.getEJBMetaData(); } catch (RemoteException re) { throw new JobExecutionException(re); } // get home interface class Class homeClass = metaData.getHomeInterfaceClass(); // get remote interface class Class remoteClass = metaData.getRemoteInterfaceClass(); // get home interface ejbHome = (EJBHome) PortableRemoteObject.narrow(ejbHome, homeClass); Method methodCreate = null; try { // create method 'create()' on home interface methodCreate = homeClass.getMethod("create", ((Class[])null)); } catch (NoSuchMethodException nsme) { throw new JobExecutionException(nsme); } // create remote object EJBObject remoteObj = null; try { // invoke 'create()' method on home interface remoteObj = (EJBObject) methodCreate.invoke(ejbHome, ((Object[])null)); } catch (IllegalAccessException iae) { throw new JobExecutionException(iae); } catch (InvocationTargetException ite) { throw new JobExecutionException(ite); } // execute user-specified method on remote object Method methodExecute = null; try { // create method signature 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[i] = arguments[i].getClass(); } } // get method on remote object methodExecute = remoteClass.getMethod(method, argTypes); } catch (NoSuchMethodException nsme) { throw new JobExecutionException(nsme); } try { // invoke user-specified method on remote object Object returnObj = methodExecute.invoke(remoteObj, arguments); // Return any result in the JobExecutionContext so it will be // available to Job/TriggerListeners context.setResult(returnObj); } catch (IllegalAccessException iae) { throw new JobExecutionException(iae); } catch (InvocationTargetException ite) { throw new JobExecutionException(ite); } } finally { // Don't close jndiContext until after method execution because // WebLogic requires context to be open to keep the user credentials // available. See JIRA Issue: QUARTZ-401 if (jndiContext != null) { try { jndiContext.close(); } catch (NamingException e) { // Ignore any errors closing the initial context } } } } 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); } String principal = jobDataMap.getString(PRINCIPAL); if ( principal != null ) { params.put( Context.SECURITY_PRINCIPAL, principal ); } String credentials = jobDataMap.getString(CREDENTIALS); if ( credentials != null ) { params.put( Context.SECURITY_CREDENTIALS, credentials ); } return (params.size() == 0) ? new InitialContext() : new InitialContext(params); } }
?
自定义EJBHome接口:
package com.easyway.app.ejb;import java.rmi.RemoteException;import javax.ejb.CreateException;import javax.ejb.EJBHome;/** * Home接口的方法 * @author longgangbai * */public interface HelloWorldHome extends EJBHome{HelloWorldRemote create() throws RemoteException, CreateException;}
?
EJB远程接口:
package com.easyway.app.ejb;import java.rmi.RemoteException;import javax.ejb.EJBObject;/** * 远程接口 * @author longgangbai * */public interface HelloWorldRemote extends EJBObject{ public String sayHello(String country,String cityName) throws RemoteException;}
?
EJB的bean类:
package com.easyway.app.ejb;import java.rmi.RemoteException;import javax.ejb.EJBException;import javax.ejb.SessionBean;import javax.ejb.SessionContext;/** * 會話bean的实现 * * (必须有会话bean的5个状态,可以为空实现,和远程接口中要实现的方法, * 把实现方法写在一个类里,每次 new一个类的对象,返回一个实现方法给Bean) * * @author longgangbai * */public class HelloWorldBean implements SessionBean{ /** * */private static final long serialVersionUID = 1L; public void setSessionContext(SessionContext arg0) throws EJBException, RemoteException { System.out.println("set session context"); } public void ejbCreate() throws EJBException { System.out.println("ejb create"); } public void ejbRemove() throws EJBException, RemoteException { System.out.println("ejb remove"); } public void ejbActivate() throws EJBException, RemoteException { System.out.println("ejb activate"); } public void ejbPassivate() throws EJBException, RemoteException { System.out.println("ejb passivate"); } /** * 自定义的EJB的方法 * @param country * @param cityName * @return * @throws RemoteException */ public String sayHello(String country,String cityName) throws RemoteException { String helloworld="your are in "+country+" on "+cityName+"Welecome to ejb2.0,HXL"; System.out.println("helloworld="+helloworld); return helloworld; }}
?在META-INF包下的ejb-jar.xml配置如下:
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"><ejb-jar><description>ejb</description><display-name>quartzEJB2</display-name><!-- 配置会话bean的信息 --><enterprise-beans><session><display-name>helloEJB</display-name><ejb-name>helloEJB</ejb-name><home>com.easyway.app.ejb.HelloWorldHome</home><remote>com.easyway.app.ejb.HelloWorldRemote</remote><ejb-class>com.easyway.app.ejb.HelloWorldBean</ejb-class><session-type>Stateful</session-type><transaction-type>Bean</transaction-type></session></enterprise-beans></ejb-jar>
?
jboss配置如下:
jboss.xml内容如下:
<?xml version="1.0" encoding="gb2312"?><!-- <jndi-name>元素的值必须在容器中唯一 --><jboss><enterprise-beans><session><ejb-name>helloEJB</ejb-name><jndi-name>ejb/helloEJB</jndi-name></session></enterprise-beans></jboss>
?
?
?
创建触发器和相关的job调用
package com.easyway.app.ejb;import static org.quartz.CronScheduleBuilder.cronSchedule;import static org.quartz.JobBuilder.newJob;import static org.quartz.TriggerBuilder.newTrigger;import java.text.ParseException;import java.util.Date;import org.quartz.CronTrigger;import org.quartz.JobDataMap;import org.quartz.JobDetail;import org.quartz.Scheduler;import org.quartz.SchedulerException;import org.quartz.SchedulerFactory;import org.quartz.SchedulerMetaData;import org.quartz.impl.StdSchedulerFactory;import org.quartz.jobs.ee.ejb.EJBInvokerJob;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * 调用EJB2.0的定时任务 * @author longgangbai * */public class QuartzEjb2Main {/** * * @param args * @throws SchedulerException * @throws ParseException */public static void main(String[] args) throws SchedulerException, ParseException { Logger log = LoggerFactory.getLogger(QuartzEjb2Main.class); log.info("------- Initializing -------------------"); // First we must get a reference to a scheduler //创建调度任务工厂 SchedulerFactory sf = new StdSchedulerFactory(); //创建调度对象 Scheduler sched = sf.getScheduler(); log.info("------- Scheduling Jobs ----------------"); // jobs can be scheduled before sched.start() has been called // job 1 will run every 20 seconds //创建一个定时任务 JobDetail job = newJob(EJBInvokerJob.class) .withIdentity("job1", "group1") .build(); //创建Cron触发器 CronTrigger trigger = newTrigger() .withIdentity("trigger1", "group1") .withSchedule(cronSchedule("0/20 * * * * ?")) .build(); //创建一个初始化任务的信息 // pass initialization parameters into the job JobDataMap jobDataMap=job.getJobDataMap(); //设置EJB的JNDI名称 jobDataMap.put(EJBInvokerJob.EJB_JNDI_NAME_KEY, "ejb/helloEJB"); //设置ejb的调用方法名称 jobDataMap.put(EJBInvokerJob.EJB_METHOD_KEY, "sayHello"); //设置ejb输入参数的类型 jobDataMap.put(EJBInvokerJob.EJB_ARG_TYPES_KEY,new Class[]{ String.class,String.class}); //设置输入类型的参数值 jobDataMap.put(EJBInvokerJob.EJB_ARGS_KEY,new Object[]{ "china","shanghai"}); //设置EJB的初始化参数 jobDataMap.put(EJBInvokerJob.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); //jobDataMap.put(EJBInvokerJob.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces"); //设置EBJ的uri路径 jobDataMap.put(EJBInvokerJob.PROVIDER_URL, "jnp://localhost:1099"); //设置调用相关的任务和触发器信息 Date ft = sched.scheduleJob(job, trigger); log.info(job.getKey() + " has been scheduled to run at: " + ft + " and repeat based on expression: " + trigger.getCronExpression()); //启动相关的的调度信息 sched.start(); log.info("------- Started Scheduler -----------------"); log.info("------- Waiting five minutes... ------------"); try { // wait five minutes to show jobs Thread.sleep(300L * 1000L); // executing... } catch (Exception e) { } log.info("------- Shutting Down ---------------------"); //关闭相关的调度 sched.shutdown(true); log.info("------- Shutdown Complete -----------------"); SchedulerMetaData metaData = sched.getMetaData(); log.info("Executed " + metaData.getNumberOfJobsExecuted() + " jobs.");}}
?