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)