Skip to content

Commit

Permalink
Consolidate scheduler extension - part 1
Browse files Browse the repository at this point in the history
- introduce lightweight scheduler implementation in quarkus-scheduler
- introduce quarkus-quartz based on quarkus-scheduler build steps and API
- remove Scheduler#startTimer() method
- add proper intergration test
  • Loading branch information
mkouba committed Nov 15, 2019
1 parent 83eb6ae commit b1feebb
Show file tree
Hide file tree
Showing 42 changed files with 1,368 additions and 405 deletions.
5 changes: 5 additions & 0 deletions bom/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,11 @@
<artifactId>quarkus-scheduler-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-quartz-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-reactive-messaging-deployment</artifactId>
Expand Down
11 changes: 11 additions & 0 deletions bom/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
<httpclient.version>4.5.9</httpclient.version>
<httpcore.version>4.4.11</httpcore.version>
<httpasync.version>4.1.4</httpasync.version>
<cronutils.version>9.0.1</cronutils.version>
<quartz.version>2.3.1</quartz.version>
<h2.version>1.4.197</h2.version> <!-- keep 1.4.197 as newer versions have severe regressions -->
<postgresql-jdbc.version>42.2.8</postgresql-jdbc.version>
Expand Down Expand Up @@ -596,6 +597,11 @@
<artifactId>quarkus-scheduler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-quartz</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-di</artifactId>
Expand Down Expand Up @@ -1995,6 +2001,11 @@
</exclusions>
</dependency>

