CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-starter-quartz

Starter for using the Quartz scheduler in Spring Boot applications with auto-configuration support

Pending
Overview
Eval results
Files

actuator-integration.mddocs/

Actuator Integration

Management endpoints for monitoring and inspecting Quartz scheduler state, including jobs, triggers, and execution history. Provides both REST API and web interface for scheduler management through Spring Boot Actuator.

Capabilities

QuartzEndpoint

Main actuator endpoint that exposes Quartz scheduler information for monitoring and management.

/**
 * Actuator endpoint for exposing Quartz Scheduler information
 * Available at /actuator/quartz when management endpoints are enabled
 */
@Endpoint(id = "quartz")
public class QuartzEndpoint {

    /**
     * Creates QuartzEndpoint with scheduler and sanitizing functions
     * @param scheduler The Quartz Scheduler instance to monitor
     * @param sanitizingFunctions Functions for sanitizing sensitive data in responses
     */
    public QuartzEndpoint(Scheduler scheduler, Iterable<SanitizingFunction> sanitizingFunctions);

    /**
     * Return the available job and trigger group names
     * @return QuartzDescriptor containing job and trigger group information
     * @throws SchedulerException if retrieving information from scheduler fails
     */
    @ReadOperation
    public QuartzDescriptor quartzReport() throws SchedulerException;

    /**
     * Return available job names organized by group
     * @return QuartzGroupsDescriptor containing job group details
     * @throws SchedulerException if retrieving information from scheduler fails
     */
    public QuartzGroupsDescriptor quartzJobGroups() throws SchedulerException;

    /**
     * Return available trigger names organized by group  
     * @return QuartzGroupsDescriptor containing trigger group details
     * @throws SchedulerException if retrieving information from scheduler fails
     */
    public QuartzGroupsDescriptor quartzTriggerGroups() throws SchedulerException;

    /**
     * Return job group summary with job details
     * @param group The job group name
     * @return QuartzJobGroupSummaryDescriptor containing jobs in the specified group
     * @throws SchedulerException if retrieving information fails
     */
    public QuartzJobGroupSummaryDescriptor quartzJobGroupSummary(String group) throws SchedulerException;

    /**
     * Return trigger group summary with trigger details
     * @param group The trigger group name  
     * @return QuartzTriggerGroupSummaryDescriptor containing triggers in the specified group
     * @throws SchedulerException if retrieving information fails
     */
    public QuartzTriggerGroupSummaryDescriptor quartzTriggerGroupSummary(String group) throws SchedulerException;

    /**
     * Return detailed information about a specific job
     * @param groupName Job group name
     * @param jobName Job name
     * @param showUnsanitized Whether to show unsanitized data
     * @return QuartzJobDetailsDescriptor with detailed job information
     * @throws SchedulerException if job cannot be found or accessed
     */
    public QuartzJobDetailsDescriptor quartzJob(String groupName, String jobName, boolean showUnsanitized) 
        throws SchedulerException;

    /**
     * Return detailed information about a specific trigger
     * @param groupName Trigger group name
     * @param triggerName Trigger name
     * @param showUnsanitized Whether to show unsanitized data
     * @return Map containing detailed trigger information  
     * @throws SchedulerException if trigger cannot be found or accessed
     */
    Map<String, Object> quartzTrigger(String groupName, String triggerName, boolean showUnsanitized)
        throws SchedulerException;

    /**
     * Trigger a specific job to run immediately (write operation since Spring Boot 3.5.0)
     * @param groupName Job group name
     * @param jobName Job name
     * @return QuartzJobTriggerDescriptor with trigger execution details
     * @throws SchedulerException if job cannot be triggered
     */
    @WriteOperation
    public QuartzJobTriggerDescriptor triggerQuartzJob(String groupName, String jobName) 
        throws SchedulerException;
}

Usage Examples:

# Get overview of all job and trigger groups
curl http://localhost:8080/actuator/quartz

# Get all job groups
curl http://localhost:8080/actuator/quartz/jobs

# Get jobs in specific group
curl http://localhost:8080/actuator/quartz/jobs/myGroup

# Get specific job details
curl http://localhost:8080/actuator/quartz/jobs/myGroup/myJob

# Get all trigger groups
curl http://localhost:8080/actuator/quartz/triggers

# Get triggers in specific group
curl http://localhost:8080/actuator/quartz/triggers/myGroup

