Return-Path: X-Original-To: apmail-zest-commits-archive@minotaur.apache.org Delivered-To: apmail-zest-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 54A1E18EC6 for ; Sat, 5 Dec 2015 09:20:17 +0000 (UTC) Received: (qmail 57609 invoked by uid 500); 5 Dec 2015 09:20:17 -0000 Delivered-To: apmail-zest-commits-archive@zest.apache.org Received: (qmail 57564 invoked by uid 500); 5 Dec 2015 09:20:17 -0000 Mailing-List: contact commits-help@zest.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@zest.apache.org Delivered-To: mailing list commits@zest.apache.org Received: (qmail 57525 invoked by uid 99); 5 Dec 2015 09:20:17 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 05 Dec 2015 09:20:17 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id E7D91E0AC7; Sat, 5 Dec 2015 09:20:16 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: niclas@apache.org To: commits@zest.apache.org Date: Sat, 05 Dec 2015 09:20:18 -0000 Message-Id: In-Reply-To: <2c9cf8bf3b0d432e8070aa47ae075e8f@git.apache.org> References: <2c9cf8bf3b0d432e8070aa47ae075e8f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [3/3] zest-java git commit: ZEST-130 - FIrst attempt at the Quartz integration issue. Doesn't work. Quartz is too complex and has not been able to separate its concerns well enough, forcing all new JobStore implementations to do a lot more work than shou ZEST-130 - FIrst attempt at the Quartz integration issue. Doesn't work. Quartz is too complex and has not been able to separate its concerns well enough, forcing all new JobStore implementations to do a lot more work than should have been necessary. Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/551c04d5 Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/551c04d5 Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/551c04d5 Branch: refs/heads/ZEST-130 Commit: 551c04d598e7279507018df2089dc70ca289549e Parents: 725b616 Author: Niclas Hedhman Authored: Sun Nov 22 14:05:16 2015 +0800 Committer: Niclas Hedhman Committed: Sun Nov 22 14:05:16 2015 +0800 ---------------------------------------------------------------------- libraries.gradle | 44 +- libraries/scheduler/build.gradle | 3 +- .../zest/library/scheduler/CalendarWrapper.java | 30 + .../zest/library/scheduler/Calendars.java | 29 + .../zest/library/scheduler/CronSchedule.java | 117 --- .../zest/library/scheduler/JobStoreMixin.java | 710 +++++++++++++++++++ .../zest/library/scheduler/JobWrapper.java | 30 + .../zest/library/scheduler/JobsGroup.java | 28 + .../zest/library/scheduler/JobsGroups.java | 31 + .../zest/library/scheduler/OnceSchedule.java | 68 -- .../apache/zest/library/scheduler/Schedule.java | 131 ---- .../zest/library/scheduler/ScheduleFactory.java | 42 -- .../zest/library/scheduler/Scheduler.java | 140 ---- .../library/scheduler/SchedulerAssembler.java | 66 ++ .../scheduler/SchedulerConfiguration.java | 66 +- .../library/scheduler/SchedulerService.java | 188 ++++- .../library/scheduler/SchedulesHandler.java | 89 --- .../org/apache/zest/library/scheduler/Task.java | 77 -- .../zest/library/scheduler/TriggerWrapper.java | 178 +++++ .../zest/library/scheduler/TriggersGroup.java | 29 + .../zest/library/scheduler/TriggersGroups.java | 29 + .../apache/zest/library/scheduler/ZestJob.java | 36 + .../zest/library/scheduler/ZestJobDetail.java | 128 ++++ .../zest/library/scheduler/ZestJobFactory.java | 63 ++ .../scheduler/bootstrap/SchedulerAssembler.java | 117 --- .../library/scheduler/bootstrap/package.html | 21 - .../defaults/DefaultRejectionHandler.java | 39 - .../defaults/DefaultScheduleFactoryMixin.java | 91 --- .../defaults/DefaultThreadFactory.java | 57 -- .../library/scheduler/internal/Execution.java | 275 ------- .../scheduler/internal/ScheduleTime.java | 61 -- .../scheduler/internal/SchedulerMixin.java | 199 ------ .../library/scheduler/internal/Schedules.java | 28 - .../library/scheduler/internal/TaskRunner.java | 115 --- .../apache/zest/library/scheduler/package.html | 21 - .../library/scheduler/schedule/package.html | 21 - .../library/scheduler/timeline/Timeline.java | 73 -- .../timeline/TimelineForScheduleConcern.java | 90 --- .../scheduler/timeline/TimelineRecord.java | 79 --- .../scheduler/timeline/TimelineRecordStep.java | 27 - .../timeline/TimelineScheduleMixin.java | 136 ---- .../timeline/TimelineScheduleState.java | 26 - .../timeline/TimelineSchedulerServiceMixin.java | 105 --- .../library/scheduler/timeline/package.html | 21 - .../apache/library/scheduler/SchedulerTest.java | 94 +++ .../scheduler/AbstractSchedulerTest.java | 74 -- .../zest/library/scheduler/Constants.java | 26 - .../library/scheduler/CronScheduleTest.java | 83 --- .../apache/zest/library/scheduler/FooTask.java | 75 -- .../zest/library/scheduler/SchedulerTest.java | 205 ------ .../scheduler/docsupport/SchedulerDocs.java | 98 --- .../src/test/resources/logback-test.xml | 32 - 52 files changed, 1707 insertions(+), 2934 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries.gradle ---------------------------------------------------------------------- diff --git a/libraries.gradle b/libraries.gradle index 13c7525..87cac54 100644 --- a/libraries.gradle +++ b/libraries.gradle @@ -54,13 +54,13 @@ def osgiVersion = '4.2.0' // 4.3.0 Fails to compile! - 5.0.0 exists def pdfboxVersion = '1.8.5' def postgresqlVersion = '9.4-1201-jdbc41' def prefuseVersion = '0.21' +def quartzVersion = '2.2.1' def restletVersion = '2.3.4' def rdfVersion = '2.7.9' def riakVersion = '1.4.4' // 2.0.x Fails to compile! def scalaVersion = '2.11.6' def servletVersion = '3.1.0' def shiroVersion = '1.2.3' -def skedVersion = '2.1' def slf4jVersion = '1.7.12' def solrVersion = "1.4.1" // 4.8.1 Fails to compile! def springVersion = '4.1.7.RELEASE' @@ -189,46 +189,46 @@ rootProject.ext { wicket_stateless: "com.jolira:wicket-stateless:$wicketStatelessVersion", // Library & Extension dependencies - jackson_mapper: "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion", - jodamoney: "org.joda:joda-money:$jodaMoneyVersion", - jodatime: "joda-time:joda-time:$jodaTimeVersion", + bonecp: "com.jolbox:bonecp:$bonecpVersion", + bouncy_castle: "org.bouncycastle:bcprov-jdk15on:$bouncyVersion", + commons_dbcp: "commons-dbcp:commons-dbcp:$commonsDbcpVersion", + commons_lang: "commons-lang:commons-lang:$commonsLangVersion", + dnsjava: "dnsjava:dnsjava:$dnsJavaVersion", ehcache: "net.sf.ehcache:ehcache:$ehcacheVersion", elasticsearch: "org.elasticsearch:elasticsearch:$elasticsearchVersion", + freemarker: "org.freemarker:freemarker:$freemarkerVersion", h2: "com.h2database:h2:$h2Version", hazelcast: "com.hazelcast:hazelcast:$hazelcastVersion", + http_client: "org.apache.httpcomponents:httpclient:$httpClientVersion", + jackson_mapper: "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion", + javaSqlGenerator: "org.java-sql-generator:org.java-sql-generator.api:$javasqlgeneratorVersion", + javaSqlGeneratorImpl: "org.java-sql-generator:org.java-sql-generator.implementation:$javasqlgeneratorVersion", jclouds_core: "org.apache.jclouds:jclouds-core:$jcloudsVersion", jclouds_blobstore: "org.apache.jclouds:jclouds-allblobstore:$jcloudsVersion", jclouds_filesystem: "org.apache.jclouds.api:filesystem:$jcloudsVersion", jdbm: "jdbm:jdbm:$jdbmVersion", jedis: "redis.clients:jedis:$jedisVersion", jgoodies_looks: "com.jgoodies:jgoodies-looks:$jgoodiesLooksVersion", + jodamoney: "org.joda:joda-money:$jodaMoneyVersion", + jodatime: "joda-time:joda-time:$jodaTimeVersion", + jta: "javax.transaction:jta:$jtaVersion", leveldb_api: "org.iq80.leveldb:leveldb-api:$leveldbVersion", leveldb_java: "org.iq80.leveldb:leveldb:$leveldbVersion", leveldb_jni_all: "org.fusesource.leveldbjni:leveldbjni-all:$leveldbJniVersion", + liquibase: "org.liquibase:liquibase-core:$liquibaseVersion", mongodb: "org.mongodb:mongo-java-driver:$mongodbVersion", + pdfbox: "org.apache.pdfbox:pdfbox:$pdfboxVersion", + prefuse: "de.sciss:prefuse-core:$prefuseVersion", + quartz: "org.quartz-scheduler:quartz:$quartzVersion", + restlet_xml: "org.restlet.jee:org.restlet.ext.xml:$restletVersion", riak: "com.basho.riak:riak-client:$riakVersion", - jta: "javax.transaction:jta:$jtaVersion", - javaSqlGenerator: "org.java-sql-generator:org.java-sql-generator.api:$javasqlgeneratorVersion", - javaSqlGeneratorImpl: "org.java-sql-generator:org.java-sql-generator.implementation:$javasqlgeneratorVersion", - velocity: "org.apache.velocity:velocity:$velocityVersion", - commons_dbcp: "commons-dbcp:commons-dbcp:$commonsDbcpVersion", - commons_lang: "commons-lang:commons-lang:$commonsLangVersion", servlet_api: "javax.servlet:javax.servlet-api:$servletVersion", - http_client: "org.apache.httpcomponents:httpclient:$httpClientVersion", - woodstox: "org.codehaus.woodstox:woodstox-core-asl:$woodstoxVersion", - restlet_xml: "org.restlet.jee:org.restlet.ext.xml:$restletVersion", - bouncy_castle: "org.bouncycastle:bcprov-jdk15on:$bouncyVersion", - dnsjava: "dnsjava:dnsjava:$dnsJavaVersion", - freemarker: "org.freemarker:freemarker:$freemarkerVersion", shiro: "org.apache.shiro:shiro-core:$shiroVersion", shiro_web: "org.apache.shiro:shiro-web:$shiroVersion", - bonecp: "com.jolbox:bonecp:$bonecpVersion", - liquibase: "org.liquibase:liquibase-core:$liquibaseVersion", - sked: "org.codeartisans:sked:$skedVersion", - yammer_metrics: "com.yammer.metrics:metrics-core:$yammerMetricsVersion", - pdfbox: "org.apache.pdfbox:pdfbox:$pdfboxVersion", - prefuse: "de.sciss:prefuse-core:$prefuseVersion", spymemcached: "net.spy:spymemcached:$spymemcachedVersion", + velocity: "org.apache.velocity:velocity:$velocityVersion", + woodstox: "org.codehaus.woodstox:woodstox-core-asl:$woodstoxVersion", + yammer_metrics: "com.yammer.metrics:metrics-core:$yammerMetricsVersion", // Testing junit: "junit:junit:$junitVersion", http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/build.gradle ---------------------------------------------------------------------- diff --git a/libraries/scheduler/build.gradle b/libraries/scheduler/build.gradle index 37b63d0..29f691c 100644 --- a/libraries/scheduler/build.gradle +++ b/libraries/scheduler/build.gradle @@ -25,8 +25,7 @@ jar { manifest { name = "Apache Zestâ„¢ Library - Scheduler" }} dependencies { compile project( ":org.apache.zest.core:org.apache.zest.core.bootstrap" ) compile project( ':org.apache.zest.libraries:org.apache.zest.library.constraints' ) - compile libraries.sked - compile libraries.slf4j_api + compile libraries.quartz testCompile project( ":org.apache.zest.core:org.apache.zest.core.testsupport" ) testCompile project( ":org.apache.zest.extensions:org.apache.zest.extension.indexing-rdf" ) http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CalendarWrapper.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CalendarWrapper.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CalendarWrapper.java new file mode 100644 index 0000000..4d6a394 --- /dev/null +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CalendarWrapper.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.zest.library.scheduler; + +import org.apache.zest.api.entity.EntityComposite; +import org.apache.zest.api.property.Property; +import org.quartz.Calendar; + +public interface CalendarWrapper extends EntityComposite +{ + Property calendar(); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Calendars.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Calendars.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Calendars.java new file mode 100644 index 0000000..9e38d8a --- /dev/null +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Calendars.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.zest.library.scheduler; + +import org.apache.zest.api.association.NamedAssociation; +import org.apache.zest.api.entity.EntityComposite; + +public interface Calendars extends EntityComposite +{ + NamedAssociation calendars(); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CronSchedule.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CronSchedule.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CronSchedule.java deleted file mode 100644 index 9ee212d..0000000 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CronSchedule.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.zest.library.scheduler; - -import java.lang.annotation.Retention; -import org.apache.zest.api.constraint.Constraint; -import org.apache.zest.api.constraint.ConstraintDeclaration; -import org.apache.zest.api.constraint.Constraints; -import org.apache.zest.api.mixin.Mixins; -import org.apache.zest.api.property.Immutable; -import org.apache.zest.api.property.Property; -import org.apache.zest.library.constraints.annotation.InstanceOf; -import org.apache.zest.library.constraints.annotation.NotEmpty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -@Mixins( CronSchedule.CronScheduleMixin.class ) -public interface CronSchedule - extends Schedule -{ - /** - * The Cron expression indicating when the Schedule is to be run. - * The Schedule can NOT be changed once it is set. If this is needed, delete this Schedule and attach the Task - * to a new Schedule. - * - * @return The cron expression that will be used on {@link org.apache.zest.api.unitofwork.UnitOfWork} completion to compute next run - */ - @CronExpression - @Immutable - Property cronExpression(); - - abstract class CronScheduleMixin - implements CronSchedule - { - private static final Logger LOGGER = LoggerFactory.getLogger( Schedule.class ); - - @Override - public void taskStarting() - { - } - - @Override - public void taskCompletedSuccessfully() - { - } - - @Override - public void taskCompletedWithException( Throwable ex ) - { - } - - @Override - public String presentationString() - { - return cronExpression().get(); - } - - @Override - public long nextRun( long from ) - { - long actualFrom = from; - long firstRun = start().get().getMillis(); - if( firstRun > from ) - { - actualFrom = firstRun; - } - Long nextRun = createCron().firstRunAfter( actualFrom ); - LOGGER.info( "CronSchedule::nextRun({}) is {}", from, firstRun ); - return nextRun; - } - - private org.codeartisans.sked.cron.CronSchedule createCron() - { - return new org.codeartisans.sked.cron.CronSchedule( cronExpression().get() ); - } - } - - @ConstraintDeclaration - @Retention( RUNTIME ) - @NotEmpty - @InstanceOf( String.class ) - @Constraints( CronExpressionConstraint.class ) - @interface CronExpression - { - } - - class CronExpressionConstraint - implements Constraint - { - private static final long serialVersionUID = 1L; - - @Override - public boolean isValid( CronExpression annotation, String cronExpression ) - { - return org.codeartisans.sked.cron.CronSchedule.isExpressionValid( cronExpression ); - } - } -} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobStoreMixin.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobStoreMixin.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobStoreMixin.java new file mode 100644 index 0000000..269b393 --- /dev/null +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobStoreMixin.java @@ -0,0 +1,710 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.zest.library.scheduler; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; +import org.apache.zest.api.entity.EntityBuilder; +import org.apache.zest.api.entity.LifecycleException; +import org.apache.zest.api.injection.scope.Structure; +import org.apache.zest.api.query.Query; +import org.apache.zest.api.query.QueryBuilder; +import org.apache.zest.api.query.QueryBuilderFactory; +import org.apache.zest.api.unitofwork.EntityTypeNotFoundException; +import org.apache.zest.api.unitofwork.NoSuchEntityException; +import org.apache.zest.api.unitofwork.UnitOfWork; +import org.apache.zest.api.unitofwork.UnitOfWorkFactory; +import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation; +import org.quartz.Calendar; +import org.quartz.JobDetail; +import org.quartz.JobKey; +import org.quartz.JobPersistenceException; +import org.quartz.ObjectAlreadyExistsException; +import org.quartz.SchedulerConfigException; +import org.quartz.SchedulerException; +import org.quartz.Trigger; +import org.quartz.TriggerKey; +import org.quartz.impl.matchers.GroupMatcher; +import org.quartz.spi.ClassLoadHelper; +import org.quartz.spi.JobStore; +import org.quartz.spi.OperableTrigger; +import org.quartz.spi.SchedulerSignaler; +import org.quartz.spi.TriggerFiredResult; + +import static org.apache.zest.api.query.QueryExpressions.and; +import static org.apache.zest.api.query.QueryExpressions.eq; +import static org.apache.zest.api.query.QueryExpressions.lt; +import static org.apache.zest.api.query.QueryExpressions.not; +import static org.apache.zest.api.query.QueryExpressions.templateFor; + +public class JobStoreMixin + implements JobStore +{ + @Structure + UnitOfWorkFactory uowf; + + @Structure + QueryBuilderFactory qbf; + private String instanceId; + private String instanceName; + private int threadPoolSize; + + @Override + @UnitOfWorkPropagation( usecase = "store quartz job" ) + public void storeJob( JobDetail newJob, boolean replaceExisting ) + throws ObjectAlreadyExistsException + { + JobKey key = newJob.getKey(); + JobsGroup group = getJobsGroup( key ); + JobWrapper job = group.jobs().get( key.getName() ); + if( job != null ) + { + if( !replaceExisting ) + { + throw new ObjectAlreadyExistsException( newJob ); + } + job.jobDetail().set( newJob ); + } + else + { + UnitOfWork uow = uowf.currentUnitOfWork(); + EntityBuilder builder = uow.newEntityBuilder( JobWrapper.class ); + builder.instance().jobDetail().set( newJob ); + job = builder.newInstance(); + group.jobs().put( key.getName(), job ); + } + } + + @Override + public void storeJobsAndTriggers( Map> triggersAndJobs, boolean replace ) + throws ObjectAlreadyExistsException, JobPersistenceException + { + // make sure there are no collisions... + if( !replace ) + { + for( Map.Entry> e : triggersAndJobs.entrySet() ) + { + if( checkExists( e.getKey().getKey() ) ) + { + throw new ObjectAlreadyExistsException( e.getKey() ); + } + for( Trigger trigger : e.getValue() ) + { + if( checkExists( trigger.getKey() ) ) + { + throw new ObjectAlreadyExistsException( trigger ); + } + } + } + } + // do bulk add... + for( Map.Entry> e : triggersAndJobs.entrySet() ) + { + storeJob( e.getKey(), true ); + for( Trigger trigger : e.getValue() ) + { + storeTrigger( (OperableTrigger) trigger, true ); + } + } + } + + @Override + @UnitOfWorkPropagation( usecase = "store quartz trigger" ) + public void storeTrigger( OperableTrigger newTrigger, boolean replaceExisting ) + throws ObjectAlreadyExistsException + { + TriggerKey key = newTrigger.getKey(); + TriggersGroup group = getTriggersGroup( key ); + TriggerWrapper trigger = group.triggers().get( key.getName() ); + if( trigger != null ) + { + if( !replaceExisting ) + { + throw new ObjectAlreadyExistsException( newTrigger ); + } + trigger.trigger().set( newTrigger ); + } + else + { + UnitOfWork uow = uowf.currentUnitOfWork(); + EntityBuilder builder = uow.newEntityBuilder( TriggerWrapper.class ); + builder.instance().trigger().set( newTrigger ); + trigger = builder.newInstance(); + group.triggers().put( key.getName(), trigger ); + } + } + + @Override + @UnitOfWorkPropagation( usecase = "store quartz calendar" ) + public void storeCalendar( String name, Calendar newCalendar, boolean replaceExisting, boolean updateTriggers ) + throws ObjectAlreadyExistsException + { + UnitOfWork uow = uowf.currentUnitOfWork(); + Calendars calendars = uow.get( Calendars.class, Calendars.class.getName() ); + try + { + CalendarWrapper calendar = calendars.calendars().get( name ); + if( !replaceExisting ) + { + throw new ObjectAlreadyExistsException( "Calendar " + name + " already exists." ); + } + calendar.calendar().set( newCalendar ); + } + catch( NoSuchEntityException e ) + { + EntityBuilder builder = uow.newEntityBuilder( CalendarWrapper.class ); + builder.instance().calendar().set( newCalendar ); + CalendarWrapper calendar = builder.newInstance(); + calendars.calendars().put( name, calendar ); + } + } + + @Override + @UnitOfWorkPropagation( usecase = "remove quartz job" ) + public boolean removeJob( JobKey jobKey ) + throws JobPersistenceException + { + UnitOfWork uow = uowf.currentUnitOfWork(); + JobsGroups groups = uow.get( JobsGroups.class, JobsGroups.class.getName() ); + JobsGroup group = groups.groups().get( jobKey.getGroup() ); + group.jobs().remove( jobKey.getName() ); + return remove( JobWrapper.class, getIdentity( jobKey ) ); + } + + @Override + public boolean removeJobs( List jobKeys ) + throws JobPersistenceException + { + return jobKeys.stream().map( this::removeJobWithSuccessIndicator ).allMatch( v -> v ); + } + + private Boolean removeJobWithSuccessIndicator( JobKey key ) + { + try + { + return removeJob( key ); + } + catch( JobPersistenceException e ) + { + return false; + } + } + + @Override + public JobDetail retrieveJob( JobKey key ) + throws JobPersistenceException + { + JobsGroup group = getJobsGroup( key ); + JobWrapper job = group.jobs().get( key.getName() ); + if( job != null ) + { + return job.jobDetail().get(); + } + return null; + } + + @Override + @UnitOfWorkPropagation( usecase = "remove quartz trigger" ) + public boolean removeTrigger( TriggerKey triggerKey ) + throws JobPersistenceException + { + UnitOfWork uow = uowf.currentUnitOfWork(); + TriggersGroups groups = uow.get( TriggersGroups.class, TriggersGroups.class.getName() ); + TriggersGroup group = groups.groups().get( triggerKey.getGroup() ); + group.triggers().remove( triggerKey.getName() ); + return remove( TriggerWrapper.class, getIdentity( triggerKey ) ); + } + + @Override + public boolean removeTriggers( List triggerKeys ) + throws JobPersistenceException + { + return triggerKeys.stream().map( this::removeTriggerWithSuccessIndicator ).allMatch( v -> v ); + } + + private boolean removeTriggerWithSuccessIndicator( TriggerKey triggerKey ) + { + try + { + return removeTrigger( triggerKey ); + } + catch( JobPersistenceException e ) + { + return false; + } + } + + @Override + public boolean replaceTrigger( TriggerKey triggerKey, OperableTrigger newTrigger ) + throws JobPersistenceException + { + TriggerWrapper existing = (TriggerWrapper) retrieveTrigger( triggerKey ); + if( existing.trigger().get().getJobKey().equals( newTrigger.getJobKey() )) + { + removeTrigger( triggerKey ); + storeTrigger( newTrigger, true ); + } + return false; + } + + private Stream allTriggers() + { + UnitOfWork uow = uowf.currentUnitOfWork(); + TriggersGroups groups = uow.get( TriggersGroups.class, TriggersGroups.class.getName() ); + return groups.groups().toMap().values().stream().flatMap( group -> group.triggers().toMap().values().stream() ); + } + + @Override + public OperableTrigger retrieveTrigger( TriggerKey key ) + throws JobPersistenceException + { + TriggersGroup group = getTriggersGroup( key ); + return group.triggers().get( key.getName() ); + } + + @Override + public boolean checkExists( JobKey key ) + throws JobPersistenceException + { + JobsGroup group = getJobsGroup( key ); + JobWrapper job = group.jobs().get( key.getName() ); + return job != null; + } + + @Override + public boolean checkExists( TriggerKey key ) + throws JobPersistenceException + { + TriggersGroup group = getTriggersGroup( key ); + return group.triggers().get( key.getName() ) != null; + } + + @Override + public void clearAllSchedulingData() + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + @UnitOfWorkPropagation( usecase = "remove quartz calendar" ) + public boolean removeCalendar( String calName ) + throws JobPersistenceException + { + UnitOfWork uow = uowf.currentUnitOfWork(); + Calendars calendars = uow.get( Calendars.class, Calendars.class.getName() ); + calendars.calendars().remove( calName ); + return remove( CalendarWrapper.class, calName ); + } + + @Override + public Calendar retrieveCalendar( String calName ) + throws JobPersistenceException + { + UnitOfWork uow = uowf.currentUnitOfWork(); + Calendars calendars = uow.get( Calendars.class, Calendars.class.getName() ); + return calendars.calendars().get( calName ).calendar().get(); + } + + @Override + @UnitOfWorkPropagation( usecase = "get number of quartz calendars" ) + public int getNumberOfCalendars() + throws JobPersistenceException + { + UnitOfWork uow = uowf.currentUnitOfWork(); + Calendars calendars = uow.get( Calendars.class, Calendars.class.getName() ); + return calendars.calendars().count(); + } + + @Override + public Set getJobKeys( GroupMatcher matcher ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public Set getTriggerKeys( GroupMatcher matcher ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + @UnitOfWorkPropagation( usecase = "get number of quartz triggers" ) + public int getNumberOfTriggers() + throws JobPersistenceException + { + UnitOfWork uow = uowf.currentUnitOfWork(); + TriggersGroups groups = uow.get( TriggersGroups.class, TriggersGroups.class.getName() ); + return (int) groups + .groups() + .toMap() + .values() + .stream() + .flatMap( + triggers -> triggers + .triggers() + .toMap() + .values() + .stream() + ).count(); + } + + @Override + @UnitOfWorkPropagation( usecase = "get number of quartz jobs" ) + public int getNumberOfJobs() + throws JobPersistenceException + { + UnitOfWork uow = uowf.currentUnitOfWork(); + JobsGroup jobs = uow.get( JobsGroup.class, JobsGroup.class.getName() ); + return jobs.jobs().count(); + } + + @Override + @UnitOfWorkPropagation( usecase = "get quartz job group names" ) + public List getJobGroupNames() + throws JobPersistenceException + { + List result = new ArrayList<>(); + UnitOfWork uow = uowf.currentUnitOfWork(); + JobsGroup jobs = uow.get( JobsGroup.class, JobsGroup.class.getName() ); + jobs.jobs().forEach( name -> result.add( getGroupName( name ) ) ); + return result; + } + + @Override + @UnitOfWorkPropagation( usecase = "get quartz trigger group names" ) + public List getTriggerGroupNames() + throws JobPersistenceException + { + List result = new ArrayList<>(); + UnitOfWork uow = uowf.currentUnitOfWork(); + TriggersGroup triggersGroup = uow.get( TriggersGroup.class, TriggersGroup.class.getName() ); + triggersGroup.triggers().forEach( name -> result.add( getGroupName( name ) ) ); + return result; + } + + @Override + @UnitOfWorkPropagation( usecase = "get quartz calendar names" ) + public List getCalendarNames() + throws JobPersistenceException + { + List result = new ArrayList<>(); + UnitOfWork uow = uowf.currentUnitOfWork(); + Calendars calendars = uow.get( Calendars.class, Calendars.class.getName() ); + calendars.calendars().forEach( result::add ); + return result; + } + + @Override + @UnitOfWorkPropagation( usecase = "get quartz triggers for job" ) + public List getTriggersForJob( JobKey jobKey ) + throws JobPersistenceException + { + List result = new ArrayList<>(); + UnitOfWork uow = uowf.currentUnitOfWork(); + TriggersGroup triggersGroup = uow.get( TriggersGroup.class, TriggersGroup.class.getName() ); + triggersGroup.triggers().toMap().values().stream() + .map( triggerWrapper -> (OperableTrigger) triggerWrapper.trigger().get() ) + .filter( trigger -> trigger.getJobKey().equals( jobKey ) ) + .forEach( result::add ); + return result; + } + + @Override + public Trigger.TriggerState getTriggerState( TriggerKey triggerKey ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public void pauseTrigger( TriggerKey triggerKey ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public Collection pauseTriggers( GroupMatcher matcher ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public void pauseJob( JobKey jobKey ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public Collection pauseJobs( GroupMatcher groupMatcher ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public void resumeTrigger( TriggerKey triggerKey ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public Collection resumeTriggers( GroupMatcher matcher ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public Set getPausedTriggerGroups() + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public void resumeJob( JobKey jobKey ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public Collection resumeJobs( GroupMatcher matcher ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public void pauseAll() + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public void resumeAll() + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public List acquireNextTriggers( long noLaterThan, int maxCount, long timeWindow ) + throws JobPersistenceException + { + List result = new ArrayList<>(); + Query query = createNextTriggersQuery( noLaterThan, timeWindow ); + query.maxResults( maxCount ); + for( TriggerWrapper wrapper : query ) + { + wrapper.state().set( TriggerWrapper.State.aquired ); + result.add( wrapper ); + } + return result; + } + + private Query createNextTriggersQuery( long noLaterThan, long timeWindow ) + { + QueryBuilder qb = qbf.newQueryBuilder( TriggerWrapper.class ); + TriggerWrapper template = templateFor( TriggerWrapper.class ); + qb = qb.where( + and( + lt( template.nextTime(), noLaterThan + timeWindow ), + not( eq( template.state(), TriggerWrapper.State.aquired ) ) + ) + ); + return uowf.currentUnitOfWork().newQuery( qb ); + } + + @Override + public void releaseAcquiredTrigger( OperableTrigger trigger ) + { + ( (TriggerWrapper) trigger ).state().set( TriggerWrapper.State.waiting ); + } + + @Override + public List triggersFired( List triggers ) + throws JobPersistenceException + { + throw new UnsupportedOperationException( "This operation is not yet supported." ); + } + + @Override + public void triggeredJobComplete( OperableTrigger trigger, + JobDetail jobDetail, + Trigger.CompletedExecutionInstruction triggerInstCode + ) + { + System.out.println("Job completed: " + jobDetail); + } + + @Override + public void setInstanceId( String schedInstId ) + { + instanceId = schedInstId; + } + + @Override + public void setInstanceName( String schedName ) + { + instanceName = schedName; + } + + @Override + public void setThreadPoolSize( int poolSize ) + { + threadPoolSize = poolSize; + } + + @Override + public void initialize( ClassLoadHelper loadHelper, SchedulerSignaler signaler ) + throws SchedulerConfigException + { + + } + + @Override + public void schedulerStarted() + throws SchedulerException + { + + } + + @Override + public void schedulerPaused() + { + + } + + @Override + public void schedulerResumed() + { + + } + + @Override + public void shutdown() + { + + } + + @Override + public boolean supportsPersistence() + { + return true; + } + + @Override + public long getEstimatedTimeToReleaseAndAcquireTrigger() + { + return 0; + } + + @Override + public boolean isClustered() + { + return false; + } + + @Override + public void storeJobAndTrigger( JobDetail newJob, OperableTrigger newTrigger ) + throws ObjectAlreadyExistsException, JobPersistenceException + { + storeJob( newJob, false ); + storeTrigger( newTrigger, false ); + } + + private String getIdentity( JobKey key ) + { + return key.getGroup() + ":" + key.getName(); + } + + private String getIdentity( TriggerKey key ) + { + return key.getGroup() + ":" + key.getName(); + } + + private String getGroupName( String name ) + { + return name.split( ":" )[ 0 ]; + } + + private JobsGroup getJobsGroup( JobKey key ) + { + UnitOfWork uow = uowf.currentUnitOfWork(); + JobsGroups groups = uow.get( JobsGroups.class, JobsGroups.class.getName() ); + JobsGroup jobsGroup = groups.groups().get( jobsGroupIdentity( key ) ); + if( jobsGroup == null ) + { + jobsGroup = uow.newEntity( JobsGroup.class, jobsGroupIdentity( key ) ); + } + return jobsGroup; + } + + private String jobsGroupIdentity( JobKey key ) + { + return "jobsGroup://" + key.getGroup() + "." + key.getName(); + } + + private TriggersGroup getTriggersGroup( TriggerKey key ) + { + UnitOfWork uow = uowf.currentUnitOfWork(); + TriggersGroups groups = uow.get( TriggersGroups.class, TriggersGroups.class.getName() ); + TriggersGroup triggersGroup = groups.groups().get( triggersGroupIdentity( key ) ); + if( triggersGroup == null ) + { + triggersGroup = uow.newEntity( TriggersGroup.class, triggersGroupIdentity( key ) ); + } + return triggersGroup; + } + + private String triggersGroupIdentity( TriggerKey key ) + { + return "triggersGroup://" + key.getGroup() + "." + key.getName(); + } + + private boolean remove( Class type, String identity ) + { + UnitOfWork uow = uowf.currentUnitOfWork(); + try + { + T wrapper = uow.get( type, identity ); + uow.remove( wrapper ); + return true; + } + catch( EntityTypeNotFoundException | NoSuchEntityException | LifecycleException e ) + { + return false; + } + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobWrapper.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobWrapper.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobWrapper.java new file mode 100644 index 0000000..7d766e5 --- /dev/null +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobWrapper.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.zest.library.scheduler; + +import org.apache.zest.api.entity.EntityComposite; +import org.apache.zest.api.property.Property; +import org.quartz.JobDetail; + +public interface JobWrapper extends EntityComposite +{ + Property jobDetail(); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroup.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroup.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroup.java new file mode 100644 index 0000000..b2fdb24 --- /dev/null +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroup.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.zest.library.scheduler; + +import org.apache.zest.api.association.NamedAssociation; + +public interface JobsGroup +{ + NamedAssociation jobs(); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroups.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroups.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroups.java new file mode 100644 index 0000000..8fad7a8 --- /dev/null +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroups.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.zest.library.scheduler; + +import org.apache.zest.api.association.NamedAssociation; +import org.apache.zest.api.common.UseDefaults; +import org.apache.zest.api.entity.EntityComposite; + +public interface JobsGroups extends EntityComposite +{ + @UseDefaults + NamedAssociation groups(); +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/OnceSchedule.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/OnceSchedule.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/OnceSchedule.java deleted file mode 100644 index 299c2be..0000000 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/OnceSchedule.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.zest.library.scheduler; - -import org.apache.zest.api.mixin.Mixins; - -@Mixins( OnceSchedule.OnceScheduleMixin.class ) -public interface OnceSchedule - extends Schedule -{ - abstract class OnceScheduleMixin - implements OnceSchedule - { - @Override - public void taskStarting() - { - } - - @Override - public void taskCompletedSuccessfully() - { - } - - @Override - public void taskCompletedWithException( Throwable ex ) - { - } - - @Override - public long nextRun( long from ) - { - if( done().get() ) - { - return Long.MIN_VALUE; - } - done().set( true ); - long runAt = start().get().getMillis(); - if( runAt >= from ) - { - return runAt; - } - return from; - } - - @Override - public String presentationString() - { - return start().get().toString(); - } - } -} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Schedule.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Schedule.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Schedule.java deleted file mode 100644 index a0f8a6e..0000000 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Schedule.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.zest.library.scheduler; - -import org.apache.zest.api.association.Association; -import org.apache.zest.api.common.UseDefaults; -import org.apache.zest.api.entity.EntityComposite; -import org.apache.zest.api.property.Immutable; -import org.apache.zest.api.property.Property; -import org.apache.zest.library.scheduler.Task; -import org.joda.time.DateTime; - -/** - * Represent the scheduling of a {@link Task}. - */ -public interface Schedule extends EntityComposite -{ - /** - * @return The Association to the Task to be executed when it is time. - */ - Association task(); - - /** The first run of this Schedule. - * - * @return The property containing the first time this Schedule will be run. - */ - @Immutable - Property start(); - - /** Returns true if the Schedule has been cancelled. - * - * @return true if the Schedule has been cancelled. - */ - @UseDefaults - Property cancelled(); - - /** Returns true if the Schedule is currently running. - * - * @return true if the Schedule is currently running. - */ - @UseDefaults - Property running(); - - /** Returns the number of times the {@link Task} has been executed. - *