<dependency>
<groupId>com.cronutils</groupId>
<artifactId>cron-utils</artifactId>
<version>${cronutils.version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public final class Capabilities extends SimpleBuildItem {
public static final String SECURITY = "io.quarkus.security";
public static final String SECURITY_ELYTRON_OAUTH2 = "io.quarkus.elytron.security.oauth2";
public static final String SECURITY_ELYTRON_JDBC = "io.quarkus.elytron.security.jdbc";
public static final String QUARTZ = "io.quarkus.quartz";

private final Set<String> capabilities;

Expand Down
1 change: 1 addition & 0 deletions extensions/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<!-- Plumbing -->
<module>arc</module>
<module>scheduler</module>
<module>quartz</module>

<!-- Formats -->
<module>jackson</module>
Expand Down
58 changes: 58 additions & 0 deletions extensions/quartz/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>quarkus-quartz-parent</artifactId>
<groupId>io.quarkus</groupId>
<version>999-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>quarkus-quartz-deployment</artifactId>
<name>Quarkus - Scheduler Quartz - Deployment</name>

<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-core-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-scheduler-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-quartz</artifactId>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package io.quarkus.quartz.deployment;

import static io.quarkus.deployment.annotations.ExecutionTime.RUNTIME_INIT;

import java.util.ArrayList;
import java.util.List;

import org.quartz.simpl.CascadingClassLoadHelper;
import org.quartz.simpl.RAMJobStore;
import org.quartz.simpl.SimpleThreadPool;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.BeanContainerBuildItem;
import io.quarkus.deployment.Capabilities;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.CapabilityBuildItem;
import io.quarkus.deployment.builditem.ServiceStartBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.logging.LogCleanupFilterBuildItem;
import io.quarkus.quartz.runtime.QuartzRecorder;
import io.quarkus.quartz.runtime.QuartzRuntimeConfig;
import io.quarkus.quartz.runtime.QuartzScheduler;
import io.quarkus.quartz.runtime.QuartzSupport;

/**
* @author Martin Kouba
*/
public class QuartzProcessor {

@BuildStep
CapabilityBuildItem capability() {
return new CapabilityBuildItem(Capabilities.QUARTZ);
}

@BuildStep
AdditionalBeanBuildItem beans() {
return new AdditionalBeanBuildItem(QuartzScheduler.class, QuartzSupport.class);
}

@BuildStep
List<ReflectiveClassBuildItem> reflectiveClasses() {
List<ReflectiveClassBuildItem> reflectiveClasses = new ArrayList<>();
reflectiveClasses.add(new ReflectiveClassBuildItem(false, false, CascadingClassLoadHelper.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, SimpleThreadPool.class.getName()));
reflectiveClasses.add(new ReflectiveClassBuildItem(true, false, RAMJobStore.class.getName()));
return reflectiveClasses;
}

@BuildStep
public void logCleanup(BuildProducer<LogCleanupFilterBuildItem> logCleanupFilter) {
logCleanupFilter.produce(new LogCleanupFilterBuildItem("org.quartz.impl.StdSchedulerFactory",
"Quartz scheduler version:",
// no need to log if it's the default
"Using default implementation for",
"Quartz scheduler 'DefaultQuartzScheduler'"));

logCleanupFilter.produce(new LogCleanupFilterBuildItem("org.quartz.core.QuartzScheduler",
"Quartz Scheduler v",
"JobFactory set to:",
"Scheduler meta-data:",
// no need to log if it's the default
"Scheduler DefaultQuartzScheduler"));

logCleanupFilter.produce(new LogCleanupFilterBuildItem("org.quartz.simpl.RAMJobStore",
"RAMJobStore initialized."));

logCleanupFilter.produce(new LogCleanupFilterBuildItem("org.quartz.core.SchedulerSignalerImpl",
"Initialized Scheduler Signaller of type"));
}

@BuildStep
@Record(RUNTIME_INIT)
public void build(QuartzRuntimeConfig runtimeConfig, QuartzRecorder recorder, BeanContainerBuildItem beanContainer,
BuildProducer<ServiceStartBuildItem> serviceStart) {
recorder.initialize(runtimeConfig, beanContainer.getValue());
// Make sure that StartupEvent is fired after the init
serviceStart.produce(new ServiceStartBuildItem("quartz"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.quartz.test;

import javax.enterprise.inject.spi.DeploymentException;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.scheduler.Scheduled;
import io.quarkus.test.QuarkusUnitTest;

public class InvalidCronExpressionTest {

@RegisterExtension
static final QuarkusUnitTest test = new QuarkusUnitTest()
.setExpectedException(DeploymentException.class)
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(InvalidBean.class));

@Test
public void test() throws InterruptedException {
}

static class InvalidBean {

@Scheduled(cron = "0 0 0 ????")
void wrong() {
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.quartz.test;

import javax.enterprise.inject.spi.DeploymentException;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.scheduler.Scheduled;
import io.quarkus.test.QuarkusUnitTest;

public class InvalidEveryExpressionTest {

@RegisterExtension
static final QuarkusUnitTest test = new QuarkusUnitTest()
.setExpectedException(DeploymentException.class)
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(InvalidEveryExpressionTest.InvalidBean.class));

@Test
public void test() throws InterruptedException {
}

static class InvalidBean {

@Scheduled(every = "call me every other day")
void wrong() {
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.quartz.test;

import java.util.NoSuchElementException;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.scheduler.Scheduled;
import io.quarkus.test.QuarkusUnitTest;

public class MissingConfigCronExpressionTest {

@RegisterExtension
static final QuarkusUnitTest test = new QuarkusUnitTest()
.setExpectedException(NoSuchElementException.class)
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(MissingConfigCronExpressionTest.InvalidBean.class));

@Test
public void test() {
}

static class InvalidBean {

@Scheduled(cron = "{my.cron}")
void wrong() {
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.quartz.test;

import javax.enterprise.inject.spi.DeploymentException;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.scheduler.Scheduled;
import io.quarkus.test.QuarkusUnitTest;

public class NoExpressionTest {

@RegisterExtension
static final QuarkusUnitTest test = new QuarkusUnitTest()
.setExpectedException(DeploymentException.class)
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(InvalidBean.class));

@Test
public void test() throws InterruptedException {
}

static class InvalidBean {

@Scheduled
void wrong() {
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package io.quarkus.quartz.test;

import java.util.concurrent.CountDownLatch;

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;

import io.quarkus.scheduler.Scheduled;

public class RequestContextJobs {

static final CountDownLatch LATCH = new CountDownLatch(1);

@Inject
RequestFoo foo;

@Scheduled(every = "1s")
void checkEverySecond() {
foo.getName();
LATCH.countDown();
}

@RequestScoped
static class RequestFoo {

private String name;

@PostConstruct
void init() {
name = "oof";
}

public String getName() {
return name;
}

}

}
Loading

0 comments on commit b1feebb

Please sign in to comment.