Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion chaos-monkey-docs/src/main/asciidoc/changes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ Built with Spring Boot {spring-boot-version}

=== New Features
// - https://github.com/codecentric/chaos-monkey-spring-boot/pull/xxx[#xxx] Added example entry. Please don't remove.
- https://github.com/codecentric/chaos-monkey-spring-boot/pull/618[#618] Upgrade to Spring Boot 4 and Spring Cloud 2025.1

=== Contributors
This release was only possible because of these great humans ❤️:

// - https://github.com/octocat[@octocat]
- https://github.com/bmatthews68[@bmatthews68]

Thank you for your support!
4 changes: 2 additions & 2 deletions chaos-monkey-docs/src/main/asciidoc/endpoints.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html[Spr
[source,txt,subs="verbatim,attributes",role="primary"]
.application.properties:
----
management.endpoint.chaosmonkey.enabled=true
management.endpoint.chaosmonkeyjmx.enabled=true
management.endpoint.chaosmonkey.access=unrestricted
management.endpoint.chaosmonkeyjmx.access=unrestricted

# include all endpoints
management.endpoints.web.exposure.include=*
Expand Down
2 changes: 1 addition & 1 deletion chaos-monkey-docs/src/main/asciidoc/getting-started.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Start your Spring Boot application, add Chaos Monkey for Spring Boot JAR and pro
----
java -cp your-app.jar
-Dloader.path=chaos-monkey-spring-boot-{project-version}-jar-with-dependencies.jar
org.springframework.boot.loader.PropertiesLauncher
org.springframework.boot.loader.launch.PropertiesLauncher
--spring.profiles.active=chaos-monkey
--spring.config.location=file:./chaos-monkey.properties
----
Expand Down
31 changes: 28 additions & 3 deletions chaos-monkey-spring-boot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,29 @@
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<artifactId>spring-boot-starter-webmvc</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-restclient</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webclient</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
Expand All @@ -69,7 +84,7 @@
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${spring-doc.version}</version>
<scope>provided</scope>
</dependency>
Expand Down Expand Up @@ -120,6 +135,11 @@
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-health</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand All @@ -146,6 +166,11 @@
<artifactId>unleash-client-java</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-resttestclient</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
import de.codecentric.spring.boot.chaos.monkey.component.MetricType;
import de.codecentric.spring.boot.chaos.monkey.configuration.AssaultProperties;
import de.codecentric.spring.boot.chaos.monkey.configuration.ChaosMonkeySettings;
import org.jspecify.annotations.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;

import java.util.concurrent.TimeUnit;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
package de.codecentric.spring.boot.chaos.monkey.configuration;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import tools.jackson.databind.ObjectMapper;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
Expand All @@ -29,6 +28,8 @@
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.util.ClassUtils;
import tools.jackson.core.JacksonException;
import tools.jackson.databind.exc.MismatchedInputException;

@Data
public class AssaultException {
Expand Down Expand Up @@ -74,7 +75,7 @@ private Throwable getThrowable() {
try {
ThrowableCreator creator = getCreator();
instance = creator.create(getExceptionArgumentValues());
} catch (ReflectiveOperationException | ClassCastException | JsonProcessingException e) {
} catch (ReflectiveOperationException | ClassCastException | JacksonException e) {
Logger.warn("Failed to create custom exception. Fallback: Throw RuntimeException");
instance = new RuntimeException("Chaos Monkey - RuntimeException (Fallback)", e);
}
Expand Down Expand Up @@ -105,15 +106,15 @@ private List<Class<?>> getExceptionArgumentTypes() throws ClassNotFoundException
return exceptionArgumentTypes;
}

private List<Object> getExceptionArgumentValues() throws ClassNotFoundException, JsonProcessingException {
private List<Object> getExceptionArgumentValues() throws ClassNotFoundException, JacksonException {
List<Object> exceptionArgumentValues = new ArrayList<>();
for (ExceptionArgument argument : arguments) {
Class<?> classType = argument.getClassType();
String value = argument.getValue();
try {
// this mostly works for primitive values and strings
exceptionArgumentValues.add(objectMapper.convertValue(value, classType));
} catch (IllegalArgumentException e) {
} catch (MismatchedInputException | IllegalArgumentException e) {
// treat value as json encoded otherwise
exceptionArgumentValues.add(objectMapper.readValue(value, classType));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package de.codecentric.spring.boot.chaos.monkey.configuration;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
import tools.jackson.databind.ObjectMapper;
import de.codecentric.spring.boot.chaos.monkey.endpoints.dto.AssaultPropertiesUpdate;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import de.codecentric.spring.boot.chaos.monkey.watcher.advice.filter.RepositoryClassFilter;
import de.codecentric.spring.boot.chaos.monkey.watcher.advice.filter.SpringHookMethodsFilter;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.ClassFilters;
import org.springframework.aop.support.RootClassFilter;
Expand Down Expand Up @@ -96,8 +95,7 @@ public ChaosMonkeyPointcutAdvisor componentPointcutAdvisor(ChaosMonkeyBaseClassF
@ConditionalOnClass(name = "org.springframework.data.repository.Repository")
public ChaosMonkeyPointcutAdvisor repositoryPointcutAdvisor(ChaosMonkeyBaseClassFilter baseClassFilter, ChaosMonkeyRequestScope requestScope,
MetricEventPublisher eventPublisher) throws ClassNotFoundException {
@SuppressWarnings("unchecked")
val repositoryDefinition = (Class<? extends Annotation>) Class.forName("org.springframework.data.repository.RepositoryDefinition");
final var repositoryDefinition = (Class<? extends Annotation>) Class.forName("org.springframework.data.repository.RepositoryDefinition");

ClassFilter[] filters = {new RepositoryClassFilter(), new RepositoryAnnotatedClassFilter(), new AnnotationClassFilter(repositoryDefinition)};
return new ChaosMonkeyPointcutAdvisor(baseClassFilter,
Expand All @@ -107,12 +105,12 @@ public ChaosMonkeyPointcutAdvisor repositoryPointcutAdvisor(ChaosMonkeyBaseClass

@Bean
@ConditionalOnMissingBean(name = "healthIndicatorAdviceProvider")
@ConditionalOnClass(name = "org.springframework.boot.actuate.health.HealthIndicator")
@ConditionalOnClass(name = "org.springframework.boot.health.contributor.HealthIndicator")
public ChaosMonkeyPointcutAdvisor healthIndicatorAdviceProvider(ChaosMonkeyBaseClassFilter baseClassFilter, ChaosMonkeyRequestScope requestScope)
throws ClassNotFoundException {
Class<?> healthIndicatorClass = Class.forName("org.springframework.boot.actuate.health.HealthIndicator");
Class<?> healthIndicatorClass = Class.forName("org.springframework.boot.health.contributor.HealthIndicator");
return new ChaosMonkeyPointcutAdvisor(baseClassFilter, new ChaosMonkeyHealthIndicatorAdvice(requestScope, watcherProperties),
new RootClassFilter(healthIndicatorClass), new MethodNameFilter("getHealth"));
new RootClassFilter(healthIndicatorClass), new MethodNameFilter("health"));
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,7 @@
*/
package de.codecentric.spring.boot.chaos.monkey.configuration;

import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2022 the original author or authors.
* Copyright 2018-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,8 +19,8 @@
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.lang.Nullable;

@Data
@NoArgsConstructor
Expand All @@ -35,7 +35,6 @@ public class ChaosMonkeyProperties {

private String togglePrefix = "chaos.monkey";

@Nullable
public void setEnabled(boolean enabled) {
if (this.enabled != enabled) {
lastEnabledToggleTimestamp = System.currentTimeMillis();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2022 the original author or authors.
* Copyright 2018-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,12 +19,13 @@
import de.codecentric.spring.boot.chaos.monkey.configuration.WatcherProperties;
import de.codecentric.spring.boot.chaos.monkey.endpoints.dto.AssaultPropertiesUpdate;
import de.codecentric.spring.boot.chaos.monkey.endpoints.dto.ChaosMonkeyStatusResponseDto;
import org.springframework.boot.actuate.endpoint.Access;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
import org.springframework.boot.actuate.endpoint.jmx.annotation.JmxEndpoint;

/** @author Benjamin Wilms */
@JmxEndpoint(enableByDefault = false, id = "chaosmonkeyjmx")
@JmxEndpoint(defaultAccess = Access.NONE, id = "chaosmonkeyjmx")
public class ChaosMonkeyJmxEndpoint extends BaseChaosMonkeyEndpoint {

public ChaosMonkeyJmxEndpoint(ChaosMonkeySettings chaosMonkeySettings) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018-2022 the original author or authors.
* Copyright 2018-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -23,14 +23,15 @@
import de.codecentric.spring.boot.chaos.monkey.endpoints.dto.ChaosMonkeySettingsDto;
import de.codecentric.spring.boot.chaos.monkey.endpoints.dto.ChaosMonkeyStatusResponseDto;
import de.codecentric.spring.boot.chaos.monkey.endpoints.dto.WatcherPropertiesUpdate;
import org.springframework.boot.actuate.endpoint.Access;
import org.springframework.boot.actuate.endpoint.web.annotation.RestControllerEndpoint;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

@RestControllerEndpoint(enableByDefault = false, id = "chaosmonkey")
@RestControllerEndpoint(defaultAccess = Access.NONE, id = "chaosmonkey")
public class ChaosMonkeyRestEndpoint extends BaseChaosMonkeyEndpoint {

private final ChaosMonkeyRuntimeScope runtimeScope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
package de.codecentric.spring.boot.chaos.monkey.endpoints.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import tools.jackson.databind.ObjectMapper;
import de.codecentric.spring.boot.chaos.monkey.configuration.AssaultException;
import de.codecentric.spring.boot.chaos.monkey.configuration.AssaultProperties;
import de.codecentric.spring.boot.chaos.monkey.endpoints.dto.validation.AssaultExceptionConstraint;
Expand All @@ -29,8 +28,9 @@
import jakarta.validation.constraints.Min;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import org.springframework.validation.annotation.Validated;
import tools.jackson.databind.DatabindException;

/**
* Is used to update properties. Partial updates are allowed: i. e.
Expand Down Expand Up @@ -133,7 +133,7 @@ public class AssaultPropertiesUpdate {
public void applyTo(AssaultProperties t) {
try {
new ObjectMapper().updateValue(t, this);
} catch (JsonMappingException e) {
} catch (DatabindException e) {
throw new IllegalArgumentException("cannot update values", e);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -24,7 +24,7 @@
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;

@Data
@NoArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
package de.codecentric.spring.boot.chaos.monkey.endpoints.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import tools.jackson.databind.ObjectMapper;
import de.codecentric.spring.boot.chaos.monkey.configuration.WatcherProperties;
import java.util.List;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.lang.Nullable;
import org.jspecify.annotations.Nullable;
import tools.jackson.databind.DatabindException;

@Data
@NoArgsConstructor
Expand Down Expand Up @@ -62,7 +62,7 @@ public class WatcherPropertiesUpdate {
public void applyTo(WatcherProperties t) {
try {
new ObjectMapper().updateValue(t, this);
} catch (JsonMappingException e) {
} catch (DatabindException e) {
throw new IllegalArgumentException("cannot update values", e);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 the original author or authors.
* Copyright 2022-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,6 @@
*/
package de.codecentric.spring.boot.chaos.monkey.watcher.advice;

import lombok.val;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.ProceedingJoinPoint;
Expand All @@ -28,7 +27,7 @@ public abstract class AbstractChaosMonkeyAdvice implements MethodInterceptor {
@Override
public final Object invoke(MethodInvocation invocation) throws Throwable {
// this cast should always succeed within spring
val pjp = new MethodInvocationProceedingJoinPoint((ProxyMethodInvocation) invocation);
final var pjp = new MethodInvocationProceedingJoinPoint((ProxyMethodInvocation) invocation);
return invoke(pjp);
}

Expand Down
Loading