RepoPilotOpen in app →

quartz-scheduler/quartz

Code for Quartz Scheduler

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 3d ago
  • 17 active contributors
  • Distributed ownership (top contributor 42% of recent commits)
Show all 6 evidence items →
  • Apache-2.0 licensed
  • Tests present
  • No CI workflows detected

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/quartz-scheduler/quartz)](https://repopilot.app/r/quartz-scheduler/quartz)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/quartz-scheduler/quartz on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: quartz-scheduler/quartz

Generated by RepoPilot · 2026-05-09 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/quartz-scheduler/quartz shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 3d ago
  • 17 active contributors
  • Distributed ownership (top contributor 42% of recent commits)
  • Apache-2.0 licensed
  • Tests present
  • ⚠ No CI workflows detected

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live quartz-scheduler/quartz repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/quartz-scheduler/quartz.

What it runs against: a local clone of quartz-scheduler/quartz — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in quartz-scheduler/quartz | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 33 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>quartz-scheduler/quartz</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of quartz-scheduler/quartz. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/quartz-scheduler/quartz.git
#   cd quartz
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of quartz-scheduler/quartz and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "quartz-scheduler/quartz(\\.git)?\\b" \\
  && ok "origin remote is quartz-scheduler/quartz" \\
  || miss "origin remote is not quartz-scheduler/quartz (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "build.gradle" \\
  && ok "build.gradle" \\
  || miss "missing critical file: build.gradle"
test -f "CONTRIBUTING.md" \\
  && ok "CONTRIBUTING.md" \\
  || miss "missing critical file: CONTRIBUTING.md"
test -f "examples/examples_guide.txt" \\
  && ok "examples/examples_guide.txt" \\
  || miss "missing critical file: examples/examples_guide.txt"
test -f ".github/pull_request_template.md" \\
  && ok ".github/pull_request_template.md" \\
  || miss "missing critical file: .github/pull_request_template.md"
test -f "checkstyle/src/main/resources/checkstyle.xml" \\
  && ok "checkstyle/src/main/resources/checkstyle.xml" \\
  || miss "missing critical file: checkstyle/src/main/resources/checkstyle.xml"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~3d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/quartz-scheduler/quartz"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Quartz Scheduler is a richly featured, open-source job scheduling library for Java that enables time-based and cron-triggered task execution within applications. It provides persistent job storage, clustering support, and remote job invocation—allowing developers to schedule tasks from microseconds to years in the future with automatic retry and recovery capabilities. Multi-module Gradle build with core scheduling engine in the main source tree (org.quartz package), extensive examples in /examples (15 example classes covering triggers, clustering, recovery, and plugins), and checkstyle enforcement in /checkstyle. Documentation lives in /docs/index.md. The architecture separates concerns into job definitions, triggers, and a persistent scheduler backend.

👥Who it's for

Java backend developers and DevOps engineers building enterprise applications that need robust, fault-tolerant job scheduling. Users range from small stand-alone applications to large e-commerce systems requiring distributed task coordination and job persistence.

🌱Maturity & risk

Quartz is production-ready and actively maintained. It has a long history (visible in the mature build.gradle setup with Maven publishing, code signing for releases, and strict checkstyle enforcement), Azure Pipelines CI configured, and examples covering 15+ distinct use cases. The codebase is large (~2.7M lines of Java) with formal release procedures (Gradle Nexus publishing plugin, GPG signing for non-SNAPSHOT versions).

Low risk for a mature library, but be aware: the project targets Java 11+ (toolchain requirement in build.gradle), which may affect legacy deployments. No visible indication of breaking changes or aggressive deprecation patterns from the file list. Dependencies are managed through mavenCentral() repositories. The project has formal Dependabot configuration (.github/dependabot.yml) suggesting active dependency maintenance.

Active areas of work

The repo is actively maintained with CI/CD via Azure Pipelines (azure-pipelines.yml configured). Stale issue management is configured (.github/stale.yml), indicating triage discipline. Recent onboarding infrastructure (pull_request_template.md, CONTRIBUTING.md) suggests the project is welcoming new contributors.

🚀Get running

git clone https://github.com/quartz-scheduler/quartz.git
cd quartz
./gradlew build
./gradlew examples:run

Daily commands:

./gradlew build                    # Build all modules
./gradlew examples:run             # Run example scheduler
./gradlew test                     # Run test suite

🗺️Map of the codebase

  • build.gradle — Root build configuration defining project structure, dependencies, publishing, and Java toolchain; all contributors must understand the build system.
  • CONTRIBUTING.md — Contribution guidelines and development workflow; essential for anyone submitting changes to the project.
  • examples/examples_guide.txt — Guide to 15 runnable examples demonstrating core Quartz scheduling patterns; reference for understanding API usage.
  • .github/pull_request_template.md — PR submission checklist and standards; enforces consistency in code review and integration process.
  • checkstyle/src/main/resources/checkstyle.xml — Code style enforcement rules applied to all contributions; must be followed to pass CI checks.
  • gradle.properties — Version and global Gradle configuration properties; controls build behavior and release versioning.
  • azure-pipelines.yml — CI/CD pipeline definition; shows how code is tested, built, and deployed across branches.

🛠️How to make changes

Add a New Job Type

  1. Create a new Java class implementing Job interface in quartz-jobs/src/main/java/org/quartz/jobs/ (quartz-jobs/src/main/java/org/quartz/jobs/NoOpJob.java)
  2. Implement execute(JobExecutionContext) method with your scheduling logic (quartz-jobs/src/main/java/org/quartz/jobs/DirectoryScanJob.java)
  3. Create a new example class in examples/src/main/java/org/quartz/examples/exampleNN/ to demonstrate usage (examples/src/main/java/org/quartz/examples/example1/SimpleExample.java)
  4. Add properties file in examples/src/main/resources/org/quartz/examples/exampleNN/quartz.properties for job configuration (examples/src/main/resources/org/quartz/examples/example10/quartz.properties)
  5. Update examples/examples_guide.txt with description of your new example (examples/examples_guide.txt)

Configure Custom Scheduler Instance

  1. Create properties file following pattern: org/quartz/examples/exampleNN/quartz.properties (examples/src/main/resources/org/quartz/examples/example10/quartz.properties)
  2. Set org.quartz.jobStore.class to RAMJobStore, JDBCJobStore, or custom implementation (examples/src/main/resources/org/quartz/examples/example13/instance1.properties)
  3. Configure thread pool size with org.quartz.threadPool.threadCount (examples/src/main/resources/org/quartz/examples/example12/server.properties)
  4. For clustering, set org.quartz.scheduler.instanceName and configure persistence (examples/src/main/resources/org/quartz/examples/example13/instance1.properties)
  5. Load properties in code via SchedulerFactory.getScheduler() or direct Properties initialization (examples/src/main/java/org/quartz/examples/example1/SimpleExample.java)

Add Job Listener or Scheduler Listener

  1. Create listener class extending JobListener or TriggerListener in examples/src/main/java/org/quartz/examples/exampleNN/ (examples/src/main/java/org/quartz/examples/example9/Job1Listener.java)
  2. Implement required callback methods (jobToBeExecuted, jobWasExecuted, jobExecutionVetoed) (examples/src/main/java/org/quartz/examples/example9/Job1Listener.java)
  3. Register listener with scheduler in example code via scheduler.getListenerManager().addJobListener() (examples/src/main/java/org/quartz/examples/example9/ListenerExample.java)
  4. Create job that will be monitored, and verify listener callbacks are triggered (examples/src/main/java/org/quartz/examples/example9/SimpleJob1.java)

🔧Why these technologies

  • Gradle with Java 11+ toolchain — Modern JVM build system with consistent toolchain management across contributors; supports multi-module projects (core, examples, jobs).
  • Checkstyle for code style enforcement — Automated enforcement of code standards (spacing, naming, complexity) to maintain consistency across distributed contributions.
  • Azure Pipelines CI/CD — Cloud-based automated testing and release pipeline ensuring code quality and enabling continuous deployment to Maven Central.
  • Log4j for logging — Industry-standard logging library for job execution tracing and runtime diagnostics.
  • Maven Central publishing via Gradle Nexus plugin — Publishes library artifacts to central repository with automatic staging repo management for releases.

⚖️Trade-offs already made

  • Support both RAMJobStore and JDBCJobStore implementations

    • Why: In-memory store provides simple setup for development; JDBC enables clustering and persistent scheduling for production.
    • Consequence: More complex codebase with abstraction layer for persistence; developers must understand store trade-offs.
  • Job execution via thread pool rather than event-driven callbacks

    • Why: Thread pool model provides predictable resource usage and isolation between job executions.
    • Consequence: Requires thread pool tuning; high-frequency jobs may compete for limited threads.
  • Property file configuration rather than fluent builders only

    • Why: Properties files enable deployment-time configuration without recompilation; standard for operational use.
    • Consequence: Configuration scattered across multiple files; examples require multiple resource files.
  • Support for distributed clustering via shared JobStore

    • Why: Allows horizontal scaling and job recovery on node failure without custom coordination logic.
    • Consequence: Requires shared persistence layer (database or shared filesystem); introduces clock synchronization requirements across nodes.

🚫Non-goals (don't propose these)

  • Does not provide built-in authentication or authorization — deployments must add security layers externally
  • Not intended for hard real-time scheduling — subject to JVM garbage collection and OS scheduling delays
  • Does not include web UI or dashboard — requires external tools for job monitoring and management
  • Not a database — relies on external database (JDBC) or RAM for persistence; does not replace data warehousing
  • Does not handle job code

🪤Traps & gotchas

Build requires Java 11+ (enforced via Gradle toolchain plugin); older Java versions will fail. Checkstyle is strict (header.txt, suppressions.xml must be respected)—failing style checks block merges. Database schema changes require corresponding TSQL updates in core/src/main/resources/sql. The examples submodule has its own build.gradle; ensure you build from root (./gradlew) to get consistent versions. Dependabot is active, so breaking dependency updates may arrive.

🏗️Architecture

💡Concepts to learn

  • Cron expressions — Quartz relies on cron syntax to define recurring schedules; understanding cron is essential for configuring CronTrigger (visible in example3/CronTriggerExample.java)
  • Job Store persistence — Quartz supports both in-memory and JDBC-based persistent job storage; choosing the right backend affects reliability and clustering capability (visible in core TSQL files and example13 clustering)
  • Stateful vs. Stateless jobs — Quartz distinguishes between @DisallowConcurrentExecution (stateful) and regular jobs; this affects concurrency and persistence semantics (visible in example13/SimpleRecoveryStatefulJob.java)
  • Trigger misfires and recovery — When the scheduler is down, triggers may misfire; Quartz provides configurable misfire policies and recovery strategies (demonstrated in example13/ClusterExample.java with SimpleRecoveryJob)
  • Clustering and distributed scheduling — Quartz can run on multiple nodes sharing a single JobStore database, enabling fault tolerance and load distribution (example13 demonstrates this with JDBC-based coordination)
  • Job priority and execution order — Quartz supports priority-based scheduling to ensure critical jobs execute first (example14/PriorityExample.java demonstrates this with TriggerEchoJob)
  • Remote job invocation (RMI) — Quartz supports Remote Method Invocation for managing jobs across network boundaries (example12 shows RemoteClientExample and RemoteServerExample patterns)
  • spring-projects/spring-boot — Spring Boot provides automatic Quartz configuration via spring-boot-starter-quartz, making Quartz the standard scheduler for Spring applications
  • jobrunr/jobrunr — Modern alternative to Quartz for Java job scheduling with simpler API and automatic retry/failover, appealing to developers seeking less configuration
  • elastic/elasticsearch — Common integration target for Quartz; users often index job execution logs and metrics into Elasticsearch for monitoring
  • quartz-scheduler/quartz-examples — Dedicated examples repository extending the 15 built-in examples with community contributions and advanced patterns

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for example modules (example1-example15)

The examples directory contains 15 distinct example modules demonstrating different Quartz features (SimpleTrigger, CronTrigger, StatefulJobs, Listeners, Clustering, etc.), but there are no corresponding unit tests in examples/src/test/. New contributors could create integration tests that verify each example runs correctly, ensuring the examples stay synchronized with API changes and serve as reliable learning resources.

  • [ ] Create examples/src/test/java/org/quartz/examples directory structure
  • [ ] Add unit tests for example1-example5 (basic trigger and job concepts)
  • [ ] Add unit tests for example6-example10 (exception handling, interruption, calendars, listeners)
  • [ ] Add unit tests for example11-example15 (load testing, clustering, priority, native jobs)
  • [ ] Update examples/build.gradle to include test dependencies (JUnit 5, Mockito)

Implement GitHub Actions workflow for automated code quality checks

The repo currently uses Azure Pipelines (azure-pipelines.yml) for CI/CD, but relies on deprecated Dependabot configuration (.github/dependabot.yml) and lacks a modern GitHub Actions workflow. Adding a GitHub Actions workflow would provide faster feedback on PRs, better integration with the GitHub UI, and could run checkstyle validation (checkstyle/src/main/resources/checkstyle.xml) and test coverage reports automatically on every push/PR.

  • [ ] Create .github/workflows/ci.yml with Java 11+ matrix testing
  • [ ] Configure checkstyle validation step using checkstyle/src/main/resources/checkstyle.xml
  • [ ] Add gradle build task with test execution
  • [ ] Set up code coverage reporting (jacoco or similar)
  • [ ] Add conditional steps for snapshot vs release builds based on version detection

Create API documentation for core scheduler interfaces in docs/

The docs/index.md exists but the file structure suggests minimal inline documentation. The codebase has complex APIs (Scheduler, Trigger, Job, JobDetail, Calendar interfaces visible through examples), but there's no structured API reference guide. Contributing a docs/api-reference.md or docs/core-concepts.md would help new users understand the scheduler's architecture, particularly around the relationship between Jobs, Triggers, and the Scheduler itself.

  • [ ] Create docs/api-reference.md documenting core interfaces (Scheduler, Job, Trigger, JobDetail, Calendar)
  • [ ] Add docs/core-concepts.md explaining job execution lifecycle and key terminology
  • [ ] Include code examples from examples/src/main/java for each concept
  • [ ] Document the difference between SimpleTrigger vs CronTrigger with real examples
  • [ ] Add troubleshooting section for common misfire and clustering issues

🌿Good first issues

  • Add missing integration tests for the RemoteClientExample (example12) and RemoteServerExample—currently no visible test coverage in examples/src/test for remote job invocation
  • Expand docs/index.md with a 'Configuration Reference' section documenting all quartz.properties settings used by examples (currently inferred only from code)
  • Add a new example (example16) demonstrating graceful scheduler shutdown with in-flight job cancellation, bridging the gap between example15 (NativeJob) and production concerns

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 9294eac — Merge pull request #1429 from mors741/patch-1 (jhouserizer)
  • 4812ed2 — Merge pull request #1446 from jrzabott/main (jhouserizer)
  • 328cab9 — Merge pull request #1442 from quartz-scheduler/dependabot/gradle/main/org.mariadb.jdbc-mariadb-java-client-3.5.7 (jhouserizer)
  • ade2324 — fix-misleading-javadoc-in-cronsexpression-month-indexing (jrzabott)
  • 747c10a — build(deps): bump org.mariadb.jdbc:mariadb-java-client (dependabot[bot])
  • c8fd3fc — Actualize the documentation link in readme.md (mors741)
  • 4406ab0 — Merge pull request #1426 from mprins/patch-1 (jhouserizer)
  • a73dab0 — Merge pull request #1424 from jhouserizer/fix1420 (jhouserizer)
  • ed6fb43 — Fix interval calculation for hourly triggers (mprins)
  • 8853377 — fix #1420, issue with nearest weekday expressions (jhouserizer)

🔒Security observations

The Quartz Scheduler project demonstrates reasonable security practices with Maven Central repository usage, GPG signing for releases, and Java 11 toolchain specification. However, there are areas for improvement: (1) Dependency locking is not implemented, exposing the project to supply chain attacks; (2) Build signing configuration could be more explicit; (3) Legacy HTTP URLs should be migrated to HTTPS; (4) Java 11 is aging and should be upgraded to a newer LTS version; (5) No evidence of automated dependency vulnerability scanning in the build pipeline. The project should implement these recommendations to strengthen its security posture, particularly around supply chain security and dependency management.

  • Medium · Gradle Build Configuration Exposed to Supply Chain Attacks — build.gradle. The build.gradle file uses mavenCentral() repository without explicit version pinning or dependency locking. This could potentially expose the project to supply chain attacks if compromised artifacts are published to Maven Central. Additionally, the Gradle Nexus Publish Plugin configuration lacks checksum verification enforcement. Fix: Implement Gradle dependency locking with 'gradle.lockfile' to pin all transitive dependencies. Add repository mirroring or use a private artifact repository proxy. Enable checksum verification and consider using the Gradle verify-gradle-wrapper task.
  • Medium · Signing Configuration May Allow Unsigned Releases — build.gradle (signing block). The signing configuration in the POM only requires signing for non-SNAPSHOT versions. If a release is accidentally published as a SNAPSHOT or if version detection fails, unsigned artifacts could be distributed without verification. Fix: Make signing mandatory for all releases explicitly. Add pre-release verification steps to the CI/CD pipeline (azure-pipelines.yml) to ensure signatures are generated and verified before publishing.
  • Low · Missing Security Headers in Git Repository Configuration — build.gradle (pom block - license and scm URLs). The repository configuration in POM/gradle files uses 'http://' for Apache License URL and 'git://' protocol for SCM connection. While the main repository URL uses HTTPS, the license URL should also use HTTPS to prevent potential MITM attacks. Fix: Update the Apache License URL from 'http://www.apache.org/licenses/LICENSE-2.0.txt' to 'https://www.apache.org/licenses/LICENSE-2.0.txt'. Ensure SCM connection uses 'https://' protocol: 'scm:git:https://github.com:quartz-scheduler/quartz.git'.
  • Low · Java Toolchain Version May Be Outdated — build.gradle (toolchain configuration). The project specifies Java 11 as the minimum language version. Java 11 is an older LTS release and may contain security vulnerabilities that have been patched in newer versions (Java 17 LTS or Java 21 LTS). Fix: Consider upgrading to Java 17 LTS or Java 21 LTS, which have more recent security patches. If Java 11 compatibility is required, ensure the project follows an aggressive patching schedule and uses the latest Java 11 update available.
  • Low · Azure Pipelines Configuration Not Reviewed — azure-pipelines.yml. The CI/CD pipeline configuration file (azure-pipelines.yml) is referenced but not provided for review. This could potentially contain security misconfigurations, exposed secrets, or insecure build processes. Fix: Review the azure-pipelines.yml file for: (1) Hardcoded credentials or secrets (use Azure Key Vault), (2) Dependency audit steps, (3) Code signing verification, (4) Artifact signing before publication, (5) SAST scanning integration.
  • Low · No Evidence of Dependency Vulnerability Scanning — build.gradle (root configuration). The build configuration does not show integration with dependency scanning tools (OWASP Dependency Check, Snyk, etc.) to identify known vulnerabilities in transitive dependencies. Fix: Add OWASP Dependency-Check Gradle plugin or equivalent scanning tool. Configure automated scanning in the CI/CD pipeline to fail builds when high-severity vulnerabilities are detected in dependencies.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · quartz-scheduler/quartz — RepoPilot