# Get specific trigger details
curl http://localhost:8080/actuator/quartz/triggers/myGroup/myTrigger

# Trigger a job to run immediately (write operation)
curl -X POST http://localhost:8080/actuator/quartz/jobs/myGroup/myJob \
     -H "Content-Type: application/json" \
     -d '{"state": "running"}'

QuartzEndpointWebExtension

Web-specific extension providing additional HTTP operations for the Quartz endpoint with path variable support and enhanced security handling.

/**
 * Web extension for QuartzEndpoint providing additional HTTP-specific operations
 * Adds path variable support and enhanced web interface capabilities
 * Annotated with @EndpointWebExtension(endpoint = QuartzEndpoint.class)
 */
@EndpointWebExtension(endpoint = QuartzEndpoint.class)
public class QuartzEndpointWebExtension {

    /**
     * Creates web extension with endpoint and configuration
     * @param endpoint The base QuartzEndpoint
     * @param showValues Show configuration for sensitive data (ALWAYS, NEVER, WHEN_AUTHORIZED)
     * @param roles Set of required roles for access
     */
    public QuartzEndpointWebExtension(
        QuartzEndpoint endpoint, 
        Show showValues, 
        Set<String> roles
    );

    /**
     * Get jobs or triggers by group type via web interface
     * @param jobsOrTriggers Either "jobs" or "triggers" path segment
     * @return WebEndpointResponse with QuartzGroupsDescriptor
     * @throws SchedulerException if group access fails
     */
    @ReadOperation
    public WebEndpointResponse<QuartzGroupsDescriptor> quartzJobOrTriggerGroups(@Selector String jobsOrTriggers) 
        throws SchedulerException;

    /**
     * Get specific job or trigger group summary via web interface
     * @param jobsOrTriggers Either "jobs" or "triggers" path segment
     * @param group Group name from path variable
     * @return WebEndpointResponse with group summary
     * @throws SchedulerException if group access fails
     */
    @ReadOperation
    public WebEndpointResponse<Object> quartzJobOrTriggerGroup(@Selector String jobsOrTriggers, @Selector String group)
        throws SchedulerException;

    /**
     * Get specific job or trigger details via web interface
     * @param securityContext Security context for access control
     * @param jobsOrTriggers Either "jobs" or "triggers" path segment
     * @param group Group name from path
     * @param name Job or trigger name from path
     * @return WebEndpointResponse with job or trigger details
     * @throws SchedulerException if access fails
     */
    @ReadOperation
    public WebEndpointResponse<Object> quartzJobOrTrigger(SecurityContext securityContext,
        @Selector String jobsOrTriggers, @Selector String group, @Selector String name) 
        throws SchedulerException;

    /**
     * Trigger a Quartz job via web interface (since Spring Boot 3.5.0)
     * @param jobs Must be "jobs" path segment
     * @param group Job group name from path
     * @param name Job name from path  
     * @param state Desired state - must be "running" to trigger
     * @return WebEndpointResponse indicating success or failure
     * @throws SchedulerException if job triggering fails
     */
    @WriteOperation
    public WebEndpointResponse<Object> triggerQuartzJob(@Selector String jobs, @Selector String group,
        @Selector String name, String state) throws SchedulerException;
}

QuartzEndpointAutoConfiguration

Auto-configuration class that automatically sets up Quartz actuator endpoints when conditions are met.

/**
 * Auto-configuration for Quartz actuator endpoint
 * Activates when Scheduler is available and endpoint is enabled
 */
@AutoConfiguration(after = QuartzAutoConfiguration.class)
@ConditionalOnClass(Scheduler.class)
@ConditionalOnAvailableEndpoint(QuartzEndpoint.class)
@EnableConfigurationProperties(QuartzEndpointProperties.class)
public class QuartzEndpointAutoConfiguration {

    /**
     * Creates QuartzEndpoint when Scheduler bean is available
     * @param scheduler The Scheduler instance to monitor
     * @param sanitizingFunctions Ordered stream of sanitizing functions
     * @return Configured QuartzEndpoint
     */
    @Bean
    @ConditionalOnBean(Scheduler.class)
    @ConditionalOnMissingBean
    public QuartzEndpoint quartzEndpoint(
        Scheduler scheduler, 
        ObjectProvider<SanitizingFunction> sanitizingFunctions
    );

