forked from codecentric/spring-boot-admin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Jackson Module for Spring Boot Admin
closes codecentric#1348
- Loading branch information
Showing
9 changed files
with
243 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
...a/de/codecentric/boot/admin/server/utils/jackson/InstanceEndpointsDetectedEventMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package de.codecentric.boot.admin.server.utils.jackson; | ||
|
||
import java.time.Instant; | ||
|
||
import com.fasterxml.jackson.annotation.JsonCreator; | ||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceEndpointsDetectedEvent; | ||
import de.codecentric.boot.admin.server.domain.values.Endpoints; | ||
import de.codecentric.boot.admin.server.domain.values.InstanceId; | ||
|
||
/** | ||
* Jackson Mixin for {@link InstanceEndpointsDetectedEvent}. | ||
*/ | ||
public class InstanceEndpointsDetectedEventMixin { | ||
|
||
@JsonCreator | ||
public InstanceEndpointsDetectedEventMixin(@JsonProperty("instance") InstanceId instance, @JsonProperty("version") long version, | ||
@JsonProperty("timestamp") Instant timestamp, @JsonProperty("endpoints") Endpoints endpoints) { | ||
} | ||
} | ||
|
34 changes: 34 additions & 0 deletions
34
...rver/src/main/java/de/codecentric/boot/admin/server/utils/jackson/InstanceEventMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package de.codecentric.boot.admin.server.utils.jackson; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
import com.fasterxml.jackson.annotation.JsonSubTypes; | ||
import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceDeregisteredEvent; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceEndpointsDetectedEvent; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceEvent; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceInfoChangedEvent; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceRegisteredEvent; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceRegistrationUpdatedEvent; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceStatusChangedEvent; | ||
|
||
/** | ||
* Jackson Mixin class helps in serialize/deserialize {@link InstanceEvent}s. | ||
* | ||
* @author Stefan Rempfer | ||
*/ | ||
@JsonTypeInfo( | ||
use = JsonTypeInfo.Id.NAME, | ||
include = JsonTypeInfo.As.EXISTING_PROPERTY, | ||
property = "type") | ||
@JsonSubTypes({ | ||
@JsonSubTypes.Type(value = InstanceEndpointsDetectedEvent.class, name = "ENDPOINTS_DETECTED"), | ||
@JsonSubTypes.Type(value = InstanceRegistrationUpdatedEvent.class, name = "REGISTRATION_UPDATED"), | ||
@JsonSubTypes.Type(value = InstanceInfoChangedEvent.class, name = "INFO_CHANGED"), | ||
@JsonSubTypes.Type(value = InstanceDeregisteredEvent.class, name = "DEREGISTERED"), | ||
@JsonSubTypes.Type(value = InstanceRegisteredEvent.class, name = "REGISTERED"), | ||
@JsonSubTypes.Type(value = InstanceStatusChangedEvent.class, name = "STATUS_CHANGED") | ||
}) | ||
@JsonIgnoreProperties(ignoreUnknown = true) | ||
public abstract class InstanceEventMixin { | ||
|
||
} |
49 changes: 49 additions & 0 deletions
49
...r/src/main/java/de/codecentric/boot/admin/server/utils/jackson/SpringBootAdminModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package de.codecentric.boot.admin.server.utils.jackson; | ||
|
||
import com.fasterxml.jackson.core.Version; | ||
import com.fasterxml.jackson.databind.module.SimpleDeserializers; | ||
import com.fasterxml.jackson.databind.module.SimpleModule; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceEndpointsDetectedEvent; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceEvent; | ||
import de.codecentric.boot.admin.server.domain.values.Registration; | ||
|
||
/** | ||
* Jackson module for spring-boot-admin. This module register {@link InstanceEventMixin}. | ||
* In order to use this module just add this modules into your ObjectMapper configuration. | ||
* | ||
* <pre> | ||
* ObjectMapper mapper = new ObjectMapper(); | ||
* mapper.registerModule(new SpringBootAdminModule()); | ||
* mapper.registerModule(new JavaTimeModule()); | ||
* </pre> | ||
* | ||
* @author Stefan Rempfer | ||
*/ | ||
public class SpringBootAdminModule extends SimpleModule { | ||
|
||
private final String[] metadataKeyPatterns; | ||
|
||
/** | ||
* Constructs the module with a pattern for metadata keys. | ||
* The values of the matched metadata keys will be sanitized before serializing to json. | ||
* | ||
* @param metadataKeyPatterns pattern for metadata keys which should be sanitized | ||
*/ | ||
public SpringBootAdminModule(String[] metadataKeyPatterns) { | ||
super(SpringBootAdminModule.class.getName(), new Version(1, 0, 0, null, null, null)); | ||
this.metadataKeyPatterns = metadataKeyPatterns; | ||
} | ||
|
||
@Override | ||
public void setupModule(SetupContext context) { | ||
SimpleDeserializers simpleDeserializers = new SimpleDeserializers(); | ||
simpleDeserializers.addDeserializer(Registration.class, new RegistrationDeserializer()); | ||
context.addDeserializers(simpleDeserializers); | ||
|
||
context.addBeanSerializerModifier( | ||
new RegistrationBeanSerializerModifier(new SanitizingMapSerializer(metadataKeyPatterns))); | ||
|
||
context.setMixInAnnotations(InstanceEvent.class, InstanceEventMixin.class); | ||
context.setMixInAnnotations(InstanceEndpointsDetectedEvent.class, InstanceEndpointsDetectedEventMixin.class); | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
.../src/test/java/de/codecentric/boot/admin/server/utils/jackson/InstanceEventMixinTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package de.codecentric.boot.admin.server.utils.jackson; | ||
|
||
import java.time.Instant; | ||
import java.time.temporal.ChronoUnit; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceEndpointsDetectedEvent; | ||
import de.codecentric.boot.admin.server.domain.events.InstanceRegistrationUpdatedEvent; | ||
import de.codecentric.boot.admin.server.domain.values.Endpoint; | ||
import de.codecentric.boot.admin.server.domain.values.Endpoints; | ||
import de.codecentric.boot.admin.server.domain.values.InstanceId; | ||
import de.codecentric.boot.admin.server.domain.values.Registration; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
public class InstanceEventMixinTest { | ||
|
||
private final ObjectMapper objectMapper; | ||
|
||
public InstanceEventMixinTest() { | ||
SpringBootAdminModule springBootAdminJacksonModule = new SpringBootAdminModule(new String[] { ".*password$" }); | ||
JavaTimeModule javaTimeModule = new JavaTimeModule(); | ||
objectMapper = Jackson2ObjectMapperBuilder.json().modules(springBootAdminJacksonModule, javaTimeModule).build(); | ||
} | ||
|
||
@Test | ||
public void verifySerializeOfInstanceId() throws JsonProcessingException { | ||
InstanceId id = InstanceId.of("test123"); | ||
String json = objectMapper.writeValueAsString(id); | ||
assertThat(json).isEqualTo("\"test123\""); | ||
} | ||
|
||
@Test | ||
public void verifyDeserializeOfInstanceId() throws JsonProcessingException { | ||
InstanceId id = objectMapper.readValue("\"test123\"", InstanceId.class); | ||
assertThat(id).isEqualTo(InstanceId.of("test123")); | ||
} | ||
|
||
@Nested | ||
class InstanceEndpointsDetectedEventTests { | ||
static final String INSTANCE_ENDPOINTS_DETECTED_EVENT_JSON = | ||
"{\"instance\":\"test123\",\"version\":12345678,\"timestamp\":1587751031.000000000,\"endpoints\":[" | ||
+ "{\"id\":\"health\",\"url\":\"http://localhost:8080/health\"}," | ||
+ "{\"id\":\"info\",\"url\":\"http://localhost:8080/info\"}" | ||
+ "],\"type\":\"ENDPOINTS_DETECTED\"}"; | ||
|
||
@Test | ||
public void verifySerialize() throws JsonProcessingException { | ||
InstanceId id = InstanceId.of("test123"); | ||
Instant timestamp = Instant.ofEpochSecond(1587751031).truncatedTo(ChronoUnit.SECONDS); | ||
Endpoints endpoints = Endpoints.single("info", "http://localhost:8080/info") | ||
.withEndpoint("health", "http://localhost:8080/health"); | ||
|
||
InstanceEndpointsDetectedEvent event = new InstanceEndpointsDetectedEvent(id, 12345678L, timestamp, endpoints); | ||
String json = objectMapper.writeValueAsString(event); | ||
assertThat(json).isEqualTo(INSTANCE_ENDPOINTS_DETECTED_EVENT_JSON); | ||
} | ||
|
||
@Test | ||
public void verifyDeserialize() throws JsonProcessingException { | ||
InstanceEndpointsDetectedEvent event = objectMapper | ||
.readValue(INSTANCE_ENDPOINTS_DETECTED_EVENT_JSON, InstanceEndpointsDetectedEvent.class); | ||
assertThat(event.getInstance()).isEqualTo(InstanceId.of("test123")); | ||
assertThat(event.getVersion()).isEqualTo(12345678L); | ||
assertThat(event.getTimestamp()) | ||
.isEqualTo(Instant.ofEpochSecond(1587751031).truncatedTo(ChronoUnit.SECONDS)); | ||
Endpoints endpoints = event.getEndpoints(); | ||
assertThat(endpoints).contains(Endpoint.of("info", "http://localhost:8080/info"), | ||
Endpoint.of("health", "http://localhost:8080/health")); | ||
} | ||
} | ||
|
||
@Nested | ||
class InstanceRegistrationUpdatedEventTest { | ||
|
||
static final String INSTANCE_REGISTRATION_UPDATED_EVENT_JSON = | ||
"{\"instance\":\"test123\",\"version\":12345678,\"timestamp\":1587751031.000000000,\"registration\":{" | ||
+ "\"name\":\"test\"," | ||
+ "\"managementUrl\":\"http://localhost:8080/management\"," | ||
+ "\"healthUrl\":\"http://localhost:8080/health\"," | ||
+ "\"serviceUrl\":\"http://localhost:8080/servie\"," | ||
+ "\"source\":\"dummy-source\"" | ||
+ ",\"metadata\":{\"PASSWORD\":\"******\",\"user\":\"humptydumpty\"}}," | ||
+ "\"type\":\"REGISTRATION_UPDATED\"}"; | ||
|
||
@Test | ||
public void verifySerialize() throws JsonProcessingException { | ||
InstanceId id = InstanceId.of("test123"); | ||
Instant timestamp = Instant.ofEpochSecond(1587751031).truncatedTo(ChronoUnit.SECONDS); | ||
Registration registration = Registration.create("test", "http://localhost:8080/health") | ||
.managementUrl("http://localhost:8080/management") | ||
.serviceUrl("http://localhost:8080/servie") | ||
.source("dummy-source") | ||
.metadata("PASSWORD", "qwertz123") | ||
.metadata("user", "humptydumpty") | ||
.build(); | ||
|
||
InstanceRegistrationUpdatedEvent event = new InstanceRegistrationUpdatedEvent(id, 12345678L, timestamp, registration); | ||
String json = objectMapper.writeValueAsString(event); | ||
assertThat(json).isEqualTo(INSTANCE_REGISTRATION_UPDATED_EVENT_JSON); | ||
} | ||
|
||
@Test | ||
public void verifyDeserialize() throws JsonProcessingException { | ||
InstanceRegistrationUpdatedEvent event = objectMapper | ||
.readValue(INSTANCE_REGISTRATION_UPDATED_EVENT_JSON, InstanceRegistrationUpdatedEvent.class); | ||
assertThat(event.getInstance()).isEqualTo(InstanceId.of("test123")); | ||
assertThat(event.getVersion()).isEqualTo(12345678L); | ||
assertThat(event.getTimestamp()) | ||
.isEqualTo(Instant.ofEpochSecond(1587751031).truncatedTo(ChronoUnit.SECONDS)); | ||
Registration registration = event.getRegistration(); | ||
} | ||
} | ||
|
||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters