Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4eb78ab
feat(quartz): add Quartz job configuration and dependencies for sched…
SteKoe Mar 26, 2026
fb3cbb2
feat(quartz): implement Quartz Actuator service for job and trigger m…
SteKoe Mar 26, 2026
e63fb3e
feat(quartz): enhance Quartz UI with job and trigger details, add new…
SteKoe Mar 26, 2026
92ea774
feat(quartz): enhance job and trigger display with improved data hand…
SteKoe Mar 26, 2026
1dc893b
feat(quartz): add job triggering functionality with UI integration an…
SteKoe Mar 26, 2026
0e8411b
feat(quartz): update trigger row styling for improved visibility and …
SteKoe Mar 26, 2026
00c6994
feat(styles): standardize CSS import syntax and improve variable form…
SteKoe Mar 26, 2026
5353777
feat(quartz): update UI styles for improved consistency and readability
SteKoe Mar 27, 2026
498c83d
refactor(quartz): modernize trigger components with <script setup> an…
SteKoe Mar 27, 2026
3589820
style(i18n): alphabetize quartz translation keys
SteKoe Mar 27, 2026
33fcfbc
i18n(quartz): externalize job trigger notification messages
SteKoe Mar 27, 2026
ead9adb
i18n(quartz): update German translations for job-related terms
SteKoe Mar 27, 2026
3836f96
i18n(quartz): translate hardcoded 'Description' label
SteKoe Mar 27, 2026
e4ce628
i18n(quartz): add missing 'name' and 'group' translation keys
SteKoe Mar 27, 2026
5522d9b
test(quartz): fix failing tests by updating i18n test setup and mocks
SteKoe Mar 27, 2026
9d09b7f
refactor(quartz): migrate job-row.spec.ts to use render function from…
SteKoe Mar 27, 2026
c55ffcf
fix(quartz): Replace i18n keys with actual translations in tests
SteKoe Mar 27, 2026
f00d0f4
fix(quartz): Use i18n key placeholders in test assertions instead of …
SteKoe Mar 27, 2026
47673e7
fix(quartz): add missing newlines at the end of i18n JSON files and f…
SteKoe Mar 27, 2026
0ade570
refactor(test-utils): remove unused deepMerge import
SteKoe Mar 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
<groupId>org.jolokia</groupId>
<artifactId>jolokia-support-springboot</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright 2014-2024 the original author or authors.
*
* 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
*
* https://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 de.codecentric.boot.admin.sample;

import java.util.TimeZone;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.QuartzJobBean;

/**
* Configuration for sample Quartz jobs and triggers to demonstrate the Quartz actuator
* endpoint. This allows testing of job/trigger listing in Spring Boot Admin UI.
*/
@Configuration
public class QuartzJobsConfiguration {

/**
* Creates job details for the sample job.
* @return job detail for the sample job
*/
@Bean
public JobDetail sampleJobDetail() {
return JobBuilder.newJob(SampleJob.class)
.withIdentity("sampleJob", "samples")
.withDescription("Sample job to demonstrate Quartz actuator endpoint")
.storeDurably()
.build();
}

/**
* Creates job details for the another sample job.
* @return job detail for the another sample job
*/
@Bean
public JobDetail anotherSampleJobDetail() {
return JobBuilder.newJob(AnotherSampleJob.class)
.withIdentity("anotherJob", "samples")
.withDescription("Another sample job for testing")
.storeDurably()
.build();
}

/**
* Creates a simple trigger that executes the sample job every 10 seconds.
* @return trigger for the sample job
*/
@Bean
public Trigger sampleJobTrigger() {
return TriggerBuilder.newTrigger()
.forJob(sampleJobDetail())
.withIdentity("sampleTrigger", "samples")
.withDescription("Trigger that executes sample job every 10 seconds")
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).repeatForever())
.build();
}

/**
* Creates a cron trigger that executes another sample job every day at 3am.
* @return trigger for the another sample job
*/
@Bean
public Trigger anotherSampleJobTrigger() {
return TriggerBuilder.newTrigger()
.forJob(anotherSampleJobDetail())
.withIdentity("dailyTrigger", "samples")
.withDescription("Daily trigger at 3am")
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 3 * * ?").inTimeZone(TimeZone.getTimeZone("UTC")))
.build();
}

/**
* Creates a simple trigger for testing purposes (every hour).
* @return trigger for hourly execution
*/
@Bean
public Trigger hourlyTestTrigger() {
return TriggerBuilder.newTrigger()
.forJob(sampleJobDetail())
.withIdentity("hourlyTrigger", "DEFAULT")
.withDescription("Hourly trigger for testing")
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInHours(1).repeatForever())
.build();
}

/**
* Sample job that logs at regular intervals.
*/
public static class SampleJob extends QuartzJobBean {

@Override
protected void executeInternal(org.quartz.JobExecutionContext context) {
System.out.println("Sample Quartz Job executed at " + new java.util.Date());
}

}

