You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
| Online: | 32 Members of 4186 |
| Forum: Seam Users |
10. Jul 2008, 19:28 CET | Link |
Quartz has been giving me a headache. The job runs on Startup, but not again.
Here is my setup:
components.xml Added schema: xmlns:async="http://jboss.com/products/seam/async" Added quartz: <async:quartz-dispatcher />
build.xml Added quartz.jar to be deployed in the ear
Action @Name("myBulkAction") @Scope( ScopeType.APPLICATION ) @Startup public class MyBulkAction { @Logger(value="com.my.log4j.category.") private Log log; @Create public void create(){ startJob1(new Date(), "0,15,30,45 * * * *", getExpiration()); startJob2(new Date(), "10,25,40,55 * * * *", getExpiration()); } @Asynchronous public void startJob1(@Expiration Date when, @IntervalCron String cron, @FinalExpiration Date endDate) { doSomething(); } @Asynchronous public void startJob2(@Expiration Date when, @IntervalCron String cron, @FinalExpiration Date endDate) { doSomethingElse(); } ... private Date getExpiration(){ Calendar cal = Calendar.getInstance (); cal.set (3000, Calendar.JAN, 1); return cal.getTime(); } }
Any suggestions would be much appreciated. Being a unix geek, the Cron format makes perfect sense to me.
Thanks in advance!
- Mike Schwartz
Sorry about the formatting, trying again:
@Name("myBulkAction") @Scope( ScopeType.APPLICATION ) @Startup public class MyBulkAction { @Logger(value="com.my.log4j.category.") private Log log; @Create public void create(){ startJob1(new Date(), "0,15,30,45 * * * *", getExpiration()); startJob2(new Date(), "10,25,40,55 * * * *", getExpiration()); } @Asynchronous public void startJob1(@Expiration Date when, @IntervalCron String cron, @FinalExpiration Date endDate) { doSomething(); } @Asynchronous public void startJob2(@Expiration Date when, @IntervalCron String cron, @FinalExpiration Date endDate) { doSomethingElse(); } ... private Date getExpiration(){ Calendar cal = Calendar.getInstance (); cal.set (3000, Calendar.JAN, 1); return cal.getTime(); } }I added seam.quartz.properties and deployed to the same location as seam.properties. Still no beans.
Compare to my code (uses Quartz or EJB3 timer):
components.xml: <event type=org.jboss.seam.postInitialization> <action execute=#{controller.scheduleTimer}/> </event> <!-- Install the QuartzDispatcher --> <async:quartz-dispatcher/> <!-- Install the EJB timer service --> <!-- <async:timer-service-dispatcher /> -->
@Name("controller") @AutoCreate public class ScheduleController implements Serializable { @In ScheduleProcessor processor; @Logger Log log; private Map<String,List<UserItem>> map; private String distinguishedNameShims; private String distinguishedNameItJava; private Timer timer; private QuartzTriggerHandle quartzTriggerHandle; public void scheduleTimer() { Long pollingInterval = null; String activeDirectoryPollingInterval = CoxProperties.getPropertyObject().getProperty(CoxConstants.ACTIVE_DIRECTORY_POLLING_INTERVAL); if (activeDirectoryPollingInterval != null) { pollingInterval = Long.valueOf(activeDirectoryPollingInterval); } Boolean usingEjbTimer = Boolean.valueOf(CoxProperties.getPropertyObject().getProperty(CoxConstants.USING_EJB_TIMER)==null?"false":CoxProperties.getPropertyObject().getProperty(CoxConstants.USING_EJB_TIMER)); distinguishedNameShims = CoxProperties.getPropertyObject().getProperty(CoxConstants.DISTINGUISHED_NAME_SHIMS); if (usingEjbTimer) { timer = processor.createEjbTimer(new Date(), pollingInterval, distinguishedNameShims); } else { quartzTriggerHandle = processor.createQuartzTimer(new Date(), pollingInterval, distinguishedNameShims); } } public Map<String, List<UserItem>> getMembersOfRoleMap(){ //get the map from the application context of EJBPollingProcessorBean map = processor.getMap(); return map; } }@Name("processor") @AutoCreate @Scope(ScopeType.APPLICATION) public class ScheduleProcessor { //TO DO: map needs to be stored in application context as it is session-independent data //TO DO: convert this into an ArrayList of map objects b/c we will need a map // for every drop-down in each app private List<UserItem> userItemList; private Map<String, List<UserItem>> map; private Boolean cancelComplete = false; @Logger Log log; //@In(create=true) TimerService timerService; //EJB Timer version... @Asynchronous @Transactional public Timer createEjbTimer(@Expiration Date when, @IntervalDuration Long interval, String distinguishedGroupName) { process(when, interval, distinguishedGroupName); return null; } //Quartz version... @Asynchronous @Transactional public QuartzTriggerHandle createQuartzTimer(@Expiration Date when, @IntervalDuration Long interval, String distinguishedGroupName) { process(when, interval, distinguishedGroupName); return null; } private void process(Date when, Long interval, String distinguishedGroupName) { /*if(!cancelComplete) { //cancel existing timers... Collection collection = timerService.getTimers(); if (collection != null) { Iterator it = collection.iterator(); while(it.hasNext()) { Timer timer = (Timer) it.next(); timer.cancel(); } cancelComplete = true; } }*/ log.info("when = " + when); log.info("interval = " + interval); log.info("distinguishedGroupName = "+distinguishedGroupName); String searchBase = CoxProperties.getPropertyObject().getProperty(CoxConstants.ACTIVE_DIRECTORY_SEARCH_BASE); String providerUrl = CoxProperties.getPropertyObject().getProperty(CoxConstants.ACTIVE_DIRECTORY_PROVIDER_URL); String principal = CoxProperties.getPropertyObject().getProperty(CoxConstants.ACTIVE_DIRECTORY_USER); String credentials = CoxProperties.getPropertyObject().getProperty(CoxConstants.ACTIVE_DIRECTORY_PWD); // Declare holders search result's SearchAdapterResult<UserItem> userSearchResults = null; // Create a new instance of CADILS search adapter SearchAdapter sa = new SearchAdapter(searchBase, providerUrl, principal, credentials); try { String groupSearchFilter = "*)(memberOf=" + distinguishedGroupName; userSearchResults = sa.searchBySAMAccountName(groupSearchFilter); if (userSearchResults.hasItems()) { //List of all the AD users who belong to your group userItemList = userSearchResults.getItemList(); if (map == null) { map = new TreeMap<String, List<UserItem>>(); } map.put(distinguishedGroupName, userItemList); } } catch (SearchFailedException sfe) { log.error(sfe); } } public Map<String, List<UserItem>> getMap() { return map; } }Thank you for your post. It is working just great. Well I will post simplification of your code.
package edu.baylor.icpc.session.email; import java.util.Date; import javax.ejb.Timer; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.AutoCreate; import org.jboss.seam.annotations.Logger; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.async.Asynchronous; import org.jboss.seam.annotations.async.Expiration; import org.jboss.seam.annotations.async.IntervalDuration; import org.jboss.seam.async.QuartzTriggerHandle; import org.jboss.seam.log.Log; @Name("processor") @AutoCreate @Scope(ScopeType.APPLICATION) public class ScheduleProcessor { @Logger Log log; //EJB Timer version... @Asynchronous @Transactional public Timer createEjbTimer(@Expiration Date when, @IntervalDuration Long interval, String text) { process(when, interval, text); return null; } //Quartz version... @Asynchronous @Transactional public QuartzTriggerHandle createQuartzTimer(@Expiration Date when, @IntervalDuration Long interval, String text) { process(when, interval, text); return null; } private void process(Date when, Long interval, String text) { log.info("when = " + when); log.info("interval = " + interval); log.info("text = " + text); } }components.xml
<event type="org.jboss.seam.postInitialization"> <action execute="#{controller.scheduleTimer}"/> </event> <!-- Install the QuartzDispatcher --> <async:quartz-dispatcher />package edu.baylor.icpc.session.email; import java.io.Serializable; import java.util.Date; import java.util.Map; import javax.ejb.Timer; 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.async.QuartzTriggerHandle; import org.jboss.seam.log.Log; @Name("controller") @AutoCreate public class ScheduleController implements Serializable { /** * */ private static final long serialVersionUID = -6332836501640042340L; @In ScheduleProcessor processor; @Logger Log log; private String text = "ahoj"; private Timer timer; private QuartzTriggerHandle quartzTriggerHandle; public void scheduleTimer() { Long pollingInterval = 5000L; boolean usingEjbTimer = true; if (usingEjbTimer) { timer = processor.createEjbTimer(new Date(), pollingInterval, text); } else { quartzTriggerHandle = processor.createQuartzTimer(new Date(), pollingInterval, text); } } }Thanks for posting this code, it helped greatly. Here is my version, which is slightly different and just uses quartz:
package edu.nova.itss.grouper.async; import java.util.Date; import java.util.Iterator; import java.util.List; import org.jboss.seam.ScopeType; 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.Scope; import org.jboss.seam.annotations.Transactional; import org.jboss.seam.annotations.async.Asynchronous; import org.jboss.seam.annotations.async.Expiration; import org.jboss.seam.annotations.async.IntervalCron; import org.jboss.seam.async.QuartzTriggerHandle; import org.jboss.seam.log.Log; import edu.nova.itss.grouper.facade.AuthManagerSearchService; import edu.nova.itss.grouper.facade.AuthManagerWriteService; import edu.nova.itss.grouper.model.People; import edu.nova.itss.grouper.model.Person; import edu.nova.itss.grouper.util.BulkUtil; @Name("processor") @AutoCreate @Scope(ScopeType.APPLICATION) public class ScheduleProcessor { @Logger(value="edu.nova.itss.grouper.async.addlog") private Log logadd; @Logger(value="edu.nova.itss.grouper.async.rolelog") private Log logrole; @In(required=false, create=true) AuthManagerWriteService authManagerService; @In(required=false, create=true) AuthManagerSearchService amSearch; @Asynchronous @Transactional public QuartzTriggerHandle createQuartzAddTimer(@Expiration Date when, @IntervalCron String interval){ bulkAddPerson(); return null; } @Asynchronous @Transactional public QuartzTriggerHandle createQuartzRoleTimer(@Expiration Date when, @IntervalCron String interval){ String date = new Date().toString(); try{ bulkUpdateRole(); } catch (Exception e){ logrole.error(date + ": Error processing role log file."); e.printStackTrace(); } return null; } . . . }And the Controller
package edu.nova.itss.grouper.async; import java.io.Serializable; import java.util.Date; 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.async.QuartzTriggerHandle; import org.jboss.seam.log.Log; import edu.nova.itss.grouper.util.BulkUtil; @Name("controller") @AutoCreate public class ScheduleController implements Serializable { private static final long serialVersionUID = 7609983147081676186L; @In ScheduleProcessor processor; @Logger Log log; private QuartzTriggerHandle quartzAddTriggerHandle; private QuartzTriggerHandle quartzRoleTriggerHandle; public void scheduleTimer() { String addCronInterval = null; String roleCronInterval = null; try{ addCronInterval = BulkUtil.getProperty("addCronInterval"); roleCronInterval = BulkUtil.getProperty("roleCronInterval"); } catch (Exception e){ e.printStackTrace(); } if ((addCronInterval != null)&(roleCronInterval != null)) { quartzAddTriggerHandle = processor.createQuartzAddTimer(new Date(), addCronInterval); quartzRoleTriggerHandle = processor.createQuartzRoleTimer(new Date(), roleCronInterval); } } }build.xml
. . . <target name="jar" depends="compile,copyclasses" description="Build the distribution .jar file"> <copy todir="${jar.dir}"> <fileset dir="${basedir}/resources"> <include name="seam.properties" /> <include name="seam.quartz.properties" /> <include name="*.drl" /> </fileset> </copy> . . . <target name="ear" description="Build the EAR"> <copy todir="${ear.dir}"> <fileset dir="${basedir}/resources"> <include name="*jpdl.xml" /> <include name="*hibernate.cfg.xml" /> <include name="jbpm.cfg.xml" /> </fileset> <fileset dir="${lib.dir}"> <include name="jboss-seam.jar" /> <include name="quartz.jar" /> </fileset> </copy> . . .seam.quartz.properties
Excerpt of my properties file with the Cron String
components.xml
Did you ever find a solution to this? I'm now encountering the same issue. I have encountered either the case where I can't get it to run the first time or only the first time and never again.
I'm trying to do scheduling on startup as well.
Thanks.
Sam,
The sample code I posted, and the original sample code worked for me. Make sure you have two classes.