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.
diff --git a/libraries.gradle b/libraries.gradle
index 13c7525..87cac54 100644
--- a/libraries.gradle
+++ b/libraries.gradle
@@ -54,13 +54,13 @@
 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 @@
           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",
-          mongodb: "org.mongodb:mongo-java-driver:$mongodbVersion",
-          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",
+          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",
+          servlet_api: "javax.servlet:javax.servlet-api:$servletVersion",
+          shiro: "org.apache.shiro:shiro-core:$shiroVersion",
+          shiro_web: "org.apache.shiro:shiro-web:$shiroVersion",
           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",
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 @@
 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" )
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CalendarWrapper.java
similarity index 75%
copy from libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
copy to libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CalendarWrapper.java
index 95563c1..4d6a394 100644
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/CalendarWrapper.java
@@ -17,12 +17,14 @@
  * under the License.
  *
  */
-package org.apache.zest.library.scheduler.internal;
 
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.library.scheduler.Schedule;
+package org.apache.zest.library.scheduler;
 
-public interface Schedules
+import org.apache.zest.api.entity.EntityComposite;
+import org.apache.zest.api.property.Property;
+import org.quartz.Calendar;
+
+public interface CalendarWrapper extends EntityComposite
 {
-    ManyAssociation<Schedule> schedules();
+    Property<Calendar> calendar();
 }
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Calendars.java
similarity index 75%
copy from libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
copy to libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Calendars.java
index 95563c1..9e38d8a 100644
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/Calendars.java
@@ -17,12 +17,13 @@
  * under the License.
  *
  */
-package org.apache.zest.library.scheduler.internal;
 
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.library.scheduler.Schedule;
+package org.apache.zest.library.scheduler;
 
-public interface Schedules
+import org.apache.zest.api.association.NamedAssociation;
+import org.apache.zest.api.entity.EntityComposite;
+
+public interface Calendars extends EntityComposite
 {
-    ManyAssociation<Schedule> schedules();
+    NamedAssociation<CalendarWrapper> calendars();
 }
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<String> 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<CronExpression, String>
-    {
-        private static final long serialVersionUID = 1L;
-
-        @Override
-        public boolean isValid( CronExpression annotation, String cronExpression )
-        {
-            return org.codeartisans.sked.cron.CronSchedule.isExpressionValid( cronExpression );
-        }
-    }
-}
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<JobWrapper> builder = uow.newEntityBuilder( JobWrapper.class );
+            builder.instance().jobDetail().set( newJob );
+            job = builder.newInstance();
+            group.jobs().put( key.getName(), job );
+        }
+    }
+
+    @Override
+    public void storeJobsAndTriggers( Map<JobDetail, Set<? extends Trigger>> triggersAndJobs, boolean replace )
+        throws ObjectAlreadyExistsException, JobPersistenceException
+    {
+        // make sure there are no collisions...
+        if( !replace )
+        {
+            for( Map.Entry<JobDetail, Set<? extends Trigger>> 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<JobDetail, Set<? extends Trigger>> 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<TriggerWrapper> 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<CalendarWrapper> 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<JobKey> 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<TriggerKey> 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<TriggerWrapper> 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<JobKey> getJobKeys( GroupMatcher<JobKey> matcher )
+        throws JobPersistenceException
+    {
+        throw new UnsupportedOperationException( "This operation is not yet supported." );
+    }
+
+    @Override
+    public Set<TriggerKey> getTriggerKeys( GroupMatcher<TriggerKey> 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<String> getJobGroupNames()
+        throws JobPersistenceException
+    {
+        List<String> 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<String> getTriggerGroupNames()
+        throws JobPersistenceException
+    {
+        List<String> 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<String> getCalendarNames()
+        throws JobPersistenceException
+    {
+        List<String> 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<OperableTrigger> getTriggersForJob( JobKey jobKey )
+        throws JobPersistenceException
+    {
+        List<OperableTrigger> 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<String> pauseTriggers( GroupMatcher<TriggerKey> 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<String> pauseJobs( GroupMatcher<JobKey> 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<String> resumeTriggers( GroupMatcher<TriggerKey> matcher )
+        throws JobPersistenceException
+    {
+        throw new UnsupportedOperationException( "This operation is not yet supported." );
+    }
+
+    @Override
+    public Set<String> 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<String> resumeJobs( GroupMatcher<JobKey> 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<OperableTrigger> acquireNextTriggers( long noLaterThan, int maxCount, long timeWindow )
+        throws JobPersistenceException
+    {
+        List<OperableTrigger> result = new ArrayList<>();
+        Query<TriggerWrapper> query = createNextTriggersQuery( noLaterThan, timeWindow );
+        query.maxResults( maxCount );
+        for( TriggerWrapper wrapper : query )
+        {
+            wrapper.state().set( TriggerWrapper.State.aquired );
+            result.add( wrapper );
+        }
+        return result;
+    }
+
+    private Query<TriggerWrapper> createNextTriggersQuery( long noLaterThan, long timeWindow )
+    {
+        QueryBuilder<TriggerWrapper> 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<TriggerFiredResult> triggersFired( List<OperableTrigger> 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 <T> boolean remove( Class<T> 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;
+        }
+    }
+}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobWrapper.java
similarity index 75%
copy from libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
copy to libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobWrapper.java
index 95563c1..7d766e5 100644
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobWrapper.java
@@ -17,12 +17,14 @@
  * under the License.
  *
  */
-package org.apache.zest.library.scheduler.internal;
 
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.library.scheduler.Schedule;
+package org.apache.zest.library.scheduler;
 
-public interface Schedules
+import org.apache.zest.api.entity.EntityComposite;
+import org.apache.zest.api.property.Property;
+import org.quartz.JobDetail;
+
+public interface JobWrapper extends EntityComposite
 {
-    ManyAssociation<Schedule> schedules();
+    Property<JobDetail> jobDetail();
 }
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroup.java
similarity index 77%
rename from libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
rename to libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroup.java
index 95563c1..b2fdb24 100644
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroup.java
@@ -17,12 +17,12 @@
  * under the License.
  *
  */
-package org.apache.zest.library.scheduler.internal;
 
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.library.scheduler.Schedule;
+package org.apache.zest.library.scheduler;
 
-public interface Schedules
+import org.apache.zest.api.association.NamedAssociation;
+
+public interface JobsGroup
 {
-    ManyAssociation<Schedule> schedules();
+    NamedAssociation<JobWrapper> jobs();
 }
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroups.java
similarity index 72%
copy from libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
copy to libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroups.java
index 95563c1..8fad7a8 100644
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/JobsGroups.java
@@ -17,12 +17,15 @@
  * under the License.
  *
  */
-package org.apache.zest.library.scheduler.internal;
 
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.library.scheduler.Schedule;
+package org.apache.zest.library.scheduler;
 
-public interface Schedules
+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
 {
-    ManyAssociation<Schedule> schedules();
+    @UseDefaults
+    NamedAssociation<JobsGroup> groups();
 }
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();
-        }
-    }
-}
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> task();
-
-    /** The first run of this Schedule.
-     *
-     * @return The property containing the first time this Schedule will be run.
-     */
-    @Immutable
-    Property<DateTime> start();
-
-    /** Returns true if the Schedule has been cancelled.
-     *
-     * @return true if the Schedule has been cancelled.
-     */
-    @UseDefaults
-    Property<Boolean> cancelled();
-
-    /** Returns true if the Schedule is currently running.
-     *
-     * @return true if the Schedule is currently running.
-     */
-    @UseDefaults
-    Property<Boolean> running();
-
-    /** Returns the number of times the {@link Task} has been executed.
-     * <p>
-     * Each time the {@link Task#run} method completes, with or without an {@link Exception}, this
-     * counter is incremented by 1.
-     * </p>
-     *
-     * @return true the number of Exception that has occurred when running the {@link Task}.
-     */
-    @UseDefaults
-    Property<Long> executionCounter();
-
-    /** Returns the number of Exception that has occurred when running the {@link Task}.
-     * <p>
-     * Each time the {@link Task#run} method throws a {@link RuntimeException}, this property
-     * is incremenented by 1,
-     * </p>
-     *
-     * @return true the number of Exception that has occurred when running the {@link Task}.
-     */
-    @UseDefaults
-    Property<Long> 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<Boolean> 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<Long> 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();
-}
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 );
-}
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.
- * <p>
- * This is the only interface you should use in your application for scheduling tasks.
- * </p>
- * <p>
- * See {@link SchedulerConfiguration} for configuration properties.
- * </p>
- * <p>
- * See in {@link SchedulerAssembler} how to assemble a {@link Scheduler} and optional {@link Timeline}.
- * </p>
- * <p>
- * By default, a {@link Schedule} is not durable. In other words, it do not survive an {@link Application} restart.
- * </p>
- * <p>
- * 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.
- * </p>
- * <p>
- *
- * </p>
- */
-@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
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 );
+    }
+}
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<Integer> workersCount();
+    @UseDefaults
+    Property<Long> batchTimeWindow();
 
-    /**
-     * @return Size of the queue to use for holding tasks before they are run, optional and defaults to 10.
-     */
-    @Optional @UseDefaults
-    Property<Integer> workQueueSize();
+    @UseDefaults
+    Property<Boolean> interrupOnShutdown();
 
-// END SNIPPET: configuration
+    @UseDefaults
+    Property<Boolean> interrupOnShutdownWithWait();
+
+    @UseDefaults
+    Property<Integer> maxBatchSize();
+
+    @UseDefaults
+    Property<Long> idleWaitTime();
+
+    @UseDefaults
+    Property<Integer> threadCount();
+
+    @UseDefaults
+    Property<Integer> threadPriority();
 }
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<SchedulerConfiguration> 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<Scheduler> 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<ServiceReference<SchedulerService>>" );
+        }
+
+        @Override
+        public ZestJobDetail createJobDetails( ZestJob jobEntity )
+        {
+            ValueBuilder<ZestJobDetail> 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<? extends EntityComposite> type )
+        {
+            UnitOfWork uow = uowf.currentUnitOfWork();
+            try
+            {
+                uow.get( type, type.getName() );
+            } catch( NoSuchEntityException e)
+            {
+                uow.newEntity( type, type.getName() );
+            }
+        }
+    }
 }
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;
-
-        }
-
-    }
-}
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.
- *<p>
- * 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").
- *</p>
- *<p>
- * 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}.
- *
- *</p>
- *
- * Here is a simple example:
- * <pre><code>
- *  interface MyTask
- *      extends Task
- *  {
- *      Property&lt;String customState();
- *      Association&lt;AnotherEntity&gt; anotherEntity();
- *  }
- *
- *  class MyTaskMixin
- *      implements Runnable
- *  {
- *      &#64;This MyTaskEntity me;
- *
- *      public void run()
- *      {
- *          me.customState().set( me.anotherEntity().get().doSomeStuff( me.customState().get() ) );
- *      }
- *  }
- * </code></pre>
- *
- * Finaly, {@literal MyTask} must be assembled into an {@literal EntityComposite}.
- */
-// START SNIPPET: task
-@Concerns( UnitOfWorkConcern.class )
-public interface Task
-    extends Runnable
-{
-    Property<String> name();
-
-    @UseDefaults
-    Property<List<String>> tags();
-
-}
-// END SNIPPET: task
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggerWrapper.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggerWrapper.java
new file mode 100644
index 0000000..47ec9f5
--- /dev/null
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggerWrapper.java
@@ -0,0 +1,178 @@
+/*
+ * 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.Date;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.property.Property;
+import org.quartz.Calendar;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.JobKey;
+import org.quartz.SchedulerException;
+import org.quartz.Trigger;
+import org.quartz.TriggerKey;
+import org.quartz.spi.OperableTrigger;
+
+@Mixins( TriggerWrapper.OperableMixin.class)
+public interface TriggerWrapper extends OperableTrigger
+{
+    enum State {waiting, aquired }
+    Property<Trigger> trigger();
+
+    Property<Long> nextTime();
+
+    Property<State> state();
+
+    abstract class OperableMixin
+        implements OperableTrigger{
+
+        @Override
+        public void triggered( Calendar calendar )
+        {
+
+        }
+
+        @Override
+        public Date computeFirstFireTime( Calendar calendar )
+        {
+            return null;
+        }
+
+        @Override
+        public CompletedExecutionInstruction executionComplete( JobExecutionContext context,
+                                                                JobExecutionException result
+        )
+        {
+            return null;
+        }
+
+        @Override
+        public void updateAfterMisfire( Calendar cal )
+        {
+
+        }
+
+        @Override
+        public void updateWithNewCalendar( Calendar cal, long misfireThreshold )
+        {
+
+        }
+
+        @Override
+        public void validate()
+            throws SchedulerException
+        {
+
+        }
+
+        @Override
+        public void setFireInstanceId( String id )
+        {
+
+        }
+
+        @Override
+        public String getFireInstanceId()
+        {
+            return null;
+        }
+
+        @Override
+        public void setNextFireTime( Date nextFireTime )
+        {
+
+        }
+
+        @Override
+        public void setPreviousFireTime( Date previousFireTime )
+        {
+
+        }
+
+        @Override
+        public void setKey( TriggerKey key )
+        {
+
+        }
+
+        @Override
+        public void setJobKey( JobKey key )
+        {
+
+        }
+
+        @Override
+        public void setDescription( String description )
+        {
+
+        }
+
+        @Override
+        public void setCalendarName( String calendarName )
+        {
+
+        }
+
+        @Override
+        public void setJobDataMap( JobDataMap jobDataMap )
+        {
+
+        }
+
+        @Override
+        public void setPriority( int priority )
+        {
+
+        }
+
+        @Override
+        public void setStartTime( Date startTime )
+        {
+
+        }
+
+        @Override
+        public void setEndTime( Date endTime )
+        {
+
+        }
+
+        @Override
+        public void setMisfireInstruction( int misfireInstruction )
+        {
+
+        }
+
+        @Override
+        public int compareTo( Trigger other )
+        {
+            return -1;
+        }
+
+        @Override
+        public Object clone()
+        {
+            throw new UnsupportedOperationException( "This operation is not supported." );
+        }
+    }
+}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggersGroup.java
similarity index 75%
copy from libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
copy to libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggersGroup.java
index 95563c1..79e98d1 100644
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggersGroup.java
@@ -17,12 +17,13 @@
  * under the License.
  *
  */
