Skip to content

Commit 393d3da

Browse files
committed
Add MetadataContirbutor
in order to easily contribute programmatically to the metadata this commit adds an MetadataContributor as extionsion point.
1 parent 6a0c7b7 commit 393d3da

File tree

10 files changed

+230
-23
lines changed

10 files changed

+230
-23
lines changed

spring-boot-admin-client/src/main/java/de/codecentric/boot/admin/client/config/SpringBootAdminClientAutoConfiguration.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,14 @@
2121
import de.codecentric.boot.admin.client.registration.DefaultApplicationFactory;
2222
import de.codecentric.boot.admin.client.registration.RegistrationApplicationListener;
2323
import de.codecentric.boot.admin.client.registration.ServletApplicationFactory;
24+
import de.codecentric.boot.admin.client.registration.metadata.CompositeMetadataContributor;
25+
import de.codecentric.boot.admin.client.registration.metadata.MetadataContributor;
26+
import de.codecentric.boot.admin.client.registration.metadata.StartupDateMetadataContributor;
2427

28+
import java.util.Collections;
29+
import java.util.List;
2530
import javax.servlet.ServletContext;
31+
import org.springframework.beans.factory.ObjectProvider;
2632
import org.springframework.beans.factory.annotation.Qualifier;
2733
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
2834
import org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration;
@@ -37,6 +43,7 @@
3743
import org.springframework.context.annotation.Bean;
3844
import org.springframework.context.annotation.Conditional;
3945
import org.springframework.context.annotation.Configuration;
46+
import org.springframework.context.annotation.Primary;
4047
import org.springframework.http.client.SimpleClientHttpRequestFactory;
4148
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
4249
import org.springframework.scheduling.TaskScheduler;
@@ -61,9 +68,10 @@ public ApplicationFactory applicationFactory(InstanceProperties instance,
6168
ServerProperties server,
6269
ServletContext servletContext,
6370
PathMappedEndpoints pathMappedEndpoints,
64-
WebEndpointProperties webEndpoint) {
71+
WebEndpointProperties webEndpoint,
72+
MetadataContributor metadataContributor) {
6573
return new ServletApplicationFactory(instance, management, server, servletContext, pathMappedEndpoints,
66-
webEndpoint);
74+
webEndpoint, metadataContributor);
6775
}
6876
}
6977

@@ -76,8 +84,10 @@ public ApplicationFactory applicationFactory(InstanceProperties instance,
7684
ManagementServerProperties management,
7785
ServerProperties server,
7886
PathMappedEndpoints pathMappedEndpoints,
79-
WebEndpointProperties webEndpoint) {
80-
return new DefaultApplicationFactory(instance, management, server, pathMappedEndpoints, webEndpoint);
87+
WebEndpointProperties webEndpoint,
88+
MetadataContributor metadataContributor) {
89+
return new DefaultApplicationFactory(instance, management, server, pathMappedEndpoints, webEndpoint,
90+
metadataContributor);
8191
}
8292
}
8393

@@ -102,8 +112,10 @@ public ApplicationFactory applicationFactory(InstanceProperties instance,
102112
ManagementServerProperties management,
103113
ServerProperties server,
104114
PathMappedEndpoints pathMappedEndpoints,
105-
WebEndpointProperties webEndpoint) {
106-
return new DefaultApplicationFactory(instance, management, server, pathMappedEndpoints, webEndpoint);
115+
WebEndpointProperties webEndpoint,
116+
MetadataContributor metadataContributor) {
117+
return new DefaultApplicationFactory(instance, management, server, pathMappedEndpoints, webEndpoint,
118+
metadataContributor);
107119
}
108120

109121
@Bean
@@ -127,4 +139,18 @@ public RegistrationApplicationListener registrationListener(ClientProperties cli
127139
listener.setRegisterPeriod(client.getPeriod());
128140
return listener;
129141
}
142+
143+
@Bean
144+
@Primary
145+
@ConditionalOnMissingBean
146+
public CompositeMetadataContributor metadataContributor(ObjectProvider<List<MetadataContributor>> contributorProvider) {
147+
List<MetadataContributor> contributors = contributorProvider.getIfAvailable(Collections::emptyList);
148+
return new CompositeMetadataContributor(contributors);
149+
}
150+
151+
@Bean
152+
@ConditionalOnMissingBean
153+
public StartupDateMetadataContributor startupDateMetadataContributor() {
154+
return new StartupDateMetadataContributor();
155+
}
130156
}

spring-boot-admin-client/src/main/java/de/codecentric/boot/admin/client/registration/DefaultApplicationFactory.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@
1717
package de.codecentric.boot.admin.client.registration;
1818

1919
import de.codecentric.boot.admin.client.config.InstanceProperties;
20+
import de.codecentric.boot.admin.client.registration.metadata.MetadataContributor;
2021

