-
1. Re: Executing a Method when Seam Starts
israel.bgf May 27, 2009 9:14 PM (in response to israel.bgf)@Startup solved my problem but now there is another. How can i retrive my timer, or delete all timers when the application starts? It keep creating timers, and i want to manage them (delete-them). I need that my timers live just for the scope of my application (if the server restart, it's make sense to my service just be restarted too with the application).
This timer stuff is cool, but very crazy.
-
2. Re: Executing a Method when Seam Starts
gonorrhea May 27, 2009 10:07 PM (in response to israel.bgf)This may help. We have some custom JARs, so ignore the AD lookup API stuff (e.g. UserItem). This solution uses org.jboss.seam.postInitialization rather than @Startup but most likely same effect/strategy.
AFAIK, you only want one EJB timer to exist, so why are there multiple? you should not have to deal with deleting them.
In my case below, the scheduleTimer() method in the controller component should be called once per start of app server, no more, no less.
I'm not sure if/how the EJB timers are persisted to a DB, but at the time I believe I was using HSQLDB.
Read JSR220-core ch. 18 on timer service for more info...
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 /> -->
ScheduleProcessor.java:
@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; @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) { 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; } }
ScheduleController.java:
@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; } }
-
3. Re: Executing a Method when Seam Starts
israel.bgf May 27, 2009 11:09 PM (in response to israel.bgf)I just want one timer indeed, but i create one every time that my app starts, so if i dont delete the old ones when my app start, i will be making new timers (timers are persistent), that's why i'm deleting them every time my app starts.
hmm, but i should just dont create new ones istead deleting the old. D'oh.
Anyway, Arbi dont you get EJB error when restarting your app? Lets say that your timer execute something every minute, so if you shutdown the server for 10 minutes, when you restart it, the timer will try to re-execute the timers 10 times, but in that moment the Seam application did not started yet, so I get an error telling that a seam component (logger) was tried to be executed outside the
Seam context
.Did you understand?
Thks in advance.
-
4. Re: Executing a Method when Seam Starts
gonorrhea May 27, 2009 11:56 PM (in response to israel.bgf)What are you using as a back-end to persist your timers (e.g. RDBMS or what?)
Like I said, IIRC I was using HSQLDB which is an in-process DB. AFAIK, when you shut down JBoss and are using HSQLDB, the records are gone.
Perhaps there is a way in the API to determine if there is already a timer existing? Have you tried Quartz? Sorry, the code I used to periodically query AD and I haven't used EJB timers in any other context other than that.
I believe there are some improvements to EJB timer service in EJB 3.1...
-
5. Re: Executing a Method when Seam Starts
kapitanpetko May 28, 2009 4:51 AM (in response to israel.bgf)Have a look at the javax.ejb.TimerService interface. You can list existing timers and cancel the ones you don't need.
Or you can simply choose to reuse the one already installed, if settings haven't changed.Quartz gives you more control over this, but for your use case you may not need it.
You could also tweak the JBoss Timer service if you want. Have a look at scheduler-service.xml
in your JBoss deploy directory.HTH
-
6. Re: Executing a Method when Seam Starts
israel.bgf May 28, 2009 6:13 PM (in response to israel.bgf)I got the things working now. I just check for older timers, and dont add new ones. Anyway, the only annoyng thing is the exception on jboss startup, but nothing serious.
And at least in the Jboss 4.2.3, the timer is persistent Arbi. In fact that's what the specification says about EJB Timers, they are that way by default. I'm a jboss-as noob, but i think that the JBoss save them in an local-file with the HSQLDB.
And i'm trying to just use EJB, i dont want third partie stuff. :)
And thks for the xml tip Nikolay.
Israel