-package org.apache.zest.library.scheduler.internal;
 
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.library.scheduler.Schedule;
+package org.apache.zest.library.scheduler;
 
-public interface Schedules
+import org.apache.zest.api.association.NamedAssociation;
+import org.apache.zest.api.entity.EntityComposite;
+
+public interface TriggersGroup extends EntityComposite
 {
-    ManyAssociation<Schedule> schedules();
+    NamedAssociation<TriggerWrapper> triggers();
 }
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggersGroups.java
similarity index 75%
copy from libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
copy to libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggersGroups.java
index 95563c1..e89f773 100644
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/TriggersGroups.java
@@ -17,12 +17,13 @@
  * under the License.
  *
  */
-package org.apache.zest.library.scheduler.internal;
 
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.library.scheduler.Schedule;
+package org.apache.zest.library.scheduler;
 
-public interface Schedules
+import org.apache.zest.api.association.NamedAssociation;
+import org.apache.zest.api.entity.EntityComposite;
+
+public interface TriggersGroups extends EntityComposite
 {
-    ManyAssociation<Schedule> schedules();
+    NamedAssociation<TriggersGroup> groups();
 }
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJob.java
similarity index 63%
copy from libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
copy to libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJob.java
index 95563c1..927df41 100644
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Schedules.java
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJob.java
@@ -17,12 +17,20 @@
  * under the License.
  *
  */
-package org.apache.zest.library.scheduler.internal;
 
-import org.apache.zest.api.association.ManyAssociation;
-import org.apache.zest.library.scheduler.Schedule;
+package org.apache.zest.library.scheduler;
 
