Skip to content

Commit 96aace1

Browse files
authored
feat(#5128): reimplement broken quartz view and add additional actuator functionallities (#5196)
1 parent 37c1bb0 commit 96aace1

37 files changed

Lines changed: 4362 additions & 288 deletions

spring-boot-admin-samples/spring-boot-admin-sample-servlet/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@
8080
<groupId>org.jolokia</groupId>
8181
<artifactId>jolokia-support-springboot</artifactId>
8282
</dependency>
83+
<dependency>
84+
<groupId>org.springframework.boot</groupId>
85+
<artifactId>spring-boot-starter-quartz</artifactId>
86+
</dependency>
8387
<!-- Test -->
8488
<dependency>
8589
<groupId>org.springframework.boot</groupId>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2014-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package de.codecentric.boot.admin.sample;
18+
19+
import java.util.TimeZone;
20+
21+
import org.quartz.CronScheduleBuilder;
22+
import org.quartz.JobBuilder;
23+
import org.quartz.JobDetail;
24+
import org.quartz.SimpleScheduleBuilder;
25+
import org.quartz.Trigger;
26+
import org.quartz.TriggerBuilder;
27+
import org.springframework.context.annotation.Bean;
28+
import org.springframework.context.annotation.Configuration;
29+
import org.springframework.scheduling.quartz.QuartzJobBean;
30+
31+
/**
32+
* Configuration for sample Quartz jobs and triggers to demonstrate the Quartz actuator
33+
* endpoint. This allows testing of job/trigger listing in Spring Boot Admin UI.
34+
*/
35+
@Configuration
36+
public class QuartzJobsConfiguration {
37+
38+
/**
39+
* Creates job details for the sample job.
40+
* @return job detail for the sample job
41+
*/
42+
@Bean
43+
public JobDetail sampleJobDetail() {
44+
return JobBuilder.newJob(SampleJob.class)
45+
.withIdentity("sampleJob", "samples")
46+
.withDescription("Sample job to demonstrate Quartz actuator endpoint")
47+
.storeDurably()
48+
.build();
49+
}
50+
51+
/**
52+
* Creates job details for the another sample job.
53+
* @return job detail for the another sample job
54+
*/
55+
@Bean
56+
public JobDetail anotherSampleJobDetail() {
57+
return JobBuilder.newJob(AnotherSampleJob.class)
58+
.withIdentity("anotherJob", "samples")
59+
.withDescription("Another sample job for testing")
60+
.storeDurably()
61+
.build();
62+
}
63+
64+
/**
65+
* Creates a simple trigger that executes the sample job every 10 seconds.
66+
* @return trigger for the sample job
67+
*/
68+
@Bean
69+
public Trigger sampleJobTrigger() {
70+
return TriggerBuilder.newTrigger()
71+
.forJob(sampleJobDetail())
72+
.withIdentity("sampleTrigger", "samples")
73+
.withDescription("Trigger that executes sample job every 10 seconds")
74+
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(10).repeatForever())
75+
.build();
76+
}
77+
78+
/**
79+
* Creates a cron trigger that executes another sample job every day at 3am.
80+
* @return trigger for the another sample job
81+
*/
82+
@Bean
83+
public Trigger anotherSampleJobTrigger() {
84+
return TriggerBuilder.newTrigger()
85+
.forJob(anotherSampleJobDetail())
86+
.withIdentity("dailyTrigger", "samples")
87+
.withDescription("Daily trigger at 3am")
88+
.withSchedule(CronScheduleBuilder.cronSchedule("0 0 3 * * ?").inTimeZone(TimeZone.getTimeZone("UTC")))
89+
.build();
90+
}
91+
92+
/**
93+
* Creates a simple trigger for testing purposes (every hour).
94+
* @return trigger for hourly execution
95+
*/
96+
@Bean
97+
public Trigger hourlyTestTrigger() {
98+
return TriggerBuilder.newTrigger()
99+
.forJob(sampleJobDetail())
100+
.withIdentity("hourlyTrigger", "DEFAULT")
101+
.withDescription("Hourly trigger for testing")
102+
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInHours(1).repeatForever())
103+
.build();
104+
}
105+
106+
/**
107+
* Sample job that logs at regular intervals.
108+
*/
109+
public static class SampleJob extends QuartzJobBean {
110+
111+
@Override
112+
protected void executeInternal(org.quartz.JobExecutionContext context) {
113+
System.out.println("Sample Quartz Job executed at " + new java.util.Date());
114+
}
115+
116+
}
117+
118+
/**
119+
* Another sample job for demonstration.
120+
*/
121+
public static class AnotherSampleJob extends QuartzJobBean {
122+
123+
@Override
124+
protected void executeInternal(org.quartz.JobExecutionContext context) {
125+
System.out.println("Another Quartz Job executed at " + new java.util.Date());
126+
}
127+
128+
}
129+
130+
}