    /**
     * Creates web extension when web endpoints are enabled
     * @param endpoint The base QuartzEndpoint
     * @param properties Configuration properties for the endpoint
     * @return Configured QuartzEndpointWebExtension
     */
    @Bean
    @ConditionalOnBean(QuartzEndpoint.class)
    @ConditionalOnMissingBean
    @ConditionalOnAvailableEndpoint(exposure = EndpointExposure.WEB)
    public QuartzEndpointWebExtension quartzEndpointWebExtension(
        QuartzEndpoint endpoint,
        QuartzEndpointProperties properties
    );
}

QuartzEndpointProperties

Configuration properties for customizing the Quartz actuator endpoint behavior.

/**
 * Configuration properties for Quartz actuator endpoint
 * Bound to management.endpoint.quartz configuration prefix
 */
@ConfigurationProperties("management.endpoint.quartz")
public class QuartzEndpointProperties {

    /**
     * Get the show configuration for sensitive data
     * @return Show enum value (ALWAYS, NEVER, WHEN_AUTHORIZED - default: NEVER)
     */
    public Show getShowValues();

    /**
     * Set the show configuration for sensitive data
     * @param showValues Show configuration for endpoint data
     */
    public void setShowValues(Show showValues);

    /**
     * Get list of required roles for endpoint access
     * @return List of role names required for access (default: empty)
     */
    public List<String> getRoles();

    /**
     * Set required roles for endpoint access
     * @param roles List of role names that can access the endpoint
     */
    public void setRoles(List<String> roles);
}

/**
 * Enumeration for controlling when sensitive data should be shown in endpoint responses
 */
public enum Show {
    /**
     * Never show sensitive data values
     */
    NEVER,
    
    /**
     * Show sensitive data values only when user is authorized  
     */
    WHEN_AUTHORIZED,
    
    /**
     * Always show sensitive data values
     */
    ALWAYS
}

Data Transfer Objects

The endpoint returns structured data through various descriptor classes:

/**
 * Root descriptor containing job and trigger group information
 */
public class QuartzDescriptor implements OperationResponseBody {
    public QuartzDescriptor(GroupNamesDescriptor jobs, GroupNamesDescriptor triggers);
    public GroupNamesDescriptor getJobs();
    public GroupNamesDescriptor getTriggers();
}

/**
 * Descriptor for group names
 */
public class GroupNamesDescriptor {
    public GroupNamesDescriptor(Set<String> groups);
    public Set<String> getGroups();
}

/**
 * Descriptor for jobs organized by group
 */
public class QuartzGroupsDescriptor {
    public Map<String, Object> getGroups();
}

/**
 * Descriptor for job collection
 */
public class JobsDescriptor {
    public Map<String, JobDescriptor> getJobs();
}

/**
 * Descriptor for trigger collection
 */
public class TriggersDescriptor {
    public Map<String, TriggerDescriptor> getTriggers();
}

/**
 * Detailed job information descriptor
 */
public class JobDescriptor {
    public String getGroup();
    public String getName();
    public String getDescription();
    public String getClassName();
    public boolean isDurable();
    public boolean isRequestsRecovery();
    public JobDataMapDescriptor getData();
}

/**
 * Detailed trigger information descriptor
 */
public class TriggerDescriptor {
    public String getGroup();
    public String getName(); 
    public String getDescription();
    public String getState();
    public String getType();
    public String getCalendarName();
    public Date getStartTime();
    public Date getEndTime();
    public Date getNextFireTime();
    public Date getPreviousFireTime();
    public int getPriority();
}

/**
 * Job data map descriptor
 */
public class JobDataMapDescriptor {
    public Map<String, Object> getData();
}

/**
 * Job group summary descriptor
 */
public class QuartzJobGroupSummaryDescriptor {
    public String getGroup();
    public JobsDescriptor getJobs();
}

/**
 * Trigger group summary descriptor
 */
public class QuartzTriggerGroupSummaryDescriptor {
    public String getGroup();
    public TriggersDescriptor getTriggers();
}

/**
 * Job details descriptor with complete job information
 */
public class QuartzJobDetailsDescriptor {
    public String getGroup();
    public String getName();
    public String getDescription();
    public String getClassName();
    public boolean isDurable();
    public boolean isRequestsRecovery();
    public JobDataMapDescriptor getData();
    public List<TriggerDescriptor> getTriggers();
}

/**
 * Job trigger descriptor for write operations
 */
public class QuartzJobTriggerDescriptor {
    public String getGroup();
    public String getName();
    public Date getFireTime();
    public String getState();
}

