tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Romain Manni-Bucau <rmannibu...@gmail.com>
Subject Re: Cluster + @Schedule
Date Sat, 18 Oct 2014 08:37:35 GMT
Le 18 oct. 2014 00:36, "Leonardo K. Shikida" <shikida@gmail.com> a écrit :
>
> Hi
>
> well, now I really have some doubts.
>
> I've noticed that in 1.6.0.2 the timers weren't ok, so I've switched to
the latest 1.7.0.
>
> It seems that from 1.7.0, quartz packages now belong to the apache
domain, so the application.properties from this URL
>
>
http://quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigJDBCJobStoreClustering
>
> will only work if I rename all the packages to follow the same pattern.
>

We have a compatibility mode by default for it

> Well, I'd suggest to document this somewhere :-)
>
> Another thing is that I've created a very very simple example using two
different TomEE+ 1.7.0 using the same code, both pointing to the same DB,
like this
>
> package test;
>
> import java.util.Date;
> import java.util.List;
>
> import javax.annotation.PostConstruct;
> import javax.annotation.Resource;
> import javax.ejb.Lock;
> import javax.ejb.LockType;
> import javax.ejb.Schedule;
> import javax.ejb.ScheduleExpression;
> import javax.ejb.Singleton;
> import javax.ejb.Timeout;
> import javax.ejb.Timer;
> import javax.ejb.TimerConfig;
> import javax.ejb.TimerService;
>
> import org.apache.openejb.core.timer.TimerData;
> import org.apache.openejb.quartz.JobKey;
> import org.apache.openejb.quartz.Scheduler;
> import org.apache.openejb.quartz.SchedulerException;
> import org.apache.openejb.quartz.Trigger;
> import org.apache.openejb.quartz.impl.StdSchedulerFactory;
> import org.apache.openejb.quartz.impl.matchers.GroupMatcher;
>
> @Singleton
> @Lock(LockType.READ)
> public class MyQuartzService {
>
>     @Resource
>     private TimerService timerService;
>
>     private long name = System.currentTimeMillis();
>
>     @PostConstruct
>     public void init() {
>         System.out.println(name+" initialized");
>
>         ScheduleExpression exp = new ScheduleExpression();
>         exp.minute("0,5,10,15,20,25,30,35,40,45,50,55");
>         exp.hour("*");
>         exp.second(30); //does not make any difference
>
>
>         TimerConfig config = new TimerConfig();
>         config.setInfo("hello "+name);
>
>         Timer created = timerService.createCalendarTimer(exp,config);
>         System.out.println("created "+created.getInfo());
>         System.out.println("handle "+created.getHandle().toString());
>     }
>
>     @Timeout
>     public void executeTimer(Timer timer) throws Exception {
>         System.out.println(name+" executeTimer ("+getInfo(timer)+") "+new
Date());
>     }
>
>     /**
>      * <br>17/10/2014
>      *
>      * @param timer
>      * @return
>      * @throws SchedulerException
>      */
>     private String getInfo(Timer timer) throws SchedulerException {
>         Scheduler scheduler = new
StdSchedulerFactory().getScheduler("MyClusteredScheduler");
>         for (String groupName : scheduler.getJobGroupNames()) {
>             for (JobKey jobKey :
scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
>                 for (Trigger trigger : (List<Trigger>)
scheduler.getTriggersOfJob(jobKey)) {
>                     TimerData timerData =
(TimerData)trigger.getJobDataMap().get("TIMER_DATA");
>                     Object s = timerData.getInfo();
>                     if (s instanceof String){
>                         String timerInfo = ((String) s);
>                         return timerInfo;
>                     }
>                 }//for trigger
>             }//for jobkey
>         }//for groupname
>
>         return null;
>     }
>
>     @Schedule(hour="*", minute="*")
>     public void executeEveryMinute() {
>         System.out.println(name+" executeEveryMinute "+new Date());
>     }
>
>     //Fail to parse schedule expression
javax.ejb.ScheduleExpression@78aded17
> //    @Schedule(hour="*", minute="5/*")
>     @Schedule(hour="*", minute="0,5,10,15,20,25,30,35,40,45,50,55")
>     public void executeEvery5Minutes() {
>         System.out.println(name+" executeEvery5Minutes "+new Date());
>     }
>
> }
>
>
> and
>
>
#============================================================================
> # Configure Main Scheduler Properties
>
#============================================================================
>
> org.apache.openejb.quartz.scheduler.instanceName = MyClusteredScheduler
> org.apache.openejb.quartz.scheduler.instanceId = AUTO
>
>
#============================================================================
> # Configure ThreadPool
>
#============================================================================
>
> org.apache.openejb.quartz.threadPool.class =
org.apache.openejb.quartz.simpl.SimpleThreadPool
> org.apache.openejb.quartz.threadPool.threadCount = 25
> org.apache.openejb.quartz.threadPool.threadPriority = 5
>
>
#============================================================================
> # Configure JobStore
>
#============================================================================
>
> org.apache.openejb.quartz.jobStore.misfireThreshold = 60000
>
> org.apache.openejb.quartz.jobStore.class =
org.apache.openejb.quartz.impl.jdbcjobstore.JobStoreTX
> org.apache.openejb.quartz.jobStore.driverDelegateClass =
org.apache.openejb.quartz.impl.jdbcjobstore.oracle.OracleDelegate
> org.apache.openejb.quartz.jobStore.useProperties = false
> org.apache.openejb.quartz.jobStore.dataSource = myDS
> org.apache.openejb.quartz.jobStore.tablePrefix = QRTZ_
>
> org.apache.openejb.quartz.jobStore.isClustered = true
> org.apache.openejb.quartz.jobStore.clusterCheckinInterval = 20000
>
>
#============================================================================
> # Configure Datasources
>
#============================================================================
>
> org.apache.openejb.quartz.dataSource.myDS.driver =
oracle.jdbc.driver.OracleDriver
> org.apache.openejb.quartz.dataSource.myDS.URL =
jdbc:oracle:thin:@localhost:1521:XE
> org.apache.openejb.quartz.dataSource.myDS.user = xxxxxx
> org.apache.openejb.quartz.dataSource.myDS.password = xxxxxx
> org.apache.openejb.quartz.dataSource.myDS.maxConnections = 5
> org.apache.openejb.quartz.dataSource.myDS.validationQuery=select 0 from
dual
>
>
> well, here's what it seems to be happening
>
> logs from server 1
>
> Informações: Server startup in 3246 ms
> 1413583920154 initialized
> created hello 1413583920154
> handle org.apache.openejb.core.timer.TimerHandleImpl@5a483ce
> 1413583920154 executeEveryMinute Fri Oct 17 19:12:00 BRT 2014
> 1413583920154 executeEvery5Minutes Fri Oct 17 19:15:00 BRT 2014
> 1413583920154 executeTimer (hello 1413583260198) Fri Oct 17 19:15:30 BRT
2014
> 1413583920154 executeEveryMinute Fri Oct 17 19:16:00 BRT 2014
> 1413583920154 executeEveryMinute Fri Oct 17 19:17:00 BRT 2014
> 1413583920154 executeEveryMinute Fri Oct 17 19:19:00 BRT 2014
> 1413583920154 executeEveryMinute Fri Oct 17 19:20:00 BRT 2014
> 1413583920154 executeTimer (hello 1413583260198) Fri Oct 17 19:20:30 BRT
2014
>
>
> logs from server 2
>
> Informações: Server startup in 3243 ms
> 1413583980207 initialized
> created hello 1413583980207
> handle org.apache.openejb.core.timer.TimerHandleImpl@77c24f14
> 1413583980207 executeEveryMinute Fri Oct 17 19:13:00 BRT 2014
> 1413583980207 executeEveryMinute Fri Oct 17 19:14:00 BRT 2014
> 1413583980207 executeEveryMinute Fri Oct 17 19:15:00 BRT 2014
> 1413583980207 executeEveryMinute Fri Oct 17 19:18:00 BRT 2014
> 1413583980207 executeEvery5Minutes Fri Oct 17 19:20:00 BRT 2014
>
> "hello 1413583260198" was created in a previous attempt, so my feeling is
that, somehow, even creating a new timer on every server restart, tomEE (or
Quartz) is assuming that the calendar timer is already created (checking by
cron expression maybe?). In fact, in the DB, there are only 3 triggers
everytime.
>
>