- * Each time the {@link Task#run} method completes, with or without an {@link Exception}, this - * counter is incremented by 1. - *

- * - * @return true the number of Exception that has occurred when running the {@link Task}. - */ - @UseDefaults - Property executionCounter(); - - /** Returns the number of Exception that has occurred when running the {@link Task}. - *

- * Each time the {@link Task#run} method throws a {@link RuntimeException}, this property - * is incremenented by 1, - *

- * - * @return true the number of Exception that has occurred when running the {@link Task}. - */ - @UseDefaults - Property exceptionCounter(); - - /** Returns true if the Schedule is done and will not be executed any more times. - * - * @return true if the Schedule is done and will not be executed any more times. - */ - @UseDefaults - Property done(); - - /** Returns the number of times the Schedule has been skipped, due to the Task was still running. - * - * @return the number of times the Schedule has been skipped, due to the Task was still running. - */ - @UseDefaults - Property overrun(); - - /** - * Called just before the {@link org.apache.zest.library.scheduler.Task#run()} method is called. - */ - void taskStarting(); - - /** - * Called directly after the {@link org.apache.zest.library.scheduler.Task#run()} method has been completed and - * returned from the method normally. - */ - void taskCompletedSuccessfully(); - - /** - * Called directly after the {@link org.apache.zest.library.scheduler.Task#run()} method has been completed but - * threw a RuntimeException. - * @param ex The execption that was thrown in the Task. If the thrown Exception was an - * {@link java.lang.reflect.UndeclaredThrowableException} then the underlying exception is passed here. - */ - void taskCompletedWithException( Throwable ex ); - - /** - * Compute the next time this schedule is to be run. - * - * @param from The starting time when to look for the next time it will run. - * - * @return The exact absolute time when this Schedule is to be run next time, or -1 if never - */ - long nextRun( long from ); - - /** - * Return a representation of the Schedule in a human understandable format. - * - * @return A String representing this schedule. - */ - String presentationString(); -} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ScheduleFactory.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ScheduleFactory.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ScheduleFactory.java deleted file mode 100644 index e891814..0000000 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ScheduleFactory.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.zest.library.scheduler; - -import org.apache.zest.api.concern.Concerns; -import org.apache.zest.api.unitofwork.concern.UnitOfWorkConcern; -import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation; -import org.apache.zest.library.scheduler.Schedule; -import org.apache.zest.library.scheduler.defaults.DefaultScheduleFactoryMixin; -import org.joda.time.DateTime; -import org.apache.zest.api.mixin.Mixins; -import org.apache.zest.library.scheduler.Task; - -import static org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY; - -@Mixins( DefaultScheduleFactoryMixin.class ) -@Concerns( UnitOfWorkConcern.class ) -public interface ScheduleFactory -{ - @UnitOfWorkPropagation( MANDATORY) - Schedule newCronSchedule( Task task, String cronExpression, DateTime start ); - - @UnitOfWorkPropagation( MANDATORY) - Schedule newOnceSchedule( Task task, DateTime runAt ); -} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Scheduler.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Scheduler.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Scheduler.java deleted file mode 100644 index 8510645..0000000 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Scheduler.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2010-2012, Paul Merlin. - * Copyright (c) 2012, Niclas Hedhman. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.zest.library.scheduler; - -import org.apache.zest.library.scheduler.internal.Schedules; -import org.joda.time.DateTime; -import org.apache.zest.api.concern.Concerns; -import org.apache.zest.api.structure.Application; -import org.apache.zest.api.unitofwork.concern.UnitOfWorkConcern; -import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation; -import org.apache.zest.library.scheduler.bootstrap.SchedulerAssembler; -import org.apache.zest.library.scheduler.timeline.Timeline; - -import static org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.MANDATORY; - -/** - * Scheduler. - *

- * This is the only interface you should use in your application for scheduling tasks. - *

- *

- * See {@link SchedulerConfiguration} for configuration properties. - *

- *

- * See in {@link SchedulerAssembler} how to assemble a {@link Scheduler} and optional {@link Timeline}. - *

- *

- * By default, a {@link Schedule} is not durable. In other words, it do not survive an {@link Application} restart. - *

- *

- * All {@link Schedule}s are durable and stored in the visible {@link org.apache.zest.spi.entitystore.EntityStore} like - * any ordinary {@link org.apache.zest.api.entity.EntityComposite}. There is also a {@link Schedules} - * entity composite that has Associations to all active, completed and cancelled schedules. - *

- *

- * - *

- */ -@Concerns( UnitOfWorkConcern.class ) -public interface Scheduler -{ - /** - * Schedule a Task to be run after a given initial delay in seconds. - * - * @param task Task to be scheduled once - * @param initialSecondsDelay Initial delay the Task will be run after, in seconds - * - * @return The newly created Schedule - */ - @UnitOfWorkPropagation( MANDATORY ) - Schedule scheduleOnce( Task task, int initialSecondsDelay ); - - /** - * Schedule a Task to be run after a given initial delay in seconds. - * - * @param task Task to be scheduled once - * @param runAt The future point in time when the Schedule will be run. - * - * @return The newly created Schedule - */ - @UnitOfWorkPropagation( MANDATORY ) - Schedule scheduleOnce( Task task, DateTime runAt ); - - /** - * Schedule a Task using a CronExpression. - * - * @param task Task to be scheduled once - * @param cronExpression CronExpression for creating the Schedule for the given Task - * - * @return The newly created Schedule - */ - @UnitOfWorkPropagation( MANDATORY ) - Schedule scheduleCron( Task task, @CronSchedule.CronExpression String cronExpression ); - - /** - * Schedule a Task using a CronExpression with a given initial delay in milliseconds. - * - * @param task Task to be scheduled once - * @param cronExpression CronExpression for creating the Schedule for the given Task - * @param initialDelay Initial delay the Schedule will be active after, in milliseconds - * - * @return The newly created Schedule - */ - @UnitOfWorkPropagation( MANDATORY ) - Schedule scheduleCron( Task task, @CronSchedule.CronExpression String cronExpression, long initialDelay ); - - /** - * Schedule a Task using a CronExpression starting at a given date. - * - * @param task Task to be scheduled once - * @param cronExpression CronExpression for creating the Schedule for the given Task - * @param start Date from which the Schedule will become active - * - * @return The newly created Schedule - */ - @UnitOfWorkPropagation( MANDATORY ) - Schedule scheduleCron( Task task, @CronSchedule.CronExpression String cronExpression, DateTime start ); - - /** Schedules a custom Schedule. - * - * - * @param schedule The Schedule instance to be scheduled. - */ - @UnitOfWorkPropagation( MANDATORY ) - void scheduleCron( Schedule schedule ); - - /** Cancels a Schedule. - * Reads the Schedule from the EntityStore and calls {@link #cancelSchedule(Schedule)}. - * - * @param scheduleId The identity of the Schedule to be cancelled. - */ - @UnitOfWorkPropagation( MANDATORY ) - void cancelSchedule( String scheduleId ); - - /** Cancels the provided Schedule. - * - * Cancellation can be done before, while and after execution of the Schedule. If the execution - * is in progress, it will not be interrupted. - * - * @param schedule The schedule to be cancelled. - */ - @UnitOfWorkPropagation( MANDATORY ) - public void cancelSchedule( Schedule schedule ); -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerAssembler.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerAssembler.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerAssembler.java new file mode 100644 index 0000000..48aa871 --- /dev/null +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerAssembler.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.zest.library.scheduler; + +import org.apache.zest.api.unitofwork.concern.UnitOfWorkConcern; +import org.apache.zest.bootstrap.Assembler; +import org.apache.zest.bootstrap.AssemblyException; +import org.apache.zest.bootstrap.ModuleAssembly; +import org.quartz.simpl.RAMJobStore; +import org.quartz.spi.JobStore; +import org.quartz.spi.OperableTrigger; + +public class SchedulerAssembler + implements Assembler +{ + + @Override + public void assemble( ModuleAssembly module ) + throws AssemblyException + { + module.services( JobStore.class ).withMixins( JobStoreMixin.class ).withConcerns( UnitOfWorkConcern.class ); + module.services( SchedulerService.class ).instantiateOnStartup(); + module.entities( JobWrapper.class ); + module.entities( SchedulerConfiguration.class ); + defineDefaults( module ); + module.entities( TriggerWrapper.class ); + module.entities( CalendarWrapper.class ); + module.entities( Calendars.class ); + module.entities( TriggersGroup.class ); + module.entities( TriggersGroups.class ); + module.entities( JobsGroup.class ); + module.entities( JobsGroups.class ); + module.values( ZestJobDetail.class ); + module.objects( ZestJobFactory.class ); + } + + private void defineDefaults( ModuleAssembly module ) + { + SchedulerConfiguration defaults = module.forMixin( SchedulerConfiguration.class ).declareDefaults(); + + defaults.idleWaitTime().set( 1000L ); + defaults.interrupOnShutdown().set( true ); + defaults.interrupOnShutdownWithWait().set( true ); + defaults.batchTimeWindow().set( 15000L ); + defaults.threadCount().set( 2 ); + defaults.threadPriority().set( Thread.NORM_PRIORITY ); + } +} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerConfiguration.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerConfiguration.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerConfiguration.java index 66d7769..2569c1d 100644 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerConfiguration.java +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerConfiguration.java @@ -1,46 +1,48 @@ /* - * Copyright (c) 2010-2012, Paul Merlin. - * Copyright (c) 2012, Niclas Hedhman. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. * - * See the License for the specific language governing permissions and - * limitations under the License. */ + package org.apache.zest.library.scheduler; -import org.apache.zest.api.common.Optional; import org.apache.zest.api.common.UseDefaults; import org.apache.zest.api.property.Property; -/** - * Configuration for the {@link Scheduler}. - * - * Every property has a default value, you can use a {@link Scheduler} without providing any. - */ public interface SchedulerConfiguration { -// START SNIPPET: configuration - /** - * @return Number of worker threads, optional and defaults to the number of available cores. - */ - @Optional @UseDefaults - Property workersCount(); - - /** - * @return Size of the queue to use for holding tasks before they are run, optional and defaults to 10. - */ - @Optional @UseDefaults - Property workQueueSize(); - -// END SNIPPET: configuration + @UseDefaults + Property batchTimeWindow(); + + @UseDefaults + Property interrupOnShutdown(); + + @UseDefaults + Property interrupOnShutdownWithWait(); + + @UseDefaults + Property maxBatchSize(); + + @UseDefaults + Property idleWaitTime(); + + @UseDefaults + Property threadCount(); + + @UseDefaults + Property threadPriority(); } http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerService.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerService.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerService.java index ade3d1e..54ea1bf 100644 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerService.java +++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulerService.java @@ -1,32 +1,182 @@ /* - * Copyright (c) 2010-2014, Paul Merlin. - * Copyright (c) 2012, Niclas Hedhman. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. * - * See the License for the specific language governing permissions and - * limitations under the License. */ + package org.apache.zest.library.scheduler; -import org.apache.zest.api.entity.Identity; +import java.util.Collection; +import org.apache.zest.api.ZestAPI; +import org.apache.zest.api.configuration.Configuration; +import org.apache.zest.api.entity.EntityBuilder; +import org.apache.zest.api.entity.EntityComposite; +import org.apache.zest.api.injection.scope.Service; +import org.apache.zest.api.injection.scope.Structure; +import org.apache.zest.api.injection.scope.This; import org.apache.zest.api.mixin.Mixins; +import org.apache.zest.api.object.ObjectFactory; import org.apache.zest.api.service.ServiceActivation; -import org.apache.zest.library.scheduler.defaults.DefaultRejectionHandler; -import org.apache.zest.library.scheduler.defaults.DefaultThreadFactory; -import org.apache.zest.library.scheduler.internal.SchedulerMixin; +import org.apache.zest.api.service.ServiceComposite; +import org.apache.zest.api.unitofwork.NoSuchEntityException; +import org.apache.zest.api.unitofwork.UnitOfWork; +import org.apache.zest.api.unitofwork.UnitOfWorkFactory; +import org.apache.zest.api.usecase.UsecaseBuilder; +import org.apache.zest.api.value.ValueBuilder; +import org.apache.zest.api.value.ValueBuilderFactory; +import org.apache.zest.spi.ZestSPI; +import org.apache.zest.spi.uuid.UuidIdentityGeneratorService; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.SchedulerFactory; +import org.quartz.impl.DirectSchedulerFactory; +import org.quartz.impl.SchedulerRepository; +import org.quartz.simpl.SimpleThreadPool; +import org.quartz.spi.JobFactory; +import org.quartz.spi.JobStore; -@Mixins( { SchedulerMixin.class, DefaultThreadFactory.class, DefaultRejectionHandler.class } ) -public interface SchedulerService - extends Scheduler, ServiceActivation, Identity +@Mixins( { SchedulerService.SchedulerActivationMixin.class } ) +public interface SchedulerService extends SchedulerFactory, ServiceActivation, ServiceComposite { + ZestJobDetail createJobDetails(ZestJob jobEntity); + + abstract class SchedulerActivationMixin + implements SchedulerService + { + + @This + private Configuration conf; + + @Service + UuidIdentityGeneratorService uuid; + + @Service + JobStore jobStore; + + @Structure + ZestAPI api; + + @Structure + ObjectFactory objectFactory; + + @Structure + UnitOfWorkFactory uowf; + + @Structure + ValueBuilderFactory vbf; + + @Override + public void activateService() + throws Exception + { + initializeRoots(); + SchedulerConfiguration config = conf.get(); + DirectSchedulerFactory factory = DirectSchedulerFactory.getInstance(); + SimpleThreadPool threadPool = new SimpleThreadPool(); + threadPool.setThreadCount( config.threadCount().get() ); + threadPool.setThreadPriority( config.threadPriority().get() ); + threadPool.setInstanceName( identity().get() ); + threadPool.setThreadNamePrefix( identity().get() ); + factory.createScheduler( identity().get(), uuid.generate( Scheduler.class ), threadPool, jobStore ); + + JobFactory jobFactory = objectFactory.newObject( ZestJobFactory.class ); + getScheduler().setJobFactory( jobFactory ); + getScheduler().start(); + } + + @Override + public void passivateService() + throws Exception + { + getScheduler().shutdown(); + SchedulerRepository schedRep = SchedulerRepository.getInstance(); + schedRep.remove( identity().get() ); + } + + @Override + public Scheduler getScheduler() + throws SchedulerException + { + SchedulerRepository schedRep = SchedulerRepository.getInstance(); + String schedulerIdentity = identity().get(); + return schedRep.lookup( schedulerIdentity ); + } + + @Override + public Scheduler getScheduler( String schedName ) + throws SchedulerException + { + throw new UnsupportedOperationException( "Quartz in Apache Zest doesn't facilitate the Quartz Repository concept, as the Zest service mechanism can replace it that.\nRegister an additional SchedulerService in your bootstrap and look it up using normal Zest @Service injection or via ServiceFinder." ); + } + + @Override + public Collection getAllSchedulers() + throws SchedulerException + { + throw new UnsupportedOperationException( "Quartz in Apache Zest doesn't facilitate the Quartz Repository concept, as the Zest service mechanism can replace it that.\nAll SchedulerServices can be looked up with @Service List>" ); + } + + @Override + public ZestJobDetail createJobDetails( ZestJob jobEntity ) + { + ValueBuilder builder = vbf.newValueBuilder( ZestJobDetail.class ); + ZestJobDetail.State proto = builder.prototypeFor(ZestJobDetail.State.class); + proto.description().set( jobEntity.description().get() ); + proto.jobClass().set( api.entityDescriptorFor( jobEntity ).primaryType().getName() ); + proto.jobIdentity().set( jobEntity.identity().get() ); + return builder.newInstance(); + } + + private void initializeRoots() + { + try( UnitOfWork uow = uowf.newUnitOfWork( UsecaseBuilder.newUsecase( "initialize quartz root entities" ) ) ) + { + createJobsGroups(); + createTriggersGroups(); + createCalendars(); + uow.complete(); + } + } + + private void createJobsGroups() + { + createContainer( JobsGroups.class ); + } + + private void createTriggersGroups() + { + createContainer( TriggersGroups.class ); + } + + private void createCalendars() + { + createContainer( Calendars.class ); + } + + private void createContainer( Class type ) + { + UnitOfWork uow = uowf.currentUnitOfWork(); + try + { + uow.get( type, type.getName() ); + } catch( NoSuchEntityException e) + { + uow.newEntity( type, type.getName() ); + } + } + } } http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulesHandler.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulesHandler.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulesHandler.java deleted file mode 100644 index b4a2b4d..0000000 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/SchedulesHandler.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -package org.apache.zest.library.scheduler; - -import org.apache.zest.api.entity.Identity; -import org.apache.zest.api.injection.scope.Structure; -import org.apache.zest.api.injection.scope.This; -import org.apache.zest.api.mixin.Mixins; -import org.apache.zest.api.structure.Module; -import org.apache.zest.api.unitofwork.NoSuchEntityException; -import org.apache.zest.api.unitofwork.UnitOfWork; -import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation; -import org.apache.zest.library.scheduler.internal.Schedules; - -@Mixins(SchedulesHandler.SchedulesHandlerMixin.class) -public interface SchedulesHandler -{ - @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY) - Schedules getActiveSchedules(); - - @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY) - Schedules getCancelledSchedules(); - - class SchedulesHandlerMixin implements SchedulesHandler - { - @This - private Identity me; - - @Structure - private Module module; - - @Override - public Schedules getActiveSchedules() - { - return getOrCreateSchedules(getActiveSchedulesIdentity()); - } - - @Override - public Schedules getCancelledSchedules() - { - return getOrCreateSchedules(getCancelledSchedulesIdentity()); - } - - public String getActiveSchedulesIdentity() - { - return "Schedules-Active:" + me.identity().get(); - } - - public String getCancelledSchedulesIdentity() - { - return "Schedules-Cancelled:" + me.identity().get(); - } - - private Schedules getOrCreateSchedules( String identity ){ - UnitOfWork uow = module.currentUnitOfWork(); - Schedules schedules; - try - { - schedules = uow.get( Schedules.class, identity ); - } - catch( NoSuchEntityException e ) - { - // Create a new Schedules entity for keeping track of them all. - schedules = uow.newEntity( Schedules.class, identity ); - } - return schedules; - - } - - } -} http://git-wip-us.apache.org/repos/asf/zest-java/blob/551c04d5/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Task.java ---------------------------------------------------------------------- diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Task.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Task.java deleted file mode 100644 index 9cce9ce..0000000 --- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Task.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2010-2012, Paul Merlin. - * Copyright (c) 2012, Niclas Hedhman. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - * implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.zest.library.scheduler; - -import java.util.List; -import org.apache.zest.api.common.UseDefaults; -import org.apache.zest.api.concern.Concerns; -import org.apache.zest.api.property.Property; -import org.apache.zest.api.unitofwork.UnitOfWork; -import org.apache.zest.api.unitofwork.concern.UnitOfWorkConcern; -import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation; - -/** - * Compose an Entity using this type to be able to Schedule it. - *

- * A Task is associated from a {@link Schedule}, and upon time to execute - * the SchedulerService will dispatch a TaskRunner in a new thread, and establish a UnitOfWork (Usecase name of "Task Runner"). - *

- *

- * The {@code Task} type declares the {@link UnitOfWorkConcern} and therefor the {@code Task} implementation may - * declare the {@link UnitOfWorkPropagation} annotation with the - * {@link org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation.Propagation#REQUIRES_NEW} and a different - * {@link UnitOfWork} strategy, such as {@code Retries} and {@code DiscardOn}. - * - *

- * - * Here is a simple example: - *

- *  interface MyTask
- *      extends Task
- *  {
- *      Property<String customState();
- *      Association<AnotherEntity> anotherEntity();
- *  }
- *
- *  class MyTaskMixin
- *      implements Runnable
- *  {
- *      @This MyTaskEntity me;
- *
- *      public void run()
- *      {
- *          me.customState().set( me.anotherEntity().get().doSomeStuff( me.customState().get() ) );
- *      }
- *  }
- * 
- * - * Finaly, {@literal MyTask} must be assembled into an {@literal EntityComposite}. - */ -// START SNIPPET: task -@Concerns( UnitOfWorkConcern.class ) -public interface Task - extends Runnable -{ - Property name(); - - @UseDefaults - Property> tags(); - -} -// END SNIPPET: task