mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-21 07:15:49 +00:00
updated
This commit is contained in:
parent
0e5c72d5ec
commit
bfec3b0cd5
10 changed files with 122 additions and 62 deletions
|
@ -11,6 +11,10 @@ extensions:
|
||||||
password: glc_eyJvIjoiOTQzMDk3IiwibiI6Im90bHAtb3RscCIsImsiOiJEWnhpNTFsZVZWMHJYcTg5MTVqODJOOEgiLCJtIjp7InIiOiJ1cyJ9fQ==
|
password: glc_eyJvIjoiOTQzMDk3IiwibiI6Im90bHAtb3RscCIsImsiOiJEWnhpNTFsZVZWMHJYcTg5MTVqODJOOEgiLCJtIjp7InIiOiJ1cyJ9fQ==
|
||||||
|
|
||||||
exporters:
|
exporters:
|
||||||
|
otlp/jaeger:
|
||||||
|
endpoint: "jaeger:4320"
|
||||||
|
tls:
|
||||||
|
insecure: true
|
||||||
otlphttp/grafana:
|
otlphttp/grafana:
|
||||||
endpoint: https://otlp-gateway-prod-us-east-0.grafana.net/otlp
|
endpoint: https://otlp-gateway-prod-us-east-0.grafana.net/otlp
|
||||||
auth:
|
auth:
|
||||||
|
@ -31,5 +35,5 @@ service:
|
||||||
pipelines:
|
pipelines:
|
||||||
traces:
|
traces:
|
||||||
receivers: [otlp]
|
receivers: [otlp]
|
||||||
exporters: [otlphttp/grafana,otlp/digma]
|
exporters: [otlphttp/grafana,otlp/digma,otlp/jaeger]
|
||||||
processors: [batch]
|
processors: [batch]
|
|
@ -1,6 +1,21 @@
|
||||||
version: "3.6"
|
version: "3.6"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
jaeger:
|
||||||
|
image: jaegertracing/all-in-one:latest
|
||||||
|
container_name: jaeger
|
||||||
|
volumes:
|
||||||
|
- badger_data:/badger
|
||||||
|
ports:
|
||||||
|
- "16686:16686"
|
||||||
|
- "14250"
|
||||||
|
- "0.0.0.0:14268:14268"
|
||||||
|
environment:
|
||||||
|
- SPAN_STORAGE_TYPE=badger
|
||||||
|
- BADGER_EPHEMERAL=false
|
||||||
|
- BADGER_SPAN_STORE_TTL=2000h
|
||||||
|
- BADGER_DIRECTORY_VALUE=/badger/data
|
||||||
|
- BADGER_DIRECTORY_KEY=/badger/key
|
||||||
|
|
||||||
collector:
|
collector:
|
||||||
image: otel/opentelemetry-collector-contrib
|
image: otel/opentelemetry-collector-contrib
|
||||||
|
@ -8,10 +23,12 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- ./collector-config.yaml:/otel-local-config.yaml
|
- ./collector-config.yaml:/otel-local-config.yaml
|
||||||
ports:
|
ports:
|
||||||
- "0.0.0.0:4317:4317" # OTLP receiver
|
- "0.0.0.0:4318:4318" # HTTP OTLP receiver
|
||||||
- "0.0.0.0:8889:8889" # METRICS
|
- "0.0.0.0:8889:8889" # METRICS
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.docker.internal:host-gateway"
|
- "host.docker.internal:host-gateway"
|
||||||
|
depends_on:
|
||||||
|
- jaeger
|
||||||
environment:
|
environment:
|
||||||
- OTLP_EXPORTER_DIGMA_COLLECTOR_API=host.docker.internal:5050
|
- OTLP_EXPORTER_DIGMA_COLLECTOR_API=host.docker.internal:5050
|
||||||
|
|
||||||
|
|
33
pom.xml
33
pom.xml
|
@ -40,14 +40,10 @@
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jobrunr</groupId>
|
<groupId>org.jobrunr</groupId>
|
||||||
<artifactId>jobrunr-spring-boot-3-starter</artifactId>
|
<artifactId>jobrunr-pro-spring-boot-3-starter</artifactId>
|
||||||
<version>6.3.0</version>
|
<version>6.3.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Spring and Spring Boot dependencies -->
|
<!-- Spring and Spring Boot dependencies -->
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-cache</artifactId>
|
<artifactId>spring-boot-starter-cache</artifactId>
|
||||||
|
@ -111,11 +107,6 @@
|
||||||
<artifactId>postgresql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>io.micrometer</groupId>
|
|
||||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<!-- caching -->
|
<!-- caching -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.cache</groupId>
|
<groupId>javax.cache</groupId>
|
||||||
|
@ -168,6 +159,22 @@
|
||||||
<artifactId>android-json</artifactId>
|
<artifactId>android-json</artifactId>
|
||||||
<version>0.0.20131108.vaadin1</version>
|
<version>0.0.20131108.vaadin1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.opentelemetry</groupId>
|
||||||
|
<artifactId>opentelemetry-exporter-otlp</artifactId>
|
||||||
|
<version>1.26.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.micrometer</groupId>
|
||||||
|
<artifactId>micrometer-tracing-bridge-otel</artifactId>
|
||||||
|
<version>1.1.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.digma-ai</groupId>
|
||||||
|
<artifactId>digma-spring-boot-micrometer-tracing-autoconf</artifactId>
|
||||||
|
<version>0.7.4</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
@ -313,6 +320,10 @@
|
||||||
<enabled>false</enabled>
|
<enabled>false</enabled>
|
||||||
</snapshots>
|
</snapshots>
|
||||||
</repository>
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>JobRunrPro</id>
|
||||||
|
<url>https://repo.jobrunr.io/private-trials-202310/</url>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<pluginRepositories>
|
<pluginRepositories>
|
||||||
|
|
|
@ -53,6 +53,7 @@ public class OwnerValidation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function and classes were generated by ChatGPT
|
// This function and classes were generated by ChatGPT
|
||||||
|
@WithSpan
|
||||||
public boolean ValidateUserAccess(String usr, String pswd, String sysCode) {
|
public boolean ValidateUserAccess(String usr, String pswd, String sysCode) {
|
||||||
|
|
||||||
UserNameMustStartWithR(usr);
|
UserNameMustStartWithR(usr);
|
||||||
|
@ -162,8 +163,41 @@ public class OwnerValidation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithSpan
|
public boolean PerformValidationFlow(String usr, String pswd, String sysCode) {
|
||||||
public void PerformValidationFlow(Owner owner) {
|
UserNameMustStartWithR(usr);
|
||||||
|
boolean vldUsr = usrValSvc.vldtUsr(usr);
|
||||||
|
if (!vldUsr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean vldPswd = pwdUtils.vldtPswd(usr, pswd);
|
||||||
|
if (!vldPswd) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean vldUsrRole = roleSvc.vldtUsrRole(usr, sysCode);
|
||||||
|
if (!vldUsrRole) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean is2FASuccess = twoFASvc.init2FA(usr);
|
||||||
|
if (!is2FASuccess) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean is2FATokenValid = false;
|
||||||
|
int retry = 0;
|
||||||
|
while (retry < 3 && !is2FATokenValid) {
|
||||||
|
String token = twoFASvc.getTokenInput();
|
||||||
|
is2FATokenValid = twoFASvc.vldtToken(usr, token);
|
||||||
|
retry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is2FATokenValid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,15 +15,10 @@ public class PasswordUtils {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithSpan
|
|
||||||
public String encPswd(String pswd) {
|
public String encPswd(String pswd) {
|
||||||
try {
|
|
||||||
Thread.sleep(300);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.springframework.samples.petclinic.domain;
|
package org.springframework.samples.petclinic.domain;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.Span;
|
import io.opentelemetry.api.trace.Span;
|
||||||
|
import io.opentelemetry.api.trace.Tracer;
|
||||||
import io.opentelemetry.instrumentation.annotations.WithSpan;
|
import io.opentelemetry.instrumentation.annotations.WithSpan;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -19,19 +20,24 @@ import java.util.List;
|
||||||
@Component
|
@Component
|
||||||
public class PetVaccinationStatusService {
|
public class PetVaccinationStatusService {
|
||||||
|
|
||||||
|
public record UpdateVaccineStatusRequest(int ownerId, int petId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private OwnerRepository ownerRepositorys;
|
private OwnerRepository ownerRepositorys;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PetVaccinationService adapter;
|
private PetVaccinationService adapter;
|
||||||
|
|
||||||
|
|
||||||
@WithSpan
|
@WithSpan
|
||||||
public void updateVaccinationStatus(List<Integer> petIds) {
|
public void updateVaccinationStatus(List<UpdateVaccineStatusRequest> updateVaccineStatusRequests) {
|
||||||
|
|
||||||
|
|
||||||
for (Integer petId : petIds) {
|
for (UpdateVaccineStatusRequest request : updateVaccineStatusRequests) {
|
||||||
var pet = ownerRepositorys.findById(petId).getPet(petId);
|
var owner = ownerRepositorys.findById(request.ownerId);
|
||||||
|
|
||||||
|
var pet = owner.getPet(request.petId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var vaccinationRecords = this.adapter.allVaccines();
|
var vaccinationRecords = this.adapter.allVaccines();
|
||||||
|
|
|
@ -63,7 +63,6 @@ class OwnerController {
|
||||||
dataBinder.setDisallowedFields("id");
|
dataBinder.setDisallowedFields("id");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ModelAttribute("owner")
|
@ModelAttribute("owner")
|
||||||
public Owner findOwner(@PathVariable(name = "ownerId", required = false) Integer ownerId) {
|
public Owner findOwner(@PathVariable(name = "ownerId", required = false) Integer ownerId) {
|
||||||
return ownerId == null ? new Owner() : this.owners.findById(ownerId);
|
return ownerId == null ? new Owner() : this.owners.findById(ownerId);
|
||||||
|
@ -89,15 +88,13 @@ class OwnerController {
|
||||||
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/owners/new")
|
@PostMapping("/owners/new")
|
||||||
public String processCreationForm(@Valid Owner owner, BindingResult result) {
|
public String processCreationForm(@Valid Owner owner, BindingResult result) {
|
||||||
if (result.hasErrors()) {
|
if (result.hasErrors()) {
|
||||||
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
||||||
}
|
}
|
||||||
validator.ValidateOwnerWithExternalService(owner);
|
validator.ValidateOwnerWithExternalService(owner);
|
||||||
validator.PerformValidationFlow(owner);
|
// validator.PerformValidationFlow(owner);
|
||||||
|
|
||||||
validator.checkOwnerValidity(owner);
|
validator.checkOwnerValidity(owner);
|
||||||
this.owners.save(owner);
|
this.owners.save(owner);
|
||||||
|
@ -110,8 +107,6 @@ class OwnerController {
|
||||||
return "owners/findOwners";
|
return "owners/findOwners";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/owners")
|
@GetMapping("/owners")
|
||||||
public String processFindForm(@RequestParam(defaultValue = "1") int page, Owner owner, BindingResult result,
|
public String processFindForm(@RequestParam(defaultValue = "1") int page, Owner owner, BindingResult result,
|
||||||
Model model) {
|
Model model) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.springframework.samples.petclinic.owner;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
@ -50,7 +51,6 @@ class PetController implements InitializingBean {
|
||||||
|
|
||||||
private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm";
|
private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm";
|
||||||
|
|
||||||
|
|
||||||
private final OwnerRepository owners;
|
private final OwnerRepository owners;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -97,7 +97,8 @@ class PetController implements InitializingBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/pets/new")
|
@PostMapping("/pets/new")
|
||||||
public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult result, ModelMap model) {
|
public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult result, ModelMap model)
|
||||||
|
throws ExecutionException, InterruptedException {
|
||||||
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) {
|
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) {
|
||||||
result.rejectValue("name", "duplicate", "already exists");
|
result.rejectValue("name", "duplicate", "already exists");
|
||||||
}
|
}
|
||||||
|
@ -109,12 +110,18 @@ class PetController implements InitializingBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.owners.save(owner);
|
this.owners.save(owner);
|
||||||
var pets = owner.getPets().toArray(Pet[]::new);
|
// var pets = owner.getPets().toArray(Pet[]::new);
|
||||||
// executorService.submit(
|
|
||||||
// () -> petVaccinationStatus.updateVaccinationStatus(pets));
|
|
||||||
|
|
||||||
var petIds = owner.getPets().stream().map(Pet::getId).toList();
|
var petRequests = owner.getPets()
|
||||||
BackgroundJob.enqueue(() -> petVaccinationStatus.updateVaccinationStatus(petIds) );
|
.stream()
|
||||||
|
.map(x -> new PetVaccinationStatusService.UpdateVaccineStatusRequest(owner.getId(), x.getId()))
|
||||||
|
.toList();
|
||||||
|
// executorService.submit(() ->
|
||||||
|
// petVaccinationStatus.updateVaccinationStatus(petRequests)).get();
|
||||||
|
executorService.submit(() -> petVaccinationStatus.updateVaccinationStatus(petRequests));
|
||||||
|
//
|
||||||
|
// BackgroundJob.enqueue(() ->
|
||||||
|
// petVaccinationStatus.updateVaccinationStatus(petRequests));
|
||||||
return "redirect:/owners/{ownerId}";
|
return "redirect:/owners/{ownerId}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@ spring.sql.init.data-locations=classpath*:db/${database}/data.sql
|
||||||
org.jobrunr.job-scheduler.enabled=true
|
org.jobrunr.job-scheduler.enabled=true
|
||||||
org.jobrunr.background-job-server.enabled=true
|
org.jobrunr.background-job-server.enabled=true
|
||||||
org.jobrunr.dashboard.enabled=true
|
org.jobrunr.dashboard.enabled=true
|
||||||
|
org.jobrunr.metrics.otel-observability.enabled=true
|
||||||
|
org.jobrunr.metrics.enabled=true
|
||||||
|
|
||||||
# Web
|
# Web
|
||||||
spring.thymeleaf.mode=HTML
|
spring.thymeleaf.mode=HTML
|
||||||
|
|
||||||
|
|
|
@ -38,24 +38,12 @@ public class OwnerControllerTests {
|
||||||
@LocalServerPort
|
@LocalServerPort
|
||||||
private Integer port;
|
private Integer port;
|
||||||
|
|
||||||
@BeforeAll
|
|
||||||
static void beforeAll() {
|
|
||||||
postgres.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterAll
|
|
||||||
static void afterAll() {
|
|
||||||
postgres.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Container
|
@Container
|
||||||
@ServiceConnection
|
@ServiceConnection
|
||||||
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15-alpine");
|
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15-alpine");
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
// ownerRepository.deleteAll();
|
|
||||||
|
|
||||||
RestAssured.baseURI = "http://localhost:" + port;
|
RestAssured.baseURI = "http://localhost:" + port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue