Skip to content

Commit ad16bd4

Browse files
committed
fix(codecentric#4164): client reg with spring boot configured to use snake case
1 parent 8ef6a46 commit ad16bd4

File tree

3 files changed

+57
-9
lines changed

3 files changed

+57
-9
lines changed

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,24 @@ public void test_context() throws InterruptedException, UnknownHostException {
8181
wireMock.verify(request);
8282
}
8383

84+
@Test
85+
public void test_context_with_snake_case() throws InterruptedException, UnknownHostException {
86+
cdl.await();
87+
Thread.sleep(2500);
88+
String hostName = InetAddress.getLocalHost().getCanonicalHostName();
89+
String serviceHost = "http://" + hostName + ":" + getServerPort();
90+
String managementHost = "http://" + hostName + ":" + getManagementPort();
91+
RequestPatternBuilder request = postRequestedFor(urlEqualTo("/instances"));
92+
request.withHeader("Content-Type", equalTo("application/json"))
93+
.withRequestBody(matchingJsonPath("$.name", equalTo("Test-Client")))
94+
.withRequestBody(matchingJsonPath("$.health_url", equalTo(managementHost + "/mgmt/health")))
95+
.withRequestBody(matchingJsonPath("$.management_url", equalTo(managementHost + "/mgmt")))
96+
.withRequestBody(matchingJsonPath("$.service_url", equalTo(serviceHost + "/")))
97+
.withRequestBody(matchingJsonPath("$.metadata.startup", matching(".+")));
98+
99+
wireMock.verify(request);
100+
}
101+
84102
protected abstract int getServerPort();
85103

86104
protected abstract int getManagementPort();

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.junit.jupiter.api.AfterEach;
2020
import org.junit.jupiter.api.BeforeEach;
21+
import org.junit.jupiter.api.TestInfo;
2122
import org.springframework.boot.SpringApplication;
2223
import org.springframework.boot.WebApplicationType;
2324
import org.springframework.context.ConfigurableApplicationContext;
@@ -27,15 +28,22 @@ public class ClientServletApplicationTest extends AbstractClientApplicationTest
2728
private ConfigurableApplicationContext instance;
2829

2930
@BeforeEach
30-
@Override
31-
public void setUp() throws Exception {
31+
public void setUp(TestInfo testInfo) throws Exception {
3232
super.setUp();
3333

3434
SpringApplication application = new SpringApplication(TestClientApplication.class);
3535
application.setWebApplicationType(WebApplicationType.SERVLET);
36-
instance = application.run("--spring.application.name=Test-Client", "--server.port=0",
36+
if(testInfo.getDisplayName().equalsIgnoreCase("test_context_with_snake_case()")) {
37+
instance = application.run("--spring.application.name=Test-Client", "--server.port=0",
38+
"--management.endpoints.web.base-path=/mgmt", "--endpoints.health.enabled=true",
39+
"--spring.boot.admin.client.url=" + wireMock.url("/"),
40+
"--spring.jackson.property-naming-strategy=SNAKE_CASE");
41+
}
42+
else {
43+
instance = application.run("--spring.application.name=Test-Client", "--server.port=0",
3744
"--management.endpoints.web.base-path=/mgmt", "--endpoints.health.enabled=true",
3845
"--spring.boot.admin.client.url=" + wireMock.url("/"));
46+
}
3947
}
4048

4149
@AfterEach

spring-boot-admin-server/src/main/java/de/codecentric/boot/admin/server/utils/jackson/RegistrationDeserializer.java

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,20 @@
1717
package de.codecentric.boot.admin.server.utils.jackson;
1818

1919
import java.io.IOException;
20+
import java.util.HashMap;
2021
import java.util.Iterator;
2122
import java.util.Map;
2223

2324
import com.fasterxml.jackson.core.JsonParser;
25+
import com.fasterxml.jackson.core.JsonToken;
2426
import com.fasterxml.jackson.databind.DeserializationContext;
2527
import com.fasterxml.jackson.databind.JsonNode;
2628
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
2729

2830
import de.codecentric.boot.admin.server.domain.values.Registration;
2931

32+
import org.springframework.util.ObjectUtils;
33+
3034
public class RegistrationDeserializer extends StdDeserializer<Registration> {
3135

3236
private static final long serialVersionUID = 1L;
@@ -38,6 +42,7 @@ public RegistrationDeserializer() {
3842
@Override
3943
public Registration deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
4044
JsonNode node = p.readValueAsTree();
45+
Map<String, String> normalizedKvPair = getNormalizedKvPair(node);
4146
Registration.Builder builder = Registration.builder();
4247

4348
if (node.hasNonNull("name")) {
@@ -48,14 +53,14 @@ public Registration deserialize(JsonParser p, DeserializationContext ctxt) throw
4853
builder.healthUrl(url.replaceFirst("/+$", "") + "/health").managementUrl(url);
4954
}
5055
else {
51-
if (node.hasNonNull("healthUrl")) {
52-
builder.healthUrl(node.get("healthUrl").asText());
56+
if (!ObjectUtils.isEmpty(normalizedKvPair.get("healthurl"))) {
57+
builder.healthUrl(normalizedKvPair.get("healthurl"));
5358
}
54-
if (node.hasNonNull("managementUrl")) {
55-
builder.managementUrl(node.get("managementUrl").asText());
59+
if (!ObjectUtils.isEmpty(normalizedKvPair.get("managementurl"))) {
60+
builder.managementUrl(normalizedKvPair.get("managementurl"));
5661
}
57-
if (node.hasNonNull("serviceUrl")) {
58-
builder.serviceUrl(node.get("serviceUrl").asText());
62+
if (!ObjectUtils.isEmpty(normalizedKvPair.get("serviceurl"))) {
63+
builder.serviceUrl(normalizedKvPair.get("serviceurl"));
5964
}
6065
}
6166

@@ -74,4 +79,21 @@ public Registration deserialize(JsonParser p, DeserializationContext ctxt) throw
7479
return builder.build();
7580
}
7681

82+
private Map<String, String> getNormalizedKvPair(JsonNode jn) throws IOException {
83+
Map<String, String> normalizedKvPair = new HashMap<>();
84+
JsonParser jp = jn.traverse();
85+
while(!jp.isClosed()) {
86+
if(jp.nextToken() == JsonToken.FIELD_NAME) {
87+
String fieldName = jp.currentName();
88+
if(!ObjectUtils.isEmpty(fieldName)) {
89+
JsonToken jsonValueToken = jp.nextValue();
90+
if(jsonValueToken == JsonToken.VALUE_STRING) {
91+
normalizedKvPair.putIfAbsent(fieldName.replaceAll("[_-]", "").toLowerCase(), jp.getValueAsString());
92+
}
93+
}
94+
}
95+
}
96+
return normalizedKvPair;
97+
}
98+
7799
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy