diff --git a/2025-05/spring-31-data-rest/pom.xml b/2025-05/spring-31-data-rest/pom.xml new file mode 100644 index 00000000..4ebf7d7e --- /dev/null +++ b/2025-05/spring-31-data-rest/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + ru.otus + spring-31-data-rest + 1.0 + + pom + + + spring-31-exercise + spring-31-solution + + diff --git a/2025-05/spring-31-data-rest/requests.http b/2025-05/spring-31-data-rest/requests.http new file mode 100644 index 00000000..e6839f0a --- /dev/null +++ b/2025-05/spring-31-data-rest/requests.http @@ -0,0 +1,79 @@ +### "Index page" +GET http://localhost:8080/actuator + +### Список бинов, созданных в приложении +GET http://localhost:8080/actuator/beans + +### Информация о приложении +GET http://localhost:8080/actuator/info + +### Все @ConfigurationProperties +GET http://localhost:8080/actuator/configprops + +### Все перепенные окружения +GET http://localhost:8080/actuator/env + +### Список логгеров +GET http://localhost:8080/actuator/loggers + +### Конфигурация конкретного логгера +GET http://localhost:8080/actuator/loggers/org.springframework + +### Изменение уровня логгирования в runtime +POST http://localhost:8080/actuator/loggers/org.springframework +Content-Type: application/json + +{ + "configuredLevel": "TRACE" +} + +### Healthchecks +GET http://localhost:8080/actuator/health + +### Собственный healthcheck +GET http://localhost:8080/actuator/health/my + +### Список метрик +GET http://localhost:8080/actuator/metrics + +### Состояние подключений к БД +GET http://localhost:8080/actuator/metrics/hikaricp.connections.usage + +### Загрузка CPU приложением +GET http://localhost:8080/actuator/metrics/process.cpu.usage + +### Используемая JVM память +GET http://localhost:8080/actuator/metrics/jvm.memory.used + +### Получение данных о запросах +# Дополнительно можно настроить SLA, персентили и т.д. +# причём для отдельных запросов +GET http://localhost:8080/actuator/metrics/http.server.requests + +### А вот все метрики для Promehteus +GET http://localhost:8080/actuator/prometheus + + +### Spring Data REST - Single entity +GET http://localhost:8080/person/40 + +### Spring Data REST - Collection +GET http://localhost:8080/person + +### Add Alex +POST http://localhost:8080/person +Content-Type: application/json + +{ + "name": "Alex" +} + +### Rename Ivan +PATCH http://localhost:8080/person/1 +Content-Type: application/json + +{ + "name": "Anton" +} + +### diff --git a/2025-05/spring-31-data-rest/spring-31-exercise/pom.xml b/2025-05/spring-31-data-rest/spring-31-exercise/pom.xml new file mode 100644 index 00000000..6b3bfd88 --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-exercise/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + ru.otus + spring-31-exercise + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 3.1.3 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.h2database + h2 + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-data-rest + + + + org.springframework.boot + spring-boot-starter-actuator + + + io.micrometer + micrometer-registry-prometheus + + + + org.springframework.data + spring-data-rest-hal-explorer + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/App.java b/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/App.java new file mode 100644 index 00000000..126c5eec --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/App.java @@ -0,0 +1,31 @@ +package ru.otus.spring.microservice; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import jakarta.annotation.PostConstruct; +import ru.otus.spring.microservice.domain.Person; +import ru.otus.spring.microservice.repostory.PersonRepository; + + +@SpringBootApplication +@EnableWebMvc +public class App { + + @Autowired + private PersonRepository repository; + + public static void main(String[] args) { + SpringApplication.run(App.class); + } + + @PostConstruct + public void init() { + for(int i = 0 ; i < 1000; ++i) { + repository.save(new Person("Ivan")); + repository.save(new Person("Maria")); + } + } +} diff --git a/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/domain/Person.java b/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/domain/Person.java new file mode 100644 index 00000000..05922c3b --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/domain/Person.java @@ -0,0 +1,38 @@ +package ru.otus.spring.microservice.domain; + + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +@Entity +public class Person { + + @Id + @GeneratedValue + private int id; + private String name; + + public Person() { + } + + public Person(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java b/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java new file mode 100644 index 00000000..ef89fee3 --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-exercise/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java @@ -0,0 +1,19 @@ +package ru.otus.spring.microservice.repostory; + +import java.util.List; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; + +import ru.otus.spring.microservice.domain.Person; + +@RepositoryRestResource(path = "person") +public interface PersonRepository extends CrudRepository { + + @Override + List findAll(); + + @RestResource(path = "names") + List findByName(String name); +} diff --git a/2025-05/spring-31-data-rest/spring-31-exercise/src/main/resources/application.yml b/2025-05/spring-31-data-rest/spring-31-exercise/src/main/resources/application.yml new file mode 100644 index 00000000..e69de29b diff --git a/2025-05/spring-31-data-rest/spring-31-solution/pom.xml b/2025-05/spring-31-data-rest/spring-31-solution/pom.xml new file mode 100644 index 00000000..aeee948b --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-solution/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + ru.otus + spring-31-solution + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 3.1.3 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + com.h2database + h2 + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.springframework.boot + spring-boot-starter-data-rest + + + + org.springframework.boot + spring-boot-starter-actuator + + + io.micrometer + micrometer-registry-prometheus + + + + org.springframework.data + spring-data-rest-hal-explorer + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/App.java b/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/App.java new file mode 100644 index 00000000..126c5eec --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/App.java @@ -0,0 +1,31 @@ +package ru.otus.spring.microservice; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import jakarta.annotation.PostConstruct; +import ru.otus.spring.microservice.domain.Person; +import ru.otus.spring.microservice.repostory.PersonRepository; + + +@SpringBootApplication +@EnableWebMvc +public class App { + + @Autowired + private PersonRepository repository; + + public static void main(String[] args) { + SpringApplication.run(App.class); + } + + @PostConstruct + public void init() { + for(int i = 0 ; i < 1000; ++i) { + repository.save(new Person("Ivan")); + repository.save(new Person("Maria")); + } + } +} diff --git a/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/actuators/RandomHealthIndicator.java b/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/actuators/RandomHealthIndicator.java new file mode 100644 index 00000000..53bc81a1 --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/actuators/RandomHealthIndicator.java @@ -0,0 +1,27 @@ +package ru.otus.spring.microservice.actuators; + +import java.util.Random; + +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; +import org.springframework.boot.actuate.health.Status; +import org.springframework.stereotype.Component; + +@Component +public class RandomHealthIndicator implements HealthIndicator { + + private final Random random = new Random(); + + @Override + public Health health() { + boolean serverIsDown = random.nextBoolean(); + if (serverIsDown) { + return Health.down() + .status(Status.DOWN) + .withDetail("message", "Караул!") + .build(); + } else { + return Health.up().withDetail("message", "Ура, товарищи!").build(); + } + } +} diff --git a/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/domain/Person.java b/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/domain/Person.java new file mode 100644 index 00000000..05922c3b --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/domain/Person.java @@ -0,0 +1,38 @@ +package ru.otus.spring.microservice.domain; + + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +@Entity +public class Person { + + @Id + @GeneratedValue + private int id; + private String name; + + public Person() { + } + + public Person(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java b/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java new file mode 100644 index 00000000..80888701 --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-solution/src/main/java/ru/otus/spring/microservice/repostory/PersonRepository.java @@ -0,0 +1,19 @@ +package ru.otus.spring.microservice.repostory; + +import java.util.List; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; + +import ru.otus.spring.microservice.domain.Person; + +@RepositoryRestResource(path = "person") +public interface PersonRepository extends CrudRepository { + + @Override + List findAll(); + + @RestResource(path = "names", rel = "names") + List findByName(String name); +} diff --git a/2025-05/spring-31-data-rest/spring-31-solution/src/main/resources/application.yml b/2025-05/spring-31-data-rest/spring-31-solution/src/main/resources/application.yml new file mode 100644 index 00000000..fae6e3e7 --- /dev/null +++ b/2025-05/spring-31-data-rest/spring-31-solution/src/main/resources/application.yml @@ -0,0 +1,14 @@ +management: + endpoints: + web: + exposure: + include: "*" + endpoint: + health: + show-details: always + health: + defaults: + enabled: true +spring: + jmx: + enabled: true \ No newline at end of file