If persistent that s possible

> ​
>
> Another thing I've noticed is that the code seems not to accept the
cron-like expression, for example
>
>     @Schedule(hour="*", minute="0,5,10,15,20,25,30,35,40,45,50,55")
>     public void executeEvery5Minutes() {
>         System.out.println(name+" executeEvery5Minutes "+new Date());
>     }
>
> works while
>
>     @Schedule(hour="*", minute="5/*")
>     public void executeEvery5Minutes() {
>         System.out.println(name+" executeEvery5Minutes "+new Date());
>     }
>
> does not
>
> the cron-like is described at
http://docs.oracle.com/javaee/6/api/javax/ejb/ScheduleExpression.html
>
> Please tell me if this is the expected behavior, because maybe I am not
getting the spec, but I thought it would be possible to create different
triggers for different jobs even if they had the same cron expression.
>

*/5 no?

> TIA
>
> []
>
> Leo
>
> On Fri, Oct 17, 2014 at 4:48 PM, Leonardo K. Shikida <shikida@gmail.com>
wrote:
>>
>> Just a note
>>
>> Romain had it in a blog already since 2012... next time I'll do some
research first
>>
>>
http://rmannibucau.wordpress.com/2012/08/22/tomee-quartz-configuration-for-scheduled-methods/
>>
>> Tested here using 1.6.0.2 and it works like a charm, for both ways
(static and dynamic timers)
>>
>> Curiously, Quartz works as a cluster even if tomee is not clustered
(very smart).
>>
>> Also noticed that this configuration needs some extra jars (probably
indicated somewhere in the quartz documentation, I guess, such as c3p0) and
my quartz DB script had a little bug (probably outdated -
https://code.google.com/p/myschedule/issues/detail?id=131)
>>
>> Other than that, it just seems to work very well.
>>
>> Thanks again, pals.
>>
>> Leo
>>
>>
>>
>>
>> []
>>
>> Leo
>>
>> On Fri, Oct 17, 2014 at 10:41 AM, Leonardo K. Shikida <shikida@gmail.com>
wrote:
>>>
>>> Thanks Andy and Romain. That's exactly what I was looking for.
>>>
>>> []
>>>
>>> Leo
>>>
>>> On Thu, Oct 16, 2014 at 11:37 AM, Andy Gumbrecht <
agumbrecht@tomitribe.com> wrote:
>>>>
>>>> Hi Leonardo,
>>>>
>>>> Never feel like a question is dumb if you're searching for an answer.
That's why we are here.
>>>>
>>>> You will find information on clustering Quartz using a JDBC JobStore
here:
http://quartz-scheduler.org/generated/2.2.1/html/qs-all/#page/Quartz_Scheduler_Documentation_Set/re-cls_cluster_configuration.html#
>>>>
>>>> Just make sure those properties are consistent across your TomEE
cluster and you'll be fine.
>>>>
>>>> The @Schedule is more tricky as you will be responsible for obtaining
a cluster wide lock from that method.
>>>> The easiest way would be to configure a DataSource to a central
database that is accessible by all the TomEE instances in the cluster - Use
a simple table with a BIT type and a DATETIME
>>>> Whichever '@Schedule' method gets the lock can then run the operation
(and unlock afterwards, so use a try/finally block) - The date can be used
to check for a lock timeout if a method fails to unlock for whatever reason
(a crash for example).
>>>>
>>>> Andy.
>>>>
>>>>
>>>> On 16/10/2014 12:27, Leonardo K. Shikida wrote:
>>>>>
>>>>> Hi
>>>>>
>>>>> this doubt may sound dumb, but if I have an EJB with a scheduled task
like
>>>>>
>>>>>      @Schedule(dayOfWeek = "*")
>>>>>      public void runMeDaily() {...}
>>>>>
>>>>> and if I am in a clustered environment, is there any way to make this
job
>>>>> run in only one of the instances? (only once)
>>>>>
>>>>> of course, I can set a flag somewhere and check it before the
execution of
>>>>> such task, so only the first cluster instance would run it, but I am
>>>>> curious if it's possible using some configuration magic.
>>>>>
>>>>> another doubt is: if I have 2 clustered tomee instances, how do I
make both
>>>>> point to the same scheduler? By scheduler I mean something like
>>>>>
>>>>> Scheduler scheduler = new
StdSchedulerFactory().getScheduler("myScheduler");
>>>>>
>>>>>
>>>>> My feeling is that my cluster will need a centralized quartz scheduler
>>>>> service somehow, so if there's some way to do that using tomee, it
would be
>>>>> useful for me.
>>>>>
>>>>> TIA
>>>>>
>>>>> Leo
>>>>>
>>>>
>>>>
>>>> --
>>>>   Andy Gumbrecht
>>>>   https://twitter.com/AndyGeeDe
>>>>   http://www.tomitribe.com
>>>>
>>>
>>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message