/**
* Another sample job for demonstration.
*/
public static class AnotherSampleJob extends QuartzJobBean {

@Override
protected void executeInternal(org.quartz.JobExecutionContext context) {
System.out.println("Another Quartz Job executed at " + new java.util.Date());
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { faStopCircle as farStopCircle } from '@fortawesome/free-regular-svg-ico
import { faTimesCircle as farTimesCircle } from '@fortawesome/free-regular-svg-icons/faTimesCircle';
import {
faAngleDoubleLeft,
faBriefcase,
faClock,
faCogs,
faExpand,
faEye,
Expand All @@ -34,6 +36,8 @@ import { faBars } from '@fortawesome/free-solid-svg-icons/faBars';
import { faBell } from '@fortawesome/free-solid-svg-icons/faBell';
import { faBellSlash } from '@fortawesome/free-solid-svg-icons/faBellSlash';
import { faBook } from '@fortawesome/free-solid-svg-icons/faBook';
import { faCalendar } from '@fortawesome/free-solid-svg-icons/faCalendar';
import { faCalendarCheck } from '@fortawesome/free-solid-svg-icons/faCalendarCheck';
import { faCheck } from '@fortawesome/free-solid-svg-icons/faCheck';
import { faCheckCircle } from '@fortawesome/free-solid-svg-icons/faCheckCircle';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons/faChevronDown';
Expand All @@ -49,13 +53,18 @@ import { faFrownOpen } from '@fortawesome/free-solid-svg-icons/faFrownOpen';
import { faHeartbeat } from '@fortawesome/free-solid-svg-icons/faHeartbeat';
import { faHistory } from '@fortawesome/free-solid-svg-icons/faHistory';
import { faHome } from '@fortawesome/free-solid-svg-icons/faHome';
import { faHourglass } from '@fortawesome/free-solid-svg-icons/faHourglass';
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons/faInfoCircle';
import { faLink } from '@fortawesome/free-solid-svg-icons/faLink';
import { faMapMarkerAlt } from '@fortawesome/free-solid-svg-icons/faMapMarkerAlt';
import { faMinusCircle } from '@fortawesome/free-solid-svg-icons/faMinusCircle';
import { faPauseCircle } from '@fortawesome/free-solid-svg-icons/faPauseCircle';
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons/faPencilAlt';
import { faPlayCircle } from '@fortawesome/free-solid-svg-icons/faPlayCircle';
import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons/faQuestionCircle';
import { faRedo } from '@fortawesome/free-solid-svg-icons/faRedo';
import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch';
import { faShield } from '@fortawesome/free-solid-svg-icons/faShield';
import { faSignOutAlt } from '@fortawesome/free-solid-svg-icons/faSignOutAlt';
import { faStepBackward } from '@fortawesome/free-solid-svg-icons/faStepBackward';
import { faStepForward } from '@fortawesome/free-solid-svg-icons/faStepForward';
Expand All @@ -77,6 +86,10 @@ library.add(
faBellSlash,
faBook,
faBars,
faBriefcase,
faCalendar,
faCalendarCheck,
faClock,
faCogs,
faEye,
faCheck,
Expand All @@ -90,20 +103,25 @@ library.add(
faFrownOpen,
faHeartbeat,
faHistory,
faHourglass,
faInfoCircle,
faExclamationCircle,
faHome,
faLink,
faList,
faExpand,
faMapMarkerAlt,
faCheckCircle,
faMinusCircle,
faChevronRight,
faChevronDown,
faPauseCircle,
faPencilAlt,
faPlayCircle,
faPowerOff,
faQuestionCircle,
faSearch,
faShield,
faSignOutAlt,
faStepBackward,
faStepForward,
Expand Down
2 changes: 1 addition & 1 deletion spring-boot-admin-server-ui/src/main/frontend/login.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@import "./theme.css";
@import './theme.css';

:root {
--bg-color-start: #71e69c;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2026 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -45,7 +45,7 @@ const isInstanceActuatorRequest = (url: string) =>

class Instance {
public readonly id: string;
private readonly axios: AxiosInstance;
readonly axios: AxiosInstance;
public registration: Registration;
public endpoints: Endpoint[] = [];
public availableMetrics: string[] = [];
Expand Down Expand Up @@ -481,30 +481,6 @@ class Instance {
return this.axios.get(uri`actuator/mappings`);
}

async fetchQuartzJobs() {
return this.axios.get(uri`actuator/quartz/jobs`, {
headers: { Accept: 'application/json' },
});
}

async fetchQuartzJob(group, name) {
return this.axios.get(uri`actuator/quartz/jobs/${group}/${name}`, {
headers: { Accept: 'application/json' },
});
}

async fetchQuartzTriggers() {
return this.axios.get(uri`actuator/quartz/triggers`, {
headers: { Accept: 'application/json' },
});
}

async fetchQuartzTrigger(group, name) {
return this.axios.get(uri`actuator/quartz/triggers/${group}/${name}`, {
headers: { Accept: 'application/json' },
});
}

async fetchSbomIds() {
return this.axios.get(uri`actuator/sbom`, {
headers: { Accept: 'application/json' },
Expand Down
Loading