2122
import java.net.InetAddress;
2223
import java.net.UnknownHostException;
23-
import java.time.OffsetDateTime;
24-
import java.time.format.DateTimeFormatter;
2524
import java.util.LinkedHashMap;
2625
import java.util.Map;
2726
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
@@ -47,7 +46,7 @@ public class DefaultApplicationFactory implements ApplicationFactory {
4746
private final ManagementServerProperties management;
4847
private final PathMappedEndpoints pathMappedEndpoints;
4948
private final WebEndpointProperties webEndpoint;
50-
private final OffsetDateTime timestamp;
49+
private final MetadataContributor metadataContributor;
5150
private Integer localServerPort;
5251
private Integer localManagementPort;
5352

@@ -56,13 +55,14 @@ public DefaultApplicationFactory(InstanceProperties instance,
5655
ManagementServerProperties management,
5756
ServerProperties server,
5857
PathMappedEndpoints pathMappedEndpoints,
59-
WebEndpointProperties webEndpoint) {
58+
WebEndpointProperties webEndpoint,
59+
MetadataContributor metadataContributor) {
6060
this.instance = instance;
6161
this.management = management;
6262
this.server = server;
6363
this.pathMappedEndpoints = pathMappedEndpoints;
6464
this.webEndpoint = webEndpoint;
65-
this.timestamp = OffsetDateTime.now();
65+
this.metadataContributor = metadataContributor;
6666
}
6767

6868
@Override
@@ -162,14 +162,10 @@ protected String getHealthUrl() {
162162
}
163163

164164
protected Map<String, String> getMetadata() {
165-
if (instance.getMetadata().containsKey("startup")) {
166-
return instance.getMetadata();
167-
} else {
168-
Map<String, String> metadata = new LinkedHashMap<>();
169-
metadata.put("startup", this.timestamp.format(DateTimeFormatter.ISO_DATE_TIME));
170-
metadata.putAll(instance.getMetadata());
171-
return metadata;
172-
}
165+
Map<String, String> metadata = new LinkedHashMap<>();
166+
metadata.putAll(metadataContributor.getMetadata());
167+
metadata.putAll(instance.getMetadata());
168+
return metadata;
173169
}
174170

175171
protected String getServiceHost() {

spring-boot-admin-client/src/main/java/de/codecentric/boot/admin/client/registration/ServletApplicationFactory.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package de.codecentric.boot.admin.client.registration;
1818

1919
import de.codecentric.boot.admin.client.config.InstanceProperties;
20+
import de.codecentric.boot.admin.client.registration.metadata.MetadataContributor;
2021

2122
import javax.servlet.ServletContext;
2223
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
@@ -35,8 +36,9 @@ public ServletApplicationFactory(InstanceProperties instance,
3536
ServerProperties server,
3637
ServletContext servletContext,
3738
PathMappedEndpoints pathMappedEndpoints,
38-
WebEndpointProperties webEndpoint) {
39-
super(instance, management, server, pathMappedEndpoints, webEndpoint);
39+
WebEndpointProperties webEndpoint,
40+
MetadataContributor metadataContributor) {
41+
super(instance, management, server, pathMappedEndpoints, webEndpoint, metadataContributor);
4042
this.servletContext = servletContext;
4143
this.servlet = server.getServlet();
4244
this.managementServlet = management.getServlet();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2014-2018 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+
* http://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.client.registration.metadata;
18+
19+
import java.util.LinkedHashMap;
20+
import java.util.List;
21+
import java.util.Map;
22+
23+
public class CompositeMetadataContributor implements MetadataContributor {
24+
private final List<MetadataContributor> delegates;
25+
26+
public CompositeMetadataContributor(List<MetadataContributor> delegates) {
27+
this.delegates = delegates;
28+
}
29+
30+
@Override
31+
public Map<String, String> getMetadata() {
32+
Map<String, String> metadata = new LinkedHashMap<>();
33+
delegates.forEach(delegate -> metadata.putAll(delegate.getMetadata()));
34+
return metadata;
35+
}
36+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright 2014-2018 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+
* http://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.client.registration.metadata;
18+
19+
import java.util.Map;
20+
21+
@FunctionalInterface
22+
public interface MetadataContributor {
23+
24+
Map<String, String> getMetadata();
25+
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2014-2018 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+
* http://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.client.registration.metadata;
18+
19+
import java.time.OffsetDateTime;
20+
import java.time.format.DateTimeFormatter;
21+
import java.util.Map;
22+
23+
import static java.util.Collections.singletonMap;
24+
25+
public class StartupDateMetadataContributor implements MetadataContributor {
26+
private final OffsetDateTime timestamp = OffsetDateTime.now();
27+
28+
@Override
29+
public Map<String, String> getMetadata() {
30+
return singletonMap("startup", this.timestamp.format(DateTimeFormatter.ISO_DATE_TIME));
31+
}
32+
}

spring-boot-admin-client/src/test/java/de/codecentric/boot/admin/client/registration/DefaultApplicationFactoryTest.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@
3131
import org.springframework.boot.web.server.Ssl;
3232
import org.springframework.boot.web.server.WebServer;
3333

34+
import static java.util.Collections.singletonMap;
3435
import static org.assertj.core.api.Assertions.assertThat;
3536
import static org.assertj.core.api.Assertions.assertThatThrownBy;
37+
import static org.assertj.core.api.Assertions.entry;
3638
import static org.mockito.Mockito.mock;
3739
import static org.mockito.Mockito.when;
3840

@@ -44,7 +46,7 @@ public class DefaultApplicationFactoryTest {
4446
private WebEndpointProperties webEndpoint = new WebEndpointProperties();
4547

4648
private DefaultApplicationFactory factory = new DefaultApplicationFactory(instanceProperties, management, server,
47-
pathMappedEndpoints, webEndpoint);
49+
pathMappedEndpoints, webEndpoint, () -> singletonMap("contributor", "test"));
4850

4951
@Before
5052
public void setup() {
@@ -65,13 +67,16 @@ public void test_mgmtPortPath() {
6567

6668
@Test
6769
public void test_default() {
70+
instanceProperties.setMetadata(singletonMap("instance", "test"));
6871
when(pathMappedEndpoints.getPath("health")).thenReturn("/actuator/health");
6972
publishApplicationReadyEvent(factory, 8080, null);
7073

7174
Application app = factory.createApplication();
7275
assertThat(app.getManagementUrl()).isEqualTo("http://" + getHostname() + ":8080/actuator");
7376
assertThat(app.getHealthUrl()).isEqualTo("http://" + getHostname() + ":8080/actuator/health");
7477
assertThat(app.getServiceUrl()).isEqualTo("http://" + getHostname() + ":8080/");
78+
79+
assertThat(app.getMetadata()).containsExactly(entry("contributor", "test"), entry("instance", "test"));
7580
}
7681

7782
@Test

spring-boot-admin-client/src/test/java/de/codecentric/boot/admin/client/registration/ServletApplicationFactoryTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.net.InetAddress;
2222
import java.net.UnknownHostException;
23+
import java.util.Collections;
2324
import org.junit.Before;
2425
import org.junit.Test;
2526
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
@@ -43,7 +44,7 @@ public class ServletApplicationFactoryTest {
4344
private PathMappedEndpoints pathMappedEndpoints = mock(PathMappedEndpoints.class);
4445
private WebEndpointProperties webEndpoint = new WebEndpointProperties();
4546
private ServletApplicationFactory factory = new ServletApplicationFactory(instance, management, server,
46-
servletContext, pathMappedEndpoints, webEndpoint);
47+
servletContext, pathMappedEndpoints, webEndpoint, Collections::emptyMap);
4748

4849
@Before
4950
public void setup() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2014-2018 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+
* http://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.client.registration.metadata;
18+
19+
import java.util.Map;
20+
import org.junit.Test;
21+
22+
import static java.util.Arrays.asList;
23+
import static java.util.Collections.emptyList;
24+
import static java.util.Collections.singletonMap;
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
import static org.assertj.core.api.Assertions.entry;
27+
28+
public class CompositeMetadataContributorTest {
29+
30+
@Test
31+
public void should_merge_metadata() {
32+
CompositeMetadataContributor contributor = new CompositeMetadataContributor(
33+
asList(() -> singletonMap("a", "first"), () -> singletonMap("b", "second"),
34+
() -> singletonMap("b", "second-new")));
35+
36+
Map<String, String> metadata = contributor.getMetadata();
37+
38+
assertThat(metadata).containsExactly(entry("a", "first"), entry("b", "second-new"));
39+
}
40+
41+
@Test
42+
public void should_return_empty_metadata() {
43+
CompositeMetadataContributor contributor = new CompositeMetadataContributor(emptyList());
44+
45+
Map<String, String> metadata = contributor.getMetadata();
46+
47+
assertThat(metadata).isEmpty();
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2014-2018 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+
* http://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.client.registration.metadata;
18+
19+
import java.util.Map;
20+
import org.junit.Test;
21+
22+
import static org.assertj.core.api.Assertions.assertThat;
23+
24+
public class StartupDateMetadataContributorTest {
25+
26+
@Test
27+
public void should_return_startupdate() {
28+
StartupDateMetadataContributor contributor = new StartupDateMetadataContributor();
29+
30+
Map<String, String> metadata = contributor.getMetadata();
31+
32+
assertThat(metadata).hasSize(1).hasEntrySatisfying("startup", (value) -> assertThat(value).isNotEmpty());
33+
}
34+
}

0 commit comments

Comments
 (0)