-public interface Schedules
+import org.apache.zest.api.common.Optional;
+import org.apache.zest.api.entity.EntityComposite;
+import org.apache.zest.api.property.Property;
+import org.apache.zest.library.constraints.annotation.Matches;
+import org.quartz.Job;
+
+public interface ZestJob extends Job, EntityComposite
 {
-    ManyAssociation<Schedule> schedules();
+//    @Matches( "job://[a-zA-Z0-9_]+\\.[a-zA-Z0-9_]+" )
+//    Property<String> identity();
+
+    @Optional
+    Property<String> description();
 }
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJobDetail.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJobDetail.java
new file mode 100644
index 0000000..5324dd0
--- /dev/null
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJobDetail.java
@@ -0,0 +1,128 @@
+/*
+ * 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.reflect.UndeclaredThrowableException;
+import org.apache.zest.api.common.Optional;
+import org.apache.zest.api.injection.scope.This;
+import org.apache.zest.api.mixin.Mixins;
+import org.apache.zest.api.property.Property;
+import org.quartz.Job;
+import org.quartz.JobBuilder;
+import org.quartz.JobDataMap;
+import org.quartz.JobDetail;
+import org.quartz.JobKey;
+
+@Mixins( ZestJobDetail.ZestJobDetailMixin.class )
+public interface ZestJobDetail extends JobDetail
+{
+
+    interface State
+    {
+        Property<String> jobIdentity();
+
+        @Optional
+        Property<String> description();
+
+        Property<String> jobClass();
+    }
+
+    class ZestJobDetailMixin implements JobDetail
+    {
+
+        @This
+        State state;
+
+        @Override
+        public JobKey getKey()
+        {
+            String id = state.jobIdentity().get();
+            id = id.substring( "job://".length() );
+            String[] split = id.split( "\\." );
+            return JobKey.jobKey( split[ 1 ], split[ 0 ] );
+        }
+
+        @Override
+        public String getDescription()
+        {
+            return state.description().get();
+        }
+
+        @Override
+        public Class<? extends Job> getJobClass()
+        {
+            String classname = state.jobClass().get();
+            try
+            {
+                @SuppressWarnings( "unchecked" )
+                Class<? extends Job> jobClass = (Class<? extends Job>) getClass().getClassLoader()
+                    .loadClass( classname );
+                return jobClass;
+            }
+            catch( ClassNotFoundException e )
+            {
+                throw new UndeclaredThrowableException( e );
+            }
+        }
+
+        @Override
+        public JobDataMap getJobDataMap()
+        {
+            return null;
+        }
+
+        @Override
+        public boolean isDurable()
+        {
+            return true;
+        }
+
+        @Override
+        public boolean isPersistJobDataAfterExecution()
+        {
+            return false;
+        }
+
+        @Override
+        public boolean isConcurrentExectionDisallowed()
+        {
+            return false;
+        }
+
+        @Override
+        public boolean requestsRecovery()
+        {
+            return false;
+        }
+
+        @Override
+        public JobBuilder getJobBuilder()
+        {
+            throw new UnsupportedOperationException( "Quartz JobBuilder is not supported in Apache Zest. Use EntityBuilders." );
+        }
+
+        @Override
+        public Object clone()
+        {
+            throw new UnsupportedOperationException( "clone() should not be needed as JobDetail is a ValueComposite." );
+        }
+    }
+}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJobFactory.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJobFactory.java
new file mode 100644
index 0000000..312d707
--- /dev/null
+++ b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/ZestJobFactory.java
@@ -0,0 +1,63 @@
+/*
+ * 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.injection.scope.Structure;
+import org.apache.zest.api.unitofwork.UnitOfWork;
+import org.apache.zest.api.unitofwork.UnitOfWorkFactory;
+import org.quartz.Job;
+import org.quartz.JobDetail;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.spi.JobFactory;
+import org.quartz.spi.TriggerFiredBundle;
+
+public class ZestJobFactory
+    implements JobFactory
+{
+    @Structure
+    private UnitOfWorkFactory uowf;
+
+    @Override
+    public Job newJob( TriggerFiredBundle bundle, Scheduler scheduler )
+        throws SchedulerException
+    {
+        JobDetail jobDetail = bundle.getJobDetail();
+        Class<? extends Job> jobType = jobDetail.getJobClass();
+        if( ZestJob.class.isAssignableFrom( jobType ) )
+        {
+            JobKey jobKey = jobDetail.getKey();
+            String jobId = "job://" + jobKey.getGroup() + "." + jobKey.getName();
+
+            @SuppressWarnings( "unchecked" )
+            ZestJob job = createJob( (Class<? extends ZestJob>) jobType, jobId );
+            return job;
+        }
+        return null;
+    }
+
+    private <T extends ZestJob> T createJob( Class<T> jobType, String jobId )
+    {
+        UnitOfWork uow = uowf.currentUnitOfWork();
+        return uow.get( jobType, jobId );
+    }
+}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/bootstrap/SchedulerAssembler.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/bootstrap/SchedulerAssembler.java
deleted file mode 100644
index 317abd1..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/bootstrap/SchedulerAssembler.java
+++ /dev/null
@@ -1,117 +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.bootstrap;
-
-import org.apache.zest.api.unitofwork.concern.UnitOfWorkConcern;
-import org.apache.zest.bootstrap.Assemblers;
-import org.apache.zest.bootstrap.AssemblyException;
-import org.apache.zest.bootstrap.EntityDeclaration;
-import org.apache.zest.bootstrap.ModuleAssembly;
-import org.apache.zest.bootstrap.ServiceDeclaration;
-import org.apache.zest.bootstrap.ValueDeclaration;
-import org.apache.zest.library.scheduler.SchedulerConfiguration;
-import org.apache.zest.library.scheduler.SchedulerService;
-import org.apache.zest.library.scheduler.internal.TaskRunner;
-import org.apache.zest.library.scheduler.ScheduleFactory;
-import org.apache.zest.library.scheduler.internal.Schedules;
-import org.apache.zest.library.scheduler.CronSchedule;
-import org.apache.zest.library.scheduler.OnceSchedule;
-import org.apache.zest.library.scheduler.timeline.Timeline;
-import org.apache.zest.library.scheduler.timeline.TimelineForScheduleConcern;
-import org.apache.zest.library.scheduler.timeline.TimelineRecord;
-import org.apache.zest.library.scheduler.timeline.TimelineScheduleMixin;
-import org.apache.zest.library.scheduler.timeline.TimelineSchedulerServiceMixin;
-
-/**
- * Assembler for Scheduler.
- *
- * Use this Assembler to add the Scheduler service to your application.
- * This Assembler provide a fluent api to programmatically configure configuration defaults and
- * activate the Timeline service assembly that allow to browse in past and future Task runs.
- *
- * Here is a full example:
- * <pre>
- *      new SchedulerAssembler().
- *              visibleIn( Visibility.layer ).
- *              withConfig( configModuleAssembly, Visibility.application ).
- *              withTimeline().
- *              assemble( module );
- * </pre>
- */
-public class SchedulerAssembler
-    extends Assemblers.VisibilityConfig<SchedulerAssembler>
-{
-
-    private static final int DEFAULT_WORKERS_COUNT = Runtime.getRuntime().availableProcessors() + 1;
-    private static final int DEFAULT_WORKQUEUE_SIZE = 10;
-
-    private boolean timeline;
-
-    /**
-     * Activate the assembly of Timeline related services.
-     *
-     * @return SchedulerAssembler
-     */
-    public SchedulerAssembler withTimeline()
-    {
-        timeline = true;
-        return this;
-    }
-
-    @Override
-    public void assemble( ModuleAssembly assembly )
-        throws AssemblyException
-    {
-        assembly.services( ScheduleFactory.class );
-        assembly.entities( Schedules.class );
-        EntityDeclaration scheduleEntities = assembly.entities( CronSchedule.class, OnceSchedule.class );
-
-        ValueDeclaration scheduleValues = assembly.values( CronSchedule.class, OnceSchedule.class );
-
-        ServiceDeclaration schedulerDeclaration = assembly.services( SchedulerService.class )
-            .visibleIn( visibility() )
-            .instantiateOnStartup();
-
-        assembly.transients( Runnable.class ).withMixins( TaskRunner.class ).withConcerns( UnitOfWorkConcern.class );
-
-        if( timeline )
-        {
-            scheduleEntities.withTypes( Timeline.class )
-                .withMixins( TimelineScheduleMixin.class )
-                .withConcerns( TimelineForScheduleConcern.class );
-
-            scheduleValues.withTypes( Timeline.class )
-                .withMixins( TimelineScheduleMixin.class )
-                .withConcerns( TimelineForScheduleConcern.class );
-
-            // Internal
-            assembly.values( TimelineRecord.class );
-            schedulerDeclaration.withTypes( Timeline.class ).withMixins( TimelineSchedulerServiceMixin.class );
-        }
-
-        if( hasConfig() )
-        {
-            configModule().entities( SchedulerConfiguration.class )
-                .visibleIn( configVisibility() );
-            SchedulerConfiguration defaults = assembly.forMixin( SchedulerConfiguration.class ).declareDefaults();
-            defaults.workersCount().set( DEFAULT_WORKERS_COUNT );
-            defaults.workQueueSize().set( DEFAULT_WORKQUEUE_SIZE );
-        }
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/bootstrap/package.html b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/bootstrap/package.html
deleted file mode 100644
index b9a2ef1..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/bootstrap/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Assembly.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultRejectionHandler.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultRejectionHandler.java
deleted file mode 100644
index 9a8e631..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultRejectionHandler.java
+++ /dev/null
@@ -1,39 +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.defaults;
-
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ThreadPoolExecutor;
-import org.apache.zest.library.scheduler.SchedulerService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DefaultRejectionHandler
-    implements RejectedExecutionHandler
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( SchedulerService.class );
-
-    @Override
-    public void rejectedExecution( Runnable r, ThreadPoolExecutor executor )
-    {
-        LOGGER.error( "Runnable [" + r + "] was rejected by executor [" + executor + "]" );
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultScheduleFactoryMixin.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultScheduleFactoryMixin.java
deleted file mode 100644
index 27c7125..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultScheduleFactoryMixin.java
+++ /dev/null
@@ -1,91 +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.defaults;
-
-import org.apache.zest.api.entity.EntityBuilder;
-import org.apache.zest.api.injection.scope.Service;
-import org.apache.zest.api.injection.scope.Structure;
-import org.apache.zest.api.structure.Module;
-import org.apache.zest.api.unitofwork.UnitOfWork;
-import org.apache.zest.library.scheduler.SchedulerService;
-import org.apache.zest.library.scheduler.Task;
-import org.apache.zest.library.scheduler.Schedule;
-import org.apache.zest.library.scheduler.ScheduleFactory;
-import org.apache.zest.library.scheduler.CronSchedule;
-import org.apache.zest.library.scheduler.OnceSchedule;
-import org.apache.zest.spi.uuid.UuidIdentityGeneratorService;
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class DefaultScheduleFactoryMixin
-    implements ScheduleFactory
-{
-    private static final Logger logger = LoggerFactory.getLogger( ScheduleFactory.class );
-
-    @Structure
-    private Module module;
-
-    @Service
-    private SchedulerService scheduler;
-
-    @Service
-    private UuidIdentityGeneratorService uuid;
-
-    @Override
-    public CronSchedule newCronSchedule( Task task, String cronExpression, DateTime start )
-    {
-        return newPersistentCronSchedule( task, cronExpression, start );
-    }
-
-    @Override
-    public Schedule newOnceSchedule( Task task, DateTime runAt )
-    {
-        return newPersistentOnceSchedule( task, runAt );
-    }
-
-    private CronSchedule newPersistentCronSchedule( Task task, String cronExpression, DateTime start )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<CronSchedule> builder = uow.newEntityBuilder( CronSchedule.class );
-        CronSchedule instance = builder.instance();
-        instance.task().set( task );
-        instance.start().set( start );
-        instance.identity().set( uuid.generate( CronSchedule.class ) );
-        instance.cronExpression().set( cronExpression );
-        CronSchedule schedule = builder.newInstance();
-        logger.info( "Schedule {} created: {}", schedule.presentationString(), schedule.identity().get() );
-        return schedule;
-    }
-
-    private Schedule newPersistentOnceSchedule( Task task, DateTime runAt )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        EntityBuilder<OnceSchedule> builder = uow.newEntityBuilder( OnceSchedule.class );
-        OnceSchedule builderInstance = builder.instance();
-        builderInstance.task().set( task );
-        builderInstance.start().set( runAt );
-        builderInstance.identity().set( uuid.generate( OnceSchedule.class ) );
-        OnceSchedule schedule = builder.newInstance();
-        logger.info( "Schedule {} created: {}", schedule.presentationString(), schedule.identity().get() );
-        return schedule;
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultThreadFactory.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultThreadFactory.java
deleted file mode 100644
index 43520bd..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/defaults/DefaultThreadFactory.java
+++ /dev/null
@@ -1,57 +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.defaults;
-
-import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.zest.api.injection.scope.This;
-import org.apache.zest.library.scheduler.internal.Execution;
-import org.apache.zest.library.scheduler.SchedulerService;
-
-public class DefaultThreadFactory
-    implements java.util.concurrent.ThreadFactory
-{
-    private static final AtomicInteger POOL_NUMBER = new AtomicInteger( 1 );
-    private final ThreadGroup group;
-    private final AtomicInteger threadNumber = new AtomicInteger( 1 );
-    private final String namePrefix;
-
-    protected DefaultThreadFactory( @This SchedulerService me )
-    {
-        SecurityManager sm = System.getSecurityManager();
-        group = ( sm != null ) ? sm.getThreadGroup() : Execution.ExecutionMixin.TG;
-        namePrefix = me.identity().get() + "-P" + POOL_NUMBER.getAndIncrement() + "W";
-    }
-
-    @Override
-    public Thread newThread( Runnable runnable )
-    {
-        Thread thread = new Thread( group, runnable, namePrefix + threadNumber.getAndIncrement(), 0 );
-        if( thread.isDaemon() )
-        {
-            thread.setDaemon( false );
-        }
-        if( thread.getPriority() != Thread.NORM_PRIORITY )
-        {
-            thread.setPriority( Thread.NORM_PRIORITY );
-        }
-        return thread;
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Execution.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Execution.java
deleted file mode 100644
index 08eb627..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/Execution.java
+++ /dev/null
@@ -1,275 +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.internal;
-
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import org.apache.zest.api.concern.Concerns;
-import org.apache.zest.api.configuration.Configuration;
-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.UnitOfWorkConcern;
-import org.apache.zest.library.scheduler.Schedule;
-import org.apache.zest.library.scheduler.Scheduler;
-import org.apache.zest.library.scheduler.SchedulerConfiguration;
-
-/**
- * This composite handles the Execution of Schedules.
- *
- * The composite is internal and should never be used by clients.
- */
-@Mixins( Execution.ExecutionMixin.class )
-public interface Execution
-{
-    void dispatchForExecution( Schedule schedule );
-
-    void start()
-        throws Exception;
-
-    void stop()
-        throws Exception;
-
-    void updateNextTime( ScheduleTime schedule );   // This method is public, only because the UnitOfWorkConcern is wanted.
-
-    class ExecutionMixin
-        implements Execution, Runnable
-    {
-        public static final ThreadGroup TG = new ThreadGroup( "Zest Scheduling" );
-
-        private final Object lock = new Object();
-
-        @Structure
-        private Module module;
-
-        @This
-        private Scheduler scheduler;
-
-        @This
-        private Configuration<SchedulerConfiguration> config;
-
-        @This
-        private ThreadFactory threadFactory;
-
-        @This
-        private RejectedExecutionHandler rejectionHandler;
-
-        private final SortedSet<ScheduleTime> timingQueue = new TreeSet<>();
-        private volatile boolean running;
-        private ThreadPoolExecutor taskExecutor;
-        private volatile Thread scheduleThread;
-
-        @Override
-        public void run()
-        {
-            running = true;
-            while( running )
-            {
-                try
-                {
-                    ScheduleTime scheduleTime = timing();
-                    if( scheduleTime != null )
-                    {
-                        waitFor( scheduleTime );
-
-                        if( isTime( scheduleTime ) ) // We might have been awakened to reschedule
-                        {
-                            updateNextTime( scheduleTime );
-                        }
-                    }
-                    else
-                    {
-                        waitFor( 100 );
-                    }
-                }
-                catch( Throwable e )
-                {
-                    e.printStackTrace();
-                }
-            }
-        }
-
-        private ScheduleTime timing()
-        {
-            synchronized( lock )
-            {
-                if( timingQueue.size() == 0 )
-                {
-                    return null;
-                }
-                return timingQueue.first();
-            }
-        }
-
-        private boolean isTime( ScheduleTime scheduleTime )
-        {
-            long now = System.currentTimeMillis();
-            return scheduleTime.nextTime() <= now;
-        }
-
-        private void waitFor( ScheduleTime scheduleTime )
-            throws InterruptedException
-        {
-            long now = System.currentTimeMillis();
-            long waitingTime = scheduleTime.nextTime() - now;
-            waitFor( waitingTime );
-        }
-
-        private void waitFor( long waitingTime )
-        {
-            if( waitingTime > 0 )
-            {
-                synchronized( lock )
-                {
-                    try
-                    {
-                        lock.wait( waitingTime );
-                    }
-                    catch( InterruptedException e )
-                    {
-                        // should be ignored.
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void updateNextTime( ScheduleTime oldScheduleTime )
-        {
-            long now = System.currentTimeMillis();
-
-            try (UnitOfWork uow = module.newUnitOfWork()) // This will discard() the UoW when block is exited. We are only doing reads, so fine.
-            {
-                submitTaskForExecution( oldScheduleTime );
-                Schedule schedule = uow.get( Schedule.class, oldScheduleTime.scheduleIdentity() );
-                long nextTime = schedule.nextRun( now + 1000 );
-                if( nextTime != Long.MIN_VALUE )
-                {
-                    ScheduleTime newScheduleTime = new ScheduleTime( oldScheduleTime.scheduleIdentity(), nextTime );
-                    synchronized( lock )
-                    {
-                        // Re-add to the Timing Queue, to re-position the sorting.
-                        timingQueue.remove( oldScheduleTime );
-                        timingQueue.add( newScheduleTime );
-                    }
-                }
-                else
-                {
-                    synchronized( lock )
-                    {
-                        timingQueue.remove( oldScheduleTime );
-                    }
-                }
-            }
-            catch( NoSuchEntityException e )
-            {
-                e.printStackTrace();
-//                scheduler.cancelSchedule( oldScheduleTime.scheduleIdentity() );
-            }
-        }
-
-        private void submitTaskForExecution( ScheduleTime scheduleTime )
-        {
-            Runnable taskRunner = module.newTransient( Runnable.class, scheduleTime );
-            this.taskExecutor.submit( taskRunner );
-        }
-
-        public void dispatchForExecution( Schedule schedule )
-        {
-            long now = System.currentTimeMillis();
-            long nextRun = schedule.nextRun( now + 1000 );
-            if( nextRun > 0 )
-            {
-                synchronized( lock )
-                {
-                    timingQueue.add( new ScheduleTime( schedule.identity().get(), nextRun ) );
-                    lock.notifyAll();
-                }
-            }
-        }
-
-        @Override
-        public void start()
-            throws Exception
-        {
-            SchedulerConfiguration configuration = config.get();
-            Integer workersCount = configuration.workersCount().get();
-            Integer workQueueSize = configuration.workQueueSize().get();
-            createThreadPoolExecutor( workersCount, workQueueSize );
-            taskExecutor.prestartAllCoreThreads();
-
-            SecurityManager sm = System.getSecurityManager();
-            ThreadGroup threadGroup = sm != null ? sm.getThreadGroup() : TG;
-            scheduleThread = new Thread( threadGroup, this, "Scheduler" );
-            scheduleThread.start();
-        }
-
-        private void createThreadPoolExecutor( Integer workersCount, Integer workQueueSize )
-        {
-            int corePoolSize = 2;
-            if( workersCount > 4 )
-            {
-                corePoolSize = workersCount / 4 + 1;
-            }
-            if( corePoolSize > 50 )
-            {
-                corePoolSize = 20;
-            }
-            if( workersCount > 200 )
-            {
-                workersCount = 200;
-            }
-            taskExecutor = new ThreadPoolExecutor( corePoolSize, workersCount,
-                                                   0, TimeUnit.MILLISECONDS,
-                                                   new LinkedBlockingQueue<>( workQueueSize ),
-                                                   threadFactory, rejectionHandler );
-        }
-
-        @Override
-        public void stop()
-            throws Exception
-        {
-            running = false;
-            synchronized( this )
-            {
-                scheduleThread.interrupt();
-            }
-            taskExecutor.shutdown();
-            try
-            {
-                taskExecutor.awaitTermination( 5, TimeUnit.SECONDS );
-            }
-            catch( InterruptedException e )
-            {
-                e.printStackTrace();
-            }
-            taskExecutor.shutdownNow();
-        }
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/ScheduleTime.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/ScheduleTime.java
deleted file mode 100644
index b008de7..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/ScheduleTime.java
+++ /dev/null
@@ -1,61 +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.internal;
-
-import org.apache.zest.api.util.NullArgumentException;
-
-public final class ScheduleTime
-    implements Comparable<ScheduleTime>
-{
-    private String scheduleIdentity;
-    private long nextTime;
-
-    public ScheduleTime( String scheduleIdentity, long nextTime )
-    {
-        NullArgumentException.validateNotEmpty( "scheduleIdentity", scheduleIdentity );
-        this.scheduleIdentity = scheduleIdentity;
-        this.nextTime = nextTime;
-    }
-
-    public long nextTime()
-    {
-        return nextTime;
-    }
-
-    public String scheduleIdentity()
-    {
-        return scheduleIdentity;
-    }
-
-    @Override
-    public int compareTo( ScheduleTime another )
-    {
-        if( this.scheduleIdentity.equals( another.scheduleIdentity ) )
-        {
-            return 0;
-        }
-
-        if( this.nextTime < another.nextTime )
-        {
-            return -1;
-        }
-        return 1;
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/SchedulerMixin.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/SchedulerMixin.java
deleted file mode 100644
index 3afafa5..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/SchedulerMixin.java
+++ /dev/null
@@ -1,199 +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.internal;
-
-import org.apache.zest.api.configuration.Configuration;
-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.service.ServiceActivation;
-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.UnitOfWorkCompletionException;
-import org.apache.zest.api.usecase.UsecaseBuilder;
-import org.apache.zest.library.scheduler.Scheduler;
-import org.apache.zest.library.scheduler.SchedulerConfiguration;
-import org.apache.zest.library.scheduler.SchedulerService;
-import org.apache.zest.library.scheduler.SchedulesHandler;
-import org.apache.zest.library.scheduler.Task;
-import org.apache.zest.library.scheduler.CronSchedule;
-import org.apache.zest.library.scheduler.Schedule;
-import org.apache.zest.library.scheduler.ScheduleFactory;
-import org.joda.time.DateTime;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SchedulerMixin
-    implements Scheduler, ServiceActivation
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( Scheduler.class );
-
-    @Service
-    private ScheduleFactory scheduleFactory;
-
-    @Structure
-    private Module module;
-
-    @This
-    private SchedulerService me;
-
-    @This
-    private SchedulesHandler schedulesHandler;
-
-    @This
-    private Execution execution;
-
-    @This
-    private Configuration<SchedulerConfiguration> config;
-
-    public SchedulerMixin()
-    {
-    }
-
-    @Override
-    public Schedule scheduleOnce( Task task, int initialSecondsDelay )
-    {
-        long now = System.currentTimeMillis();
-        Schedule schedule = scheduleFactory.newOnceSchedule( task, new DateTime( now + initialSecondsDelay * 1000 ) );
-        saveAndDispatch( schedule );
-        return schedule;
-    }
-
-    @Override
-    public Schedule scheduleOnce( Task task, DateTime runAt )
-    {
-        Schedule schedule = scheduleFactory.newOnceSchedule( task, runAt );
-        saveAndDispatch( schedule );
-        return schedule;
-    }
-
-    @Override
-    public Schedule scheduleCron( Task task, String cronExpression )
-    {
-        DateTime now = new DateTime();
-        Schedule schedule = scheduleFactory.newCronSchedule( task, cronExpression, now );
-        saveAndDispatch( schedule );
-        return schedule;
-    }
-
-    @Override
-    public Schedule scheduleCron( Task task, @CronSchedule.CronExpression String cronExpression, DateTime start )
-    {
-        Schedule schedule = scheduleFactory.newCronSchedule( task, cronExpression, start );
-        saveAndDispatch( schedule );
-        return schedule;
-    }
-
-    @Override
-    public void scheduleCron( Schedule schedule )
-    {
-        saveAndDispatch( schedule );
-    }
-
-    @Override
-    public Schedule scheduleCron( Task task, String cronExpression, long initialDelay )
-    {
-        DateTime start = new DateTime( System.currentTimeMillis() + initialDelay );
-        Schedule schedule = scheduleFactory.newCronSchedule( task, cronExpression, start );
-        saveAndDispatch( schedule );
-        return schedule;
-    }
-
-    @Override
-    public void cancelSchedule( String scheduleId )
-    {
-        UnitOfWork uow = module.currentUnitOfWork();
-        Schedule schedule = null;
-        try
-        {
-            schedule = uow.get( Schedule.class, scheduleId );
-        }
-        catch( NoSuchEntityException e )
-        {
-            return;
-        }
-        cancelSchedule( schedule );
-    }
-
-    @Override
-    public void cancelSchedule( Schedule schedule )
-    {
-        Schedules active = schedulesHandler.getActiveSchedules();
-        if( active.schedules().remove( schedule ) )
-        {
-            schedule.cancelled().set( true );
-        }
-    }
-
-    private void saveAndDispatch( Schedule schedule )
-    {
-        Schedules schedules = schedulesHandler.getActiveSchedules();
-        schedules.schedules().add( schedule );
-        execution.dispatchForExecution( schedule );
-    }
-
-    private void loadSchedules()
-        throws UnitOfWorkCompletionException
-    {
-        try (UnitOfWork ignored = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Initialize Schedules" ) ))
-        {
-            Schedules schedules = schedulesHandler.getActiveSchedules();
-            for( Schedule schedule : schedules.schedules() )
-            {
-                dispatch( schedule );
-            }
-        }
-    }
-
-    private void dispatch( Schedule schedule )
-    {
-        try
-        {
-            if( !schedule.cancelled().get() && !schedule.done().get() )
-            {
-                execution.dispatchForExecution( schedule );
-            }
-        } catch( Exception e )
-        {
-            e.printStackTrace();
-        }
-    }
-
-    @Override
-    public void activateService()
-        throws Exception
-    {
-        // Throws IllegalArgument if corePoolSize or keepAliveTime less than zero,
-        // or if workersCount less than or equal to zero,
-        // or if corePoolSize greater than workersCount.
-        execution.start();
-        loadSchedules();
-        LOGGER.debug( "Activated" );
-    }
-
-    @Override
-    public void passivateService()
-        throws Exception
-    {
-        execution.stop();
-        LOGGER.debug( "Passivated" );
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/TaskRunner.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/TaskRunner.java
deleted file mode 100644
index fa52d73..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/internal/TaskRunner.java
+++ /dev/null
@@ -1,115 +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.internal;
-
-import java.lang.reflect.UndeclaredThrowableException;
-import java.util.concurrent.locks.ReentrantLock;
-import org.apache.zest.api.injection.scope.Structure;
-import org.apache.zest.api.injection.scope.Uses;
-import org.apache.zest.api.structure.Module;
-import org.apache.zest.api.unitofwork.UnitOfWork;
-import org.apache.zest.api.usecase.UsecaseBuilder;
-import org.apache.zest.library.scheduler.Task;
-import org.apache.zest.library.scheduler.Schedule;
-
-public class TaskRunner
-    implements Runnable
-{
-    private static ReentrantLock lock = new ReentrantLock();
-
-    @Structure
-    private Module module;
-
-    @Uses
-    private ScheduleTime schedule;
-
-    @Override
-    public void run()
-    {
-        // TODO: (niclas) I am NOT happy with this implementation, requiring 3 UnitOfWorks to be created. 15-20 milliseconds on my MacBook. If there is a better way to detect overrun, two of those might not be needed.
-        UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Task Runner initialize" ) );
-        try
-        {
-            lock.lock();
-            Schedule schedule = uow.get( Schedule.class, this.schedule.scheduleIdentity() );
-            if( !schedule.running().get() )  // check for overrun.
-            {
-                try
-                {
-                    schedule.taskStarting();
-                    schedule.running().set( true );
-                    uow.complete();                     // This completion is needed to detect overrun
-
-                    uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Task Runner" ) );
-                    schedule = uow.get( schedule );     // re-attach the entity to the new UnitOfWork
-                    Task task = schedule.task().get();
-                    lock.unlock();
-                    task.run();
-                    lock.lock();
-                    uow.complete();
-                    uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "Task Runner conclude" ) );
-                    schedule = uow.get( schedule );     // re-attach the entity to the new UnitOfWork
-                    schedule.running().set( false );
-                    schedule.taskCompletedSuccessfully();
-                    schedule.executionCounter().set( schedule.executionCounter().get() + 1 );
-                }
-                catch( RuntimeException ex )
-                {
-                    schedule.running().set( false );
-                    processException( schedule, ex );
-                }
-            }
-            else
-            {
-                schedule.overrun().set( schedule.overrun().get() + 1 );
-            }
-            uow.complete();
-        }
-        catch( Exception e )
-        {
-            e.printStackTrace();
-            throw new UndeclaredThrowableException( e );
-        }
-        finally
-        {
-            uow.discard();
-            try
-            {
-                lock.unlock();
-            }
-            catch( IllegalMonitorStateException e )
-            {
-                // ignore, as it may happen on certain exceptions.
-            }
-        }
-    }
-
-    private void processException( Schedule schedule, RuntimeException ex )
-    {
-        Throwable exception = ex;
-        while( exception instanceof UndeclaredThrowableException )
-        {
-            exception = ( (UndeclaredThrowableException) ex ).getUndeclaredThrowable();
-        }
-        schedule.taskCompletedWithException( exception );
-        schedule.exceptionCounter().set( schedule.exceptionCounter().get() + 1 );
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/package.html b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/package.html
deleted file mode 100644
index a796ce1..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Library.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/schedule/package.html b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/schedule/package.html
deleted file mode 100644
index 7c74250..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/schedule/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Schedules.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/Timeline.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/Timeline.java
deleted file mode 100644
index 1c2e7e7..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/Timeline.java
+++ /dev/null
@@ -1,73 +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.timeline;
-
-import java.time.ZonedDateTime;
-import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation;
-
-/**
- * Timeline allow to browse in past and future Task runs.
- */
-// START SNIPPET: timeline
-public interface Timeline
-{
-// END SNIPPET: timeline
-
-    /**
-     * @param maxResults Maximum number of TimelineRecord to compute
-     *
-     * @return Last past records
-     */
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY )
-// START SNIPPET: timeline
-    Iterable<TimelineRecord> getLastRecords( int maxResults );
-// END SNIPPET: timeline
-
-    /**
-     * @param maxResults Maximum number of TimelineRecord to compute
-     *
-     * @return Next running or future records
-     */
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY )
-// START SNIPPET: timeline
-    Iterable<TimelineRecord> getNextRecords( int maxResults );
-// END SNIPPET: timeline
-
-    /**
-     * @param from Lower limit
-     * @param to   Upper limit
-     *
-     * @return Records between the given dates
-     */
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY )
-// START SNIPPET: timeline
-    Iterable<TimelineRecord> getRecords( ZonedDateTime from, ZonedDateTime to );
-// END SNIPPET: timeline
-
-    /**
-     * @param from Lower limit
-     * @param to   Upper limit
-     *
-     * @return Records between the given dates
-     */
-    @UnitOfWorkPropagation( UnitOfWorkPropagation.Propagation.MANDATORY )
-// START SNIPPET: timeline
-    Iterable<TimelineRecord> getRecords( long from, long to );
-}
-// END SNIPPET: timeline
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineForScheduleConcern.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineForScheduleConcern.java
deleted file mode 100644
index 2ec856d..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineForScheduleConcern.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.timeline;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.util.List;
-import org.apache.zest.api.concern.ConcernOf;
-import org.apache.zest.api.injection.scope.Structure;
-import org.apache.zest.api.injection.scope.This;
-import org.apache.zest.api.structure.Module;
-import org.apache.zest.api.value.ValueBuilder;
-import org.apache.zest.library.scheduler.Schedule;
-
-public abstract class TimelineForScheduleConcern
-    extends ConcernOf<Schedule>
-    implements Schedule
-{
-    @This
-    private TimelineScheduleState state;
-
-    @Structure
-    private Module module;
-
-    @Override
-    public void taskStarting()
-    {
-        addRecord( TimelineRecordStep.STARTED, "" );
-        next.taskStarting();
-    }
-
-    @Override
-    public void taskCompletedSuccessfully()
-    {
-        addRecord( TimelineRecordStep.SUCCESS, "" );
-        next.taskCompletedSuccessfully();
-    }
-
-    @Override
-    public void taskCompletedWithException( Throwable ex )
-    {
-        TimelineRecordStep step = TimelineRecordStep.FAILURE;
-        String details = "Exception occurred:" + getStackTrace( ex );
-        addRecord( step, details );
-        next.taskCompletedWithException( ex );
-    }
-
-    private void addRecord( TimelineRecordStep step, String details )
-    {
-        ValueBuilder<TimelineRecord> builder = module.newValueBuilder( TimelineRecord.class );
-        TimelineRecord prototype = builder.prototype();
-        prototype.step().set( step );
-        prototype.taskName().set( task().get().name().get() );
-        List<String> tags = task().get().tags().get();
-        prototype.taskTags().set( tags );
-        prototype.timestamp().set( System.currentTimeMillis() );
-        prototype.scheduleIdentity().set( this.identity().get() );
-        prototype.details().set( details );
-        TimelineRecord record = builder.newInstance();
-        List<TimelineRecord> timelineRecords = state.history().get();
-        timelineRecords.add( record );
-        state.history().set( timelineRecords );
-    }
-
-    private String getStackTrace( Throwable ex )
-    {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream( 1000 );
-        BufferedOutputStream out = new BufferedOutputStream( baos );
-        PrintStream print = new PrintStream( out );
-        ex.printStackTrace( print );
-        print.flush();
-        return baos.toString();
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineRecord.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineRecord.java
deleted file mode 100644
index 1c7c304..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineRecord.java
+++ /dev/null
@@ -1,79 +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.timeline;
-
-import java.util.List;
-import org.apache.zest.api.common.UseDefaults;
-import org.apache.zest.api.entity.Queryable;
-import org.apache.zest.api.mixin.Mixins;
-import org.apache.zest.api.property.Property;
-import org.apache.zest.api.value.ValueComposite;
-import org.apache.zest.library.scheduler.Scheduler;
-
-/**
- * Record in {@link Scheduler}'s {@link Timeline}.
- *
- * {@link TimelineRecord}s are {@link Comparable} regarding their {@link TimelineRecord#timestamp()}.
- */
-@Mixins( TimelineRecord.Mixin.class )
-public interface TimelineRecord
-    extends Comparable<TimelineRecord>, ValueComposite
-{
-    /**
-     * @return Identity of the associated {@link Scheduler}
-     */
-    Property<String> scheduleIdentity();
-
-    /**
-     * @return Timestamp of this record
-     */
-    Property<Long> timestamp();
-
-    /**
-     * @return Name of the associated {@link org.apache.zest.library.scheduler.Task}
-     */
-    Property<String> taskName();
-
-    /**
-     * @return Tags of the associated {@link org.apache.zest.library.scheduler.Task}
-     */
-    @UseDefaults
-    Property<List<String>> taskTags();
-
-    Property<TimelineRecordStep> step();
-
-    /**
-     * @return Details text of this record
-     */
-    @Queryable( false )
-    @UseDefaults
-    Property<String> details();
-
-    abstract class Mixin
-        implements TimelineRecord
-    {
-
-        @Override
-        public int compareTo( TimelineRecord o )
-        {
-            return timestamp().get().compareTo( o.timestamp().get() );
-        }
-    }
-
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineRecordStep.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineRecordStep.java
deleted file mode 100644
index e1110ce..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineRecordStep.java
+++ /dev/null
@@ -1,27 +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.timeline;
-
-public enum TimelineRecordStep
-{
-    STARTED,
-    SUCCESS,
-    FAILURE,
-    FUTURE
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineScheduleMixin.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineScheduleMixin.java
deleted file mode 100644
index 01d9628..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineScheduleMixin.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * 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.timeline;
-
-import java.time.ZonedDateTime;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.apache.zest.api.injection.scope.Structure;
-import org.apache.zest.api.injection.scope.This;
-import org.apache.zest.api.structure.Module;
-import org.apache.zest.api.value.ValueBuilder;
-import org.apache.zest.library.scheduler.Schedule;
-
-public class TimelineScheduleMixin
-    implements Timeline
-{
-    @Structure
-    private Module module;
-
-    @This
-    private TimelineScheduleState state;
-
-    @This
-    private Schedule me;
-
-    @Override
-    public Iterable<TimelineRecord> getLastRecords( int maxResults )
-    {
-        List<TimelineRecord> timelineRecords = state.history().get();
-        int size = timelineRecords.size();
-        if( size < maxResults )
-        {
-            return Collections.unmodifiableCollection( timelineRecords );
-        }
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        for( int i = size - maxResults; i < size; i++ )
-        {
-            result.add( timelineRecords.get( i ) );
-        }
-        return result;
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getNextRecords( int maxResults )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        long time = System.currentTimeMillis();
-        for( int i = 0; i < maxResults; i++ )
-        {
-            time = me.nextRun( time );
-            result.add( createFutureRecord( time ) );
-        }
-        return result;
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getRecords( ZonedDateTime from, ZonedDateTime to )
-    {
-        return getRecords( from.toInstant().toEpochMilli(), to.toInstant().toEpochMilli() );
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getRecords( long from, long to )
-    {
-        long now = System.currentTimeMillis();
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        result.addAll( getPastRecords( from ) );
-        result.addAll( getFutureRecords( now, to ) );
-        return result;
-    }
-
-    private Collection<? extends TimelineRecord> getPastRecords( long from )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        List<TimelineRecord> timelineRecords = state.history().get();
-        for( TimelineRecord record : timelineRecords )
-        {
-            Long timestamp = record.timestamp().get();
-            if( timestamp >= from )
-            {
-                result.add( record );
-            }
-        }
-        return result;
-    }
-
-    private Collection<? extends TimelineRecord> getFutureRecords( long now, long to )
-    {
-        if( now > to )
-        {
-            return Collections.emptyList();
-        }
-
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        long time = now;
-        while( time <= to )
-        {
-            time = me.nextRun( time );
-            if( time <= to )
-            {
-                result.add( createFutureRecord( time ) );
-            }
-        }
-        return result;
-    }
-
-    private TimelineRecord createFutureRecord( long when )
-    {
-        ValueBuilder<TimelineRecord> builder = module.newValueBuilder( TimelineRecord.class );
-        TimelineRecord prototype = builder.prototype();
-        prototype.step().set( TimelineRecordStep.FUTURE );
-        prototype.taskName().set( me.task().get().name().get() );
-        List<String> tags = me.task().get().tags().get();
-        prototype.taskTags().set( tags );
-        prototype.timestamp().set( when );
-        prototype.scheduleIdentity().set( me.identity().get() );
-        prototype.details().set( "" );
-        return builder.newInstance();
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineScheduleState.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineScheduleState.java
deleted file mode 100644
index c6ff172..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineScheduleState.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * 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.timeline;
-
-import java.util.List;
-import org.apache.zest.api.common.UseDefaults;
-import org.apache.zest.api.property.Property;
-
-public interface TimelineScheduleState
-{
-    @UseDefaults
-    Property<List<TimelineRecord>> history();
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineSchedulerServiceMixin.java b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineSchedulerServiceMixin.java
deleted file mode 100644
index d04934c..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/TimelineSchedulerServiceMixin.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * 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.timeline;
-
-import java.time.ZonedDateTime;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.apache.zest.api.injection.scope.Structure;
-import org.apache.zest.api.injection.scope.This;
-import org.apache.zest.api.service.ServiceComposite;
-import org.apache.zest.api.structure.Module;
-import org.apache.zest.functional.Iterables;
-import org.apache.zest.library.scheduler.SchedulerService;
-import org.apache.zest.library.scheduler.SchedulesHandler;
-import org.apache.zest.library.scheduler.Schedule;
-import org.apache.zest.library.scheduler.internal.Schedules;
-
-/**
- * WARN TimelineService Mixin use SortedSets to keep records ordered and repeatedly search for the next run.
- * Could be greedy with large intervals
- */
-public abstract class TimelineSchedulerServiceMixin
-    implements Timeline, ServiceComposite
-{
-    @Structure
-    private Module module;
-
-    @This
-    private SchedulerService scheduler;
-
-    @This
-    private SchedulesHandler schedulesHandler;
-
-    @Override
-    public Iterable<TimelineRecord> getLastRecords( int maxResults )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-
-        Schedules schedules = schedulesHandler.getActiveSchedules();
-        for( Schedule schedule : schedules.schedules() )
-        {
-            Timeline timeline = (Timeline) schedule;
-            Iterable<TimelineRecord> lastRecords = timeline.getLastRecords( maxResults );
-            Iterables.addAll( result, lastRecords );
-        }
-        return Iterables.limit( maxResults, Iterables.reverse( result ) );
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getNextRecords( int maxResults )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-        Schedules schedules = schedulesHandler.getActiveSchedules();
-        for( Schedule schedule : schedules.schedules() )
-        {
-            Timeline timeline = (Timeline) schedule;
-            Iterable<TimelineRecord> lastRecords = timeline.getNextRecords( maxResults );
-            Iterables.addAll( result, lastRecords );
-        }
-        return Iterables.limit( maxResults, result );
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getRecords( ZonedDateTime from, ZonedDateTime to )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-
-        Schedules schedules = schedulesHandler.getActiveSchedules();
-        for( Schedule schedule : schedules.schedules() )
-        {
-            Timeline timeline = (Timeline) schedule;
-            Iterable<TimelineRecord> lastRecords = timeline.getRecords( from, to );
-            Iterables.addAll( result, lastRecords );
-        }
-        return result;
-    }
-
-    @Override
-    public Iterable<TimelineRecord> getRecords( long from, long to )
-    {
-        SortedSet<TimelineRecord> result = new TreeSet<>();
-
-        Schedules schedules = schedulesHandler.getActiveSchedules();
-        for( Schedule schedule : schedules.schedules() )
-        {
-            Timeline timeline = (Timeline) schedule;
-            Iterable<TimelineRecord> lastRecords = timeline.getRecords( from, to );
-            Iterables.addAll( result, lastRecords );
-        }
-        return result;
-    }
-}
diff --git a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/package.html b/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/package.html
deleted file mode 100644
index 1b757d2..0000000
--- a/libraries/scheduler/src/main/java/org/apache/zest/library/scheduler/timeline/package.html
+++ /dev/null
@@ -1,21 +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.
--->
-<html>
-    <body>
-        <h2>Scheduler Timeline.</h2>
-    </body>
-</html>
\ No newline at end of file
diff --git a/libraries/scheduler/src/test/java/org/apache/library/scheduler/SchedulerTest.java b/libraries/scheduler/src/test/java/org/apache/library/scheduler/SchedulerTest.java
new file mode 100644
index 0000000..2832ec1
--- /dev/null
+++ b/libraries/scheduler/src/test/java/org/apache/library/scheduler/SchedulerTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.library.scheduler;
+
+import java.util.Date;
+import org.apache.zest.api.entity.Identity;
+import org.apache.zest.api.unitofwork.UnitOfWork;
+import org.apache.zest.api.usecase.UsecaseBuilder;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.ModuleAssembly;
+import org.apache.zest.entitystore.memory.MemoryEntityStoreService;
+import org.apache.zest.library.scheduler.SchedulerAssembler;
+import org.apache.zest.library.scheduler.SchedulerService;
+import org.apache.zest.library.scheduler.ZestJob;
+import org.apache.zest.library.scheduler.ZestJobDetail;
+import org.apache.zest.spi.uuid.UuidIdentityGeneratorService;
+import org.apache.zest.test.AbstractZestTest;
+import org.apache.zest.valueserialization.jackson.JacksonValueSerializationAssembler;
+import org.apache.zest.valueserialization.orgjson.OrgJsonValueSerializationAssembler;
+import org.junit.Test;
+import org.quartz.CronExpression;
+import org.quartz.CronTrigger;
+import org.quartz.Job;
+import org.quartz.JobDetail;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.quartz.Trigger;
+
+import static org.quartz.CronScheduleBuilder.cronSchedule;
+import static org.quartz.TriggerBuilder.newTrigger;
+
+public class SchedulerTest extends AbstractZestTest
+{
+    @Override
+    public void assemble( ModuleAssembly module )
+        throws AssemblyException
+    {
+        new SchedulerAssembler().assemble( module );
+        module.services( MemoryEntityStoreService.class );
+        module.services( UuidIdentityGeneratorService.class );
+        new JacksonValueSerializationAssembler().assemble( module );
+        module.entities( ZestJob.class ).withMixins( HelloJob.class );
+    }
+
+    @Test
+    public void givenSchedulerWhenScheduleJobExpectJobExecuted()
+        throws Exception
+    {
+        try(UnitOfWork uow = module.newUnitOfWork( UsecaseBuilder.newUsecase( "testing" )) )
+        {
+            SchedulerService underTest = module.findService( SchedulerService.class ).get();
+            ZestJob job = uow.newEntity( ZestJob.class, "job://group1.job1" );
+            ZestJobDetail details = underTest.createJobDetails( job );
+
+            CronTrigger trigger = newTrigger()
+                .withIdentity("trigger1", "group1")
+                .withSchedule(cronSchedule("* * * * * ?"))
+                .build();
+            underTest.getScheduler().scheduleJob( details, trigger );
+            uow.complete();
+
+        }
+        Thread.sleep(15000);
+    }
+
+    public static abstract class HelloJob
+        implements ZestJob
+    {
+        @Override
+        public void execute( JobExecutionContext context )
+            throws JobExecutionException
+        {
+            System.out.println("Hello, Quartz!");
+        }
+    }
+}
diff --git a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/AbstractSchedulerTest.java b/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/AbstractSchedulerTest.java
deleted file mode 100644
index 02d5636..0000000
--- a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/AbstractSchedulerTest.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin.
- *
- * 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.api.entity.EntityBuilder;
-import org.apache.zest.api.entity.IdentityGenerator;
-import org.apache.zest.api.unitofwork.UnitOfWork;
-import org.apache.zest.api.value.ValueSerialization;
-import org.apache.zest.bootstrap.AssemblyException;
-import org.apache.zest.bootstrap.ModuleAssembly;
-import org.apache.zest.bootstrap.ServiceDeclaration;
-import org.apache.zest.entitystore.memory.MemoryEntityStoreService;
-import org.apache.zest.index.rdf.assembly.RdfMemoryStoreAssembler;
-import org.apache.zest.spi.uuid.UuidIdentityGeneratorService;
-import org.apache.zest.test.AbstractZestTest;
-import org.apache.zest.test.EntityTestAssembler;
-import org.apache.zest.valueserialization.orgjson.OrgJsonValueSerializationService;
-
-public abstract class AbstractSchedulerTest
-    extends AbstractZestTest
-{
-    @Override
-    public final void assemble( ModuleAssembly assembly )
-        throws AssemblyException
-    {
-        assembly.entities( FooTask.class );
-
-        assembly.services( MemoryEntityStoreService.class );
-        assembly.services( UuidIdentityGeneratorService.class).withMixins( CountingIdentityGeneratorService.class );
-        assembly.services( OrgJsonValueSerializationService.class ).taggedWith( ValueSerialization.Formats.JSON );
-        new RdfMemoryStoreAssembler().assemble( assembly );
-
-        onAssembly( assembly );
-    }
-
-    protected abstract void onAssembly( ModuleAssembly module )
-        throws AssemblyException;
-
-    protected final FooTask createFooTask( UnitOfWork uow, String name, String input )
-    {
-        EntityBuilder<FooTask> builder = uow.newEntityBuilder( FooTask.class );
-        FooTask task = builder.instance();
-        task.name().set( name );
-        task.input().set( input );
-        return builder.newInstance();
-    }
-
-    public static class CountingIdentityGeneratorService
-        implements IdentityGenerator
-    {
-        int counter = 0;
-
-        @Override
-        public String generate( Class<?> compositeType )
-        {
-            return compositeType.getSimpleName() + ":" + counter++;
-        }
-    }
-}
diff --git a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/Constants.java b/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/Constants.java
deleted file mode 100644
index 55de82f..0000000
--- a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/Constants.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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
- *
- *   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;
-
-// TODO Rename to TestConstants
-public interface Constants
-{
-    String BAR = "bar";
-    String BAZAR = "bazar";
-}
diff --git a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/CronScheduleTest.java b/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/CronScheduleTest.java
deleted file mode 100644
index ad210a2..0000000
--- a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/CronScheduleTest.java
+++ /dev/null
@@ -1,83 +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.EntityBuilder;
-import org.apache.zest.api.unitofwork.UnitOfWork;
-import org.apache.zest.api.value.ValueSerialization;
-import org.apache.zest.bootstrap.AssemblyException;
-import org.apache.zest.bootstrap.ModuleAssembly;
-import org.apache.zest.entitystore.memory.MemoryEntityStoreService;
-import org.apache.zest.spi.uuid.UuidIdentityGeneratorService;
-import org.apache.zest.test.AbstractZestTest;
-import org.apache.zest.valueserialization.orgjson.OrgJsonValueSerializationService;
-import org.joda.time.DateTime;
-import org.junit.Test;
-
-import static org.hamcrest.number.IsCloseTo.closeTo;
-import static org.junit.Assert.assertThat;
-
-public class CronScheduleTest extends AbstractZestTest
-{
-    @Override
-    public void assemble( ModuleAssembly module )
-        throws AssemblyException
-    {
-        module.services( OrgJsonValueSerializationService.class )
-            .taggedWith( ValueSerialization.Formats.JSON );
-        module.services( MemoryEntityStoreService.class );
-        module.services( UuidIdentityGeneratorService.class );
-        module.entities( CronSchedule.class );
-        module.entities( Task.class ).withMixins( DummyTask.class );
-    }
-
-    @Test
-    public void given15SecondCronWhenRequestingNextExpectEvery15Seconds()
-        throws Exception
-    {
-
-        UnitOfWork work = module.newUnitOfWork();
-        EntityBuilder<Task> builder1 = work.newEntityBuilder( Task.class );
-        builder1.instance().name().set( "abc" );
-        Task task = builder1.newInstance();
-        EntityBuilder<CronSchedule> builder = work.newEntityBuilder( CronSchedule.class );
-        builder.instance().start().set( DateTime.now() );
-        builder.instance().task().set( task );
-        builder.instance().cronExpression().set( "*/15 * * * * *" );
-        CronSchedule schedule = builder.newInstance();
-        long runAt = schedule.nextRun( System.currentTimeMillis() );
-        for( int i = 0; i < 1000; i++ )
-        {
-            long nextRun = schedule.nextRun( runAt + 1000 );  // Needs to push forward one second...
-            assertThat( "At:" + i, (double) nextRun, closeTo( runAt + 15000, 50 ) );
-        }
-        work.discard();
-    }
-
-    public static abstract class DummyTask implements Task
-    {
-        @Override
-        public void run()
-        {
-            System.out.println( "Dummy" );
-        }
-    }
-}
diff --git a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/FooTask.java b/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/FooTask.java
deleted file mode 100644
index 63fbee4..0000000
--- a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/FooTask.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin.
- *
- * 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.api.common.Optional;
-import org.apache.zest.api.common.UseDefaults;
-import org.apache.zest.api.entity.Identity;
-import org.apache.zest.api.injection.scope.This;
-import org.apache.zest.api.mixin.Mixins;
-import org.apache.zest.api.property.Property;
-import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation.Propagation.REQUIRES_NEW;
-
-@Mixins( FooTask.Mixin.class )
-public interface FooTask
-    extends Task, Identity
-{
-    Property<String> input();
-
-    @Optional
-    Property<String> output();
-
-    @UseDefaults
-    Property<Integer> runCounter();
-
-    abstract class Mixin
-        implements Task
-    {
-        private static final Logger LOGGER = LoggerFactory.getLogger( FooTask.class );
-
-        @This
-        private FooTask me;
-
-        @Override
-        public void run()
-        {
-            LOGGER.info( "FooTask.run({})", me.input().get() );
-            synchronized( this )
-            {
-                me.runCounter().set( me.runCounter().get() + 1 );
-                LOGGER.info( "Identity: " + me.identity().get() );
-                LOGGER.info( " Counter: " + me.runCounter().get() );
-            }
-            if( me.input().get().equals( Constants.BAZAR ) )
-            {
-                if( me.output().get() == null )
-                {
-                    me.output().set( Constants.BAR );
-                }
-                else
-                {
-                    me.output().set( me.output().get() + Constants.BAR );
-                }
-            }
-        }
-    }
-}
diff --git a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/SchedulerTest.java b/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/SchedulerTest.java
deleted file mode 100644
index 15a356c..0000000
--- a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/SchedulerTest.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2010-2014, Paul Merlin. All Rights Reserved.
- * Copyright (c) 2012, Niclas Hedhman. All Rights Reserved.
- *
- * 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.concurrent.Callable;
-import org.apache.zest.api.common.Visibility;
-import org.apache.zest.api.unitofwork.UnitOfWork;
-import org.apache.zest.api.unitofwork.UnitOfWorkCompletionException;
-import org.apache.zest.api.usecase.Usecase;
-import org.apache.zest.api.usecase.UsecaseBuilder;
-import org.apache.zest.bootstrap.AssemblyException;
-import org.apache.zest.bootstrap.ModuleAssembly;
-import org.apache.zest.library.scheduler.bootstrap.SchedulerAssembler;
-import org.apache.zest.library.scheduler.timeline.Timeline;
-import org.joda.time.DateTime;
-import org.joda.time.Interval;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static com.jayway.awaitility.Awaitility.await;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.apache.zest.functional.Iterables.count;
-import static org.apache.zest.library.scheduler.Constants.BAR;
-import static org.apache.zest.library.scheduler.Constants.BAZAR;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertThat;
-
-public class SchedulerTest
-    extends AbstractSchedulerTest
-{
-    private static final Logger LOGGER = LoggerFactory.getLogger( SchedulerTest.class );
-
-    @Override
-    protected void onAssembly( ModuleAssembly testAssembly )
-        throws AssemblyException
-    {
-        @SuppressWarnings( "UnnecessaryLocalVariable" )
-        ModuleAssembly moduleAssembly = testAssembly;
-
-        @SuppressWarnings( "UnnecessaryLocalVariable" )
-        ModuleAssembly configModuleAssembly = testAssembly;
-
-        // START SNIPPET: assembly
-        new SchedulerAssembler().visibleIn( Visibility.application )
-            .withConfig( configModuleAssembly, Visibility.layer )
-            .withTimeline()
-            .assemble( moduleAssembly );
-        // END SNIPPET: assembly
-    }
-
-    @Test
-    public void testTaskWithoutScheduling()
-        throws UnitOfWorkCompletionException
-    {
-        Usecase usecase = UsecaseBuilder.newUsecase( "testTask" );
-        String taskId;
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            FooTask task = createFooTask( uow, "TestTask", BAZAR );
-            taskId = task.identity().get();
-            task.run();
-            uow.complete();
-        }
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            FooTask task = uow.get( FooTask.class, taskId );
-            assertThat( task.runCounter().get(), equalTo( 1 ) );
-            assertThat( task.output().get(), equalTo( BAR ) );
-        }
-    }
-
-    @Test
-    public void testMinutely()
-        throws UnitOfWorkCompletionException
-    {
-        Usecase usecase = UsecaseBuilder.newUsecase( "TestMinutely" );
-        DateTime start = new DateTime();
-        String taskIdentity;
-        long sleepMillis;
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            Scheduler scheduler = module.findService( Scheduler.class ).get();
-
-            FooTask task = createFooTask( uow, usecase.name(), BAZAR );
-            taskIdentity = task.identity().get();
-
-            DateTime expectedRun = start.withMillisOfSecond( 0 ).withSecondOfMinute( 0 ).plusMinutes( 1 );
-            scheduler.scheduleCron( task, "@minutely" );
-
-            uow.complete();
-
-            sleepMillis = new Interval( start, expectedRun ).toDurationMillis();
-            LOGGER.info( "Task scheduled on {} to be run at {}", start.getMillis(), expectedRun.getMillis() );
-        }
-
-        await( usecase.name() )
-            .atMost( sleepMillis + 5000, MILLISECONDS )
-            .until( taskOutput( taskIdentity ), equalTo( 1 ) );
-
-        //noinspection unused
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            Timeline timeline = module.findService( Timeline.class ).get();
-            DateTime now = new DateTime();
-
-            // Queries returning past records
-            assertThat( count( timeline.getLastRecords( 5 ) ),
-                        is( 2L ) );
-            assertThat( count( timeline.getRecords( start.getMillis(), now.getMillis() ) ),
-                        is( 2L ) );
-
-            // Queries returning future records
-            assertThat( count( timeline.getNextRecords( 4 ) ),
-                        is( 4L ) );
-            assertThat( count( timeline.getRecords( now.getMillis() + 100, now.plusMinutes( 5 ).getMillis() ) ),
-                        is( 5L ) );
-
-            // Queries returning mixed past and future records
-            assertThat( count( timeline.getRecords( start.getMillis(), now.plusMinutes( 5 ).getMillis() ) ),
-                        is( 7L ) );
-        }
-    }
-
-    @Test
-    public void testOnce()
-        throws UnitOfWorkCompletionException, InterruptedException
-    {
-        System.setProperty( "zest.entity.print.state", Boolean.TRUE.toString() );
-        final Usecase usecase = UsecaseBuilder.newUsecase( "TestOnce" );
-        final String taskIdentity;
-        Scheduler scheduler = module.findService( Scheduler.class ).get();
-
-        Schedule schedule1;
-        Schedule schedule2;
-        Schedule schedule3;
-        Schedule schedule4;
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            FooTask task = createFooTask( uow, usecase.name(), BAZAR );
-            taskIdentity = task.identity().get();
-
-            schedule1 = scheduler.scheduleOnce( task, 1 );
-            schedule2 = scheduler.scheduleOnce( task, 2 );
-            schedule3 = scheduler.scheduleOnce( task, 3 );
-            schedule4 = scheduler.scheduleOnce( task, 4 );
-
-            uow.complete();
-        }
-        await( usecase.name() )
-            .atMost( 6, SECONDS )
-            .until( taskOutput( taskIdentity ), equalTo( 4 ) );
-
-        try( UnitOfWork uow = module.newUnitOfWork( usecase ) )
-        {
-            schedule1 = uow.get( schedule1 );
-            schedule2 = uow.get( schedule2 );
-            schedule3 = uow.get( schedule3 );
-            schedule4 = uow.get( schedule4 );
-            assertThat(schedule1.cancelled().get(), equalTo( false ));
-            assertThat(schedule2.cancelled().get(), equalTo( false ));
-            assertThat(schedule3.cancelled().get(), equalTo( false ));
-            assertThat(schedule4.cancelled().get(), equalTo( false ));
-            assertThat(schedule1.done().get(), equalTo( true ));
-            assertThat(schedule2.done().get(), equalTo( true ));
-            assertThat(schedule3.done().get(), equalTo( true ));
-            assertThat(schedule4.done().get(), equalTo( true ));
-            assertThat(schedule1.running().get(), equalTo( false ));
-            assertThat(schedule2.running().get(), equalTo( false ));
-            assertThat(schedule3.running().get(), equalTo( false ));
-            assertThat(schedule4.running().get(), equalTo( false ));
-        }
-    }
-
-    private Callable<Integer> taskOutput( final String taskIdentity )
-    {
-        return () -> {
-            try( UnitOfWork uow = module.newUnitOfWork() )
-            {
-                FooTask task = uow.get( FooTask.class, taskIdentity );
-                Integer count = task.runCounter().get();
-                uow.discard();
-                return count;
-            }
-        };
-    }
-}
diff --git a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/docsupport/SchedulerDocs.java b/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/docsupport/SchedulerDocs.java
deleted file mode 100644
index 998d36b..0000000
--- a/libraries/scheduler/src/test/java/org/apache/zest/library/scheduler/docsupport/SchedulerDocs.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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
- *
- *   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.docsupport;
-
-import org.apache.zest.api.association.Association;
-import org.apache.zest.api.injection.scope.Service;
-import org.apache.zest.api.injection.scope.This;
-import org.apache.zest.api.property.Property;
-import org.apache.zest.api.unitofwork.concern.UnitOfWorkDiscardOn;
-import org.apache.zest.api.unitofwork.concern.UnitOfWorkPropagation;
-import org.apache.zest.api.unitofwork.concern.UnitOfWorkRetry;
-import org.apache.zest.library.scheduler.Scheduler;
-import org.apache.zest.library.scheduler.Task;
-import org.apache.zest.library.scheduler.Schedule;
-import org.apache.zest.library.scheduler.timeline.Timeline;
-
-public class SchedulerDocs
-{
-
-    // START SNIPPET: timeline
-    @Service
-    Timeline timeline;
-// END SNIPPET: timeline
-
-    // START SNIPPET: 2
-    @Service
-    Scheduler scheduler;
-
-    public void method()
-    {
-        MyTaskEntity myTask = todo();
-        Schedule schedule = scheduler.scheduleOnce( myTask, 10 );
-        // myTask will be run in 10 seconds from now
-    }
-
-    // END SNIPPET: 2
-    MyTaskEntity todo()
-    {
-        return null;
-    }
-
-    // START SNIPPET: 1
-    interface MyTaskEntity extends Task
-    {
-        Property<String> myTaskState();
-
-        Association<AnotherEntity> anotherEntity();
-    }
-
-    class MyTaskMixin implements Runnable
-    {
-        @This
-        MyTaskEntity me;
-
-        @Override
-        public void run()
-        {
-            me.myTaskState().set( me.anotherEntity().get().doSomeStuff( me.myTaskState().get() ) );
-        }
-    }
-
-    // END SNIPPET: 1
-    interface AnotherEntity
-    {
-        String doSomeStuff( String p );
-    }
-
-    public class MyTask implements Runnable
-    {
-
-        // START SNIPPET: strategy
-        @Override
-        @UnitOfWorkRetry( retries = 3 )
-        @UnitOfWorkDiscardOn( IllegalArgumentException.class )
-        @UnitOfWorkPropagation( value = UnitOfWorkPropagation.Propagation.REQUIRES_NEW, usecase = "Load Data" )
-        public void run()
-        {
-            // END SNIPPET: strategy
-
-        }
-    }
-}
\ No newline at end of file
diff --git a/libraries/scheduler/src/test/resources/logback-test.xml b/libraries/scheduler/src/test/resources/logback-test.xml
deleted file mode 100644
index 256127e..0000000
--- a/libraries/scheduler/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-<configuration>
-
-    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
-        <layout class="ch.qos.logback.classic.PatternLayout">
-            <Pattern>@%-10thread %-5level %logger{20} - %msg%n</Pattern>
-        </layout>
-    </appender>
-
-    <root level="info">
-        <appender-ref ref="stdout" />
-    </root>
-
-    <logger name="org.apache.zest.library.scheduler" level="trace"/>
-
-</configuration>
\ No newline at end of file