Help

Controls

PermLinkWikiLink

Built with Seam

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.

Forum: Seam Users Forum ListTopic List
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

7 Replies:
10. Jul 2008, 19:36 CET | Link

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(); 
    } 
}
10. Jul 2008, 20:29 CET | Link

I added seam.quartz.properties and deployed to the same location as seam.properties. Still no beans.

#============================================================================
# Configure Main Scheduler Properties
#============================================================================

org.quartz.scheduler.instanceName Sched1
org.quartz.scheduler.instanceId AUTO
org.quartz.scheduler.rmi.export false
org.quartz.scheduler.rmi.proxy false

#============================================================================
# Configure ThreadPool
#============================================================================

org.quartz.threadPool.class org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount 3

#============================================================================
# Configure JobStore
#============================================================================

org.quartz.jobStore.misfireThreshold 60000
org.quartz.jobStore.class org.quartz.simpl.RAMJobStore
11. Jul 2008, 01:24 CET | Link
Arbi Sookazian

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;
    }
}
19. Jul 2008, 05:07 CET | Link

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

    }

}
19. Jul 2008, 07:37 CET | Link

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


#==============================================================
# Configure Main Scheduler Properties
#==============================================================

org.quartz.scheduler.instanceName Sched1
org.quartz.scheduler.instanceId AUTO
org.quartz.scheduler.rmi.export false
org.quartz.scheduler.rmi.proxy false

#==============================================================
# Configure ThreadPool
#==============================================================

org.quartz.threadPool.class org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount 3

#==============================================================
# Configure JobStore
#==============================================================

org.quartz.jobStore.misfireThreshold 60000
org.quartz.jobStore.class org.quartz.simpl.RAMJobStore

Excerpt of my properties file with the Cron String


addCronInterval=0 0,15,30,45 * * * ?
roleCronInterval=0 10,25,40,55 * * * ?

components.xml

Added schema: 
xmlns:async="http://jboss.com/products/seam/async" 
Added quartz: 
<async:quartz-dispatcher />
17. Sep 2008, 23:00 CET | Link

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.

18. Sep 2008, 03:29 CET | Link

Sam,

The sample code I posted, and the original sample code worked for me. Make sure you have two classes.