spring-boot-admin-server-ui/src/main/frontend/components/font-awesome-icon.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { faStopCircle as farStopCircle } from '@fortawesome/free-regular-svg-ico
2121
import { faTimesCircle as farTimesCircle } from '@fortawesome/free-regular-svg-icons/faTimesCircle';
2222
import {
2323
faAngleDoubleLeft,
24+
faBriefcase,
25+
faClock,
2426
faCogs,
2527
faExpand,
2628
faEye,
@@ -34,6 +36,8 @@ import { faBars } from '@fortawesome/free-solid-svg-icons/faBars';
3436
import { faBell } from '@fortawesome/free-solid-svg-icons/faBell';
3537
import { faBellSlash } from '@fortawesome/free-solid-svg-icons/faBellSlash';
3638
import { faBook } from '@fortawesome/free-solid-svg-icons/faBook';
39+
import { faCalendar } from '@fortawesome/free-solid-svg-icons/faCalendar';
40+
import { faCalendarCheck } from '@fortawesome/free-solid-svg-icons/faCalendarCheck';
3741
import { faCheck } from '@fortawesome/free-solid-svg-icons/faCheck';
3842
import { faCheckCircle } from '@fortawesome/free-solid-svg-icons/faCheckCircle';
3943
import { faChevronDown } from '@fortawesome/free-solid-svg-icons/faChevronDown';
@@ -49,13 +53,18 @@ import { faFrownOpen } from '@fortawesome/free-solid-svg-icons/faFrownOpen';
4953
import { faHeartbeat } from '@fortawesome/free-solid-svg-icons/faHeartbeat';
5054
import { faHistory } from '@fortawesome/free-solid-svg-icons/faHistory';
5155
import { faHome } from '@fortawesome/free-solid-svg-icons/faHome';
56+
import { faHourglass } from '@fortawesome/free-solid-svg-icons/faHourglass';
5257
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons/faInfoCircle';
58+
import { faLink } from '@fortawesome/free-solid-svg-icons/faLink';
5359
import { faMapMarkerAlt } from '@fortawesome/free-solid-svg-icons/faMapMarkerAlt';
5460
import { faMinusCircle } from '@fortawesome/free-solid-svg-icons/faMinusCircle';
61+
import { faPauseCircle } from '@fortawesome/free-solid-svg-icons/faPauseCircle';
5562
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons/faPencilAlt';
63+
import { faPlayCircle } from '@fortawesome/free-solid-svg-icons/faPlayCircle';
5664
import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons/faQuestionCircle';
5765
import { faRedo } from '@fortawesome/free-solid-svg-icons/faRedo';
5866
import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch';
67+
import { faShield } from '@fortawesome/free-solid-svg-icons/faShield';
5968
import { faSignOutAlt } from '@fortawesome/free-solid-svg-icons/faSignOutAlt';
6069
import { faStepBackward } from '@fortawesome/free-solid-svg-icons/faStepBackward';
6170
import { faStepForward } from '@fortawesome/free-solid-svg-icons/faStepForward';
@@ -77,6 +86,10 @@ library.add(
7786
faBellSlash,
7887
faBook,
7988
faBars,
89+
faBriefcase,
90+
faCalendar,
91+
faCalendarCheck,
92+
faClock,
8093
faCogs,
8194
faEye,
8295
faCheck,
@@ -90,20 +103,25 @@ library.add(
90103
faFrownOpen,
91104
faHeartbeat,
92105
faHistory,
106+
faHourglass,
93107
faInfoCircle,
94108
faExclamationCircle,
95109
faHome,
110+
faLink,
96111
faList,
97112
faExpand,
98113
faMapMarkerAlt,
99114
faCheckCircle,
100115
faMinusCircle,
101116
faChevronRight,
102117
faChevronDown,
118+
faPauseCircle,
103119
faPencilAlt,
120+
faPlayCircle,
104121
faPowerOff,
105122
faQuestionCircle,
106123
faSearch,
124+
faShield,
107125
faSignOutAlt,
108126
faStepBackward,
109127
faStepForward,

spring-boot-admin-server-ui/src/main/frontend/services/instance.ts

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2019 the original author or authors.
2+
* Copyright 2014-2026 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ const isInstanceActuatorRequest = (url: string) =>
4646

4747
class Instance {
4848
public readonly id: string;
49-
private readonly axios: AxiosInstance;
49+
readonly axios: AxiosInstance;
5050
public registration: Registration;
5151
public endpoints: Endpoint[] = [];
5252
public availableMetrics: string[] = [];
@@ -483,30 +483,6 @@ class Instance {
483483
return this.axios.get(uri`actuator/mappings`);
484484
}
485485

486-
async fetchQuartzJobs() {
487-
return this.axios.get(uri`actuator/quartz/jobs`, {
488-
headers: { Accept: 'application/json' },
489-
});
490-
}
491-
492-
async fetchQuartzJob(group, name) {
493-
return this.axios.get(uri`actuator/quartz/jobs/${group}/${name}`, {
494-
headers: { Accept: 'application/json' },
495-
});
496-
}
497-
498-
async fetchQuartzTriggers() {
499-
return this.axios.get(uri`actuator/quartz/triggers`, {
500-
headers: { Accept: 'application/json' },
501-
});
502-
}
503-
504-
async fetchQuartzTrigger(group, name) {
505-
return this.axios.get(uri`actuator/quartz/triggers/${group}/${name}`, {
506-
headers: { Accept: 'application/json' },
507-
});
508-
}
509-
510486
async fetchSbomIds() {
511487
return this.axios.get(uri`actuator/sbom`, {
512488
headers: { Accept: 'application/json' },

0 commit comments

Comments
 (0)