#1207: AbstractJob.kt
projectforge-business/src/main/kotlin/org/projectforge/framework/jobs/AbstractJob.kt Job Framework, projectforge-business/src/main/kotlin/org/projectforge/framework/jobs/AbstractJob.kt 429 lines · 280 code · 93 comments · 56 blank
Abstract base class for background jobs in ProjectForge. Supports queuing strategies (none, per-queue, per-queue-and-user, refuse), optional timeout (default 120s), progress tracking (total/processed count), and cancellation via Kotlin coroutines. Jobs have a lifecycle and expose readAccess / writeAccess for permission checks. Integrates with UserGroupCache for owner display.
Architecture
Class Hierarchy
- AbstractJob — abstract class implementing
Comparable<AbstractJob>
- Subclasses must implement
suspend fun run()
Key Enums
| Enum | Values | Purpose |
QueueStrategy | NONE, PER_QUEUE, PER_QUEUE_AND_USER, REFUSE_PER_QUEUE, REFUSE_PER_QUEUE_AND_USER | Controls whether job blocks/refuses new jobs in the same area |
Status | RUNNING, WAITING, FINISHED, FAILED, CANCELLED, REFUSED | Implements I18nEnum; drives ordering in job list |
ErrorCode | TIMEOUT_WHILE_WAITING, REFUSED_BY_ANOTHER_RUNNING_JOB | Reason for failure/refusal |
Job Lifecycle
The lifecycle is managed by JobHandler:
addJob() — job added to handler, status = WAITING
- Queue check — compares against running jobs via
isBlocking()
onBeforeStart() — hook before execution
start() — sets status to RUNNING, calls run()
- On success:
onFinish() → onAfterFinish() → onAfterTermination()
- On cancellation:
cancel() → onBeforeCancel() → onAfterCancel() → onAfterTermination()
- On failure:
markJobAsFailed() → onAfterException() → onAfterTermination()
Key Properties
| Property | Type | Description |
title | String | Human-readable title for display/logging |
area | String? | Groups jobs; queue strategy scoped to same area |
ownerId | Long? | User who started the job |
id | Int | Auto-incrementing unique job ID |
timeout | Int | Timeout in ms (from constructor param in seconds) |
timeoutReached | Boolean | True if job exceeded timeout while RUNNING |
isActive | Boolean | Convenience: status==RUNNING && coroutineJob.isActive |
progressPercentage | Int | Computed from processedNumber/totalNumber |
terminatedForDeletion | Boolean | True if terminated > 1 hour ago (cleanup) |
info | String | Markdown-formatted status info (owner, times, status, title) |
Permissions
readAccess(user) — delegates to writeAccess(user) by default
writeAccess(user) — abstract, must be implemented by subclass
isOwner — checks if current logged-in user matches ownerId
Integration Points
- JobHandler — manages jobs, calls lifecycle methods
- JobHandlerScheduler — triggers
tidyUp() every minute
- AccessChecker — injected via
@Autowired
- Coroutines —
Job handle stored as coroutinesJob
- I18n — status labels via
I18nEnum.i18nKey
Git History
868d6abb7 2025 -> 2026
63081666f Source file headers: 2024-> 2025.
cba940301 Migration stuff in progress...
67805f2fc ThreadLocalUserContext.user -> ThreadLocalUserContext.loggedInUser (renamed)
4c04cfd65 MAJOR-CHANGE! Migration of integer id's to Long id's (including fk's etc.)
b6092df09 Copyright 2023 -> 2024
ab45d51fa Copyright 2001-2022 -> 2001-2023.
163492453 WIP: Jobs and Bank account records.
232a91c5a BaseUserGroupRightUtils implemented. WIP BankingPlugin and jobs-handling.
38bec971a ThreadLocal -> Kotlin
09b3f0df7 WIP: Jobmonitor. ListStatisticsSupport -> MarkdownBuilder
fcc4c67f6 WIP: Jobmonitor.
a1646e91a WIP: Banking plugin (and new import module).
d93f61491 WIP: Banking plugin (and new import module).
cd69cc40f WIP: Banking plugin (and new import module).
f68cda98e Jobmonitor.
67eed70e4 WIP: Banking plugin (and new import module). JobHandler/monitor started.