Configuration Examples

Basic Endpoint Configuration

# Enable Quartz endpoint
management.endpoints.web.exposure.include=quartz
management.endpoint.quartz.enabled=true

# Security configuration
management.endpoint.quartz.roles=ADMIN,OPERATOR
management.endpoint.quartz.show-values=password,secret

# Endpoint path customization
management.endpoints.web.path-mapping.quartz=scheduler
management:
  endpoints:
    web:
      exposure:
        include: quartz,health,info
      path-mapping:
        quartz: scheduler
  endpoint:
    quartz:
      enabled: true
      roles:
        - ADMIN
        - OPERATOR
      show-values:
        - password
        - apiKey

Security Configuration

@Configuration
@EnableWebSecurity
public class ActuatorSecurityConfiguration {
    
    @Bean
    public SecurityFilterChain actuatorFilterChain(HttpSecurity http) throws Exception {
        return http
            .requestMatcher(EndpointRequest.toAnyEndpoint())
            .authorizeHttpRequests(requests -> requests
                .requestMatchers(EndpointRequest.to(QuartzEndpoint.class))
                .hasRole("ADMIN")
                .anyRequest().hasRole("ACTUATOR")
            )
            .httpBasic(withDefaults())
            .build();
    }
}

Custom Sanitizing Functions

@Configuration
public class QuartzSanitizationConfiguration {
    
    @Bean
    public SanitizingFunction quartzDataSanitizer() {
        return new SanitizingFunction() {
            @Override
            public SanitizableData apply(SanitizableData data) {
                String key = data.getKey();
                Object value = data.getValue();
                
                if (key != null && key.toLowerCase().contains("password")) {
                    return data.withValue("******");
                }
                
                if (key != null && key.toLowerCase().contains("secret")) {
                    return data.withValue("[HIDDEN]");
                }
                
                return data;
            }
        };
    }
}

Monitoring and Alerting

Custom Health Indicator

@Component
public class QuartzHealthIndicator implements HealthIndicator {
    
    private final Scheduler scheduler;
    
    public QuartzHealthIndicator(Scheduler scheduler) {
        this.scheduler = scheduler;
    }
    
    @Override
    public Health health() {
        try {
            if (scheduler.isStarted()) {
                int jobCount = scheduler.getJobKeys(GroupMatcher.anyGroup()).size();
                int triggerCount = scheduler.getTriggerKeys(GroupMatcher.anyGroup()).size();
                
                return Health.up()
                    .withDetail("jobs", jobCount)
                    .withDetail("triggers", triggerCount)
                    .withDetail("running", scheduler.getCurrentlyExecutingJobs().size())
                    .build();
            } else {
                return Health.down()
                    .withDetail("reason", "Scheduler is not started")
                    .build();
            }
        } catch (SchedulerException e) {
            return Health.down(e)
                .withDetail("error", e.getMessage())
                .build();
        }
    }
}

Metrics Integration

@Configuration
public class QuartzMetricsConfiguration {
    
    @Bean
    public SchedulerFactoryBeanCustomizer metricsCustomizer(MeterRegistry meterRegistry) {
        return schedulerFactoryBean -> {
            schedulerFactoryBean.setGlobalJobListeners(
                new MicrometerJobListener(meterRegistry)
            );
        };
    }
}

public class MicrometerJobListener implements JobListener {
    
    private final MeterRegistry meterRegistry;
    private final Timer.Sample sample = Timer.start();
    
    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        sample.start();
    }
    
    @Override
    public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
        sample.stop(Timer.builder("quartz.job.execution")
            .tag("job", context.getJobDetail().getKey().toString())
            .tag("success", jobException == null ? "true" : "false")
            .register(meterRegistry));
    }
}

Error Handling

Exception Management

@ControllerAdvice
public class QuartzEndpointExceptionHandler {
    
    @ExceptionHandler(SchedulerException.class)
    public ResponseEntity<Map<String, String>> handleSchedulerException(SchedulerException e) {
        Map<String, String> error = Map.of(
            "error", "SchedulerException",
            "message", e.getMessage(),
            "timestamp", Instant.now().toString()
        );
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
    }
}

Timeout Configuration

# Configure timeouts for endpoint operations
management.endpoint.quartz.cache.time-to-live=30s
server.servlet.context-timeout=60s

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-quartz

docs

actuator-integration.md

auto-configuration.md

configuration-properties.md

index.md

scheduler-customization.md

tile.json