mirror of
https://github.com/spring-projects/spring-petclinic.git
synced 2025-07-21 07:15:49 +00:00
jobruhnr
This commit is contained in:
parent
9244518ff9
commit
0e5c72d5ec
12 changed files with 94 additions and 103 deletions
|
@ -1,17 +1,17 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
pet-clinic:
|
||||
build: ./
|
||||
healthcheck:
|
||||
test: [ "CMD", "curl", "-f", "http://localhost:8082/" ]
|
||||
interval: 20s
|
||||
timeout: 10s
|
||||
retries: 4
|
||||
start_period: 5s
|
||||
ports:
|
||||
- "8082:8082"
|
||||
entrypoint: java -jar app.jar
|
||||
# pet-clinic:
|
||||
# build: ./
|
||||
# healthcheck:
|
||||
# test: [ "CMD", "curl", "-f", "http://localhost:8082/" ]
|
||||
# interval: 20s
|
||||
# timeout: 10s
|
||||
# retries: 4
|
||||
# start_period: 5s
|
||||
# ports:
|
||||
# - "8082:8082"
|
||||
# entrypoint: java -jar app.jar
|
||||
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
|
|
|
@ -4,28 +4,32 @@ receivers:
|
|||
grpc:
|
||||
http:
|
||||
|
||||
extensions:
|
||||
basicauth/client:
|
||||
client_auth:
|
||||
username: 738734
|
||||
password: glc_eyJvIjoiOTQzMDk3IiwibiI6Im90bHAtb3RscCIsImsiOiJEWnhpNTFsZVZWMHJYcTg5MTVqODJOOEgiLCJtIjp7InIiOiJ1cyJ9fQ==
|
||||
|
||||
exporters:
|
||||
jaeger:
|
||||
endpoint: "jaeger:14250"
|
||||
otlphttp/grafana:
|
||||
endpoint: https://otlp-gateway-prod-us-east-0.grafana.net/otlp
|
||||
auth:
|
||||
authenticator: basicauth/client
|
||||
tls:
|
||||
insecure: true
|
||||
insecure: false
|
||||
|
||||
otlp/digma:
|
||||
endpoint: ${OTLP_EXPORTER_DIGMA_COLLECTOR_API}
|
||||
tls:
|
||||
insecure: true
|
||||
prometheus:
|
||||
endpoint: "0.0.0.0:8889"
|
||||
|
||||
processors:
|
||||
batch:
|
||||
|
||||
service:
|
||||
extensions: [basicauth/client]
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
exporters: [otlp/digma, jaeger]
|
||||
processors: [batch]
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
exporters: [prometheus]
|
||||
exporters: [otlphttp/grafana,otlp/digma]
|
||||
processors: [batch]
|
|
@ -1,36 +1,6 @@
|
|||
version: "3.6"
|
||||
|
||||
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
|
||||
|
||||
grafana:
|
||||
container_name: grafana
|
||||
image: grafana/grafana-oss:latest
|
||||
ports:
|
||||
- 3000:3000
|
||||
|
||||
prometheus:
|
||||
container_name: prometheus
|
||||
image: prom/prometheus:latest
|
||||
volumes:
|
||||
- ./prometheus.yaml:/etc/prometheus/prometheus.yml
|
||||
ports:
|
||||
- "9090:9090"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
collector:
|
||||
image: otel/opentelemetry-collector-contrib
|
||||
|
@ -42,8 +12,6 @@ services:
|
|||
- "0.0.0.0:8889:8889" # METRICS
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
depends_on:
|
||||
- jaeger
|
||||
environment:
|
||||
- OTLP_EXPORTER_DIGMA_COLLECTOR_API=host.docker.internal:5050
|
||||
|
||||
|
|
5
pom.xml
5
pom.xml
|
@ -38,6 +38,11 @@
|
|||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jobrunr</groupId>
|
||||
<artifactId>jobrunr-spring-boot-3-starter</artifactId>
|
||||
<version>6.3.0</version>
|
||||
</dependency>
|
||||
<!-- Spring and Spring Boot dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -52,7 +52,6 @@ public class OwnerValidation {
|
|||
|
||||
}
|
||||
|
||||
|
||||
// This function and classes were generated by ChatGPT
|
||||
public boolean ValidateUserAccess(String usr, String pswd, String sysCode) {
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.json.JSONException;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.adapters.PetVaccinationService;
|
||||
import org.springframework.samples.petclinic.adapters.VaccinnationRecord;
|
||||
import org.springframework.samples.petclinic.owner.OwnerRepository;
|
||||
import org.springframework.samples.petclinic.owner.Pet;
|
||||
import org.springframework.samples.petclinic.owner.PetVaccine;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
@ -13,18 +14,25 @@ import org.springframework.stereotype.Component;
|
|||
import java.io.IOException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class PetVaccinationStatusService {
|
||||
|
||||
@Autowired
|
||||
private OwnerRepository ownerRepositorys;
|
||||
|
||||
@Autowired
|
||||
private PetVaccinationService adapter;
|
||||
|
||||
|
||||
@WithSpan
|
||||
public void UpdateVaccinationStatus(Pet[] pets) {
|
||||
public void updateVaccinationStatus(List<Integer> petIds) {
|
||||
|
||||
|
||||
for (Integer petId : petIds) {
|
||||
var pet = ownerRepositorys.findById(petId).getPet(petId);
|
||||
|
||||
for (Pet pet : pets) {
|
||||
try {
|
||||
var vaccinationRecords = this.adapter.allVaccines();
|
||||
for (VaccinnationRecord record : vaccinationRecords) {
|
||||
|
|
|
@ -15,29 +15,24 @@
|
|||
*/
|
||||
package org.springframework.samples.petclinic.owner;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import io.opentelemetry.instrumentation.annotations.WithSpan;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.samples.petclinic.domain.OwnerValidation;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.ErrorResponse;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.opentelemetry.api.GlobalOpenTelemetry.getTracer;
|
||||
|
||||
|
@ -56,7 +51,6 @@ class OwnerController {
|
|||
|
||||
private OwnerValidation validator;
|
||||
|
||||
|
||||
public OwnerController(OwnerRepository clinicService) {
|
||||
this.owners = clinicService;
|
||||
var otelTracer = getTracer("OwnerController");
|
||||
|
@ -64,17 +58,26 @@ class OwnerController {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@InitBinder
|
||||
public void setAllowedFields(WebDataBinder dataBinder) {
|
||||
dataBinder.setDisallowedFields("id");
|
||||
}
|
||||
|
||||
|
||||
@ModelAttribute("owner")
|
||||
public Owner findOwner(@PathVariable(name = "ownerId", required = false) Integer ownerId) {
|
||||
return ownerId == null ? new Owner() : this.owners.findById(ownerId);
|
||||
}
|
||||
|
||||
// @ExceptionHandler(NullPointerException.class)
|
||||
// @ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
// public ErrorResponse onIllegaArgumentException(RuntimeException npe){
|
||||
// return ErrorResponse.builder(npe,HttpStatus.NOT_FOUND, npe.getMessage())
|
||||
// .title("Not found")
|
||||
// .type(URI.create("https://api.bookmarks.com/errors/not-found"))
|
||||
// .build();
|
||||
//
|
||||
// }
|
||||
|
||||
@GetMapping("/owners/new")
|
||||
public String initCreationForm(Map<String, Object> model) {
|
||||
|
@ -86,6 +89,8 @@ class OwnerController {
|
|||
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@PostMapping("/owners/new")
|
||||
public String processCreationForm(@Valid Owner owner, BindingResult result) {
|
||||
if (result.hasErrors()) {
|
||||
|
@ -105,6 +110,8 @@ class OwnerController {
|
|||
return "owners/findOwners";
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping("/owners")
|
||||
public String processFindForm(@RequestParam(defaultValue = "1") int page, Owner owner, BindingResult result,
|
||||
Model model) {
|
||||
|
|
|
@ -57,6 +57,10 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
|
|||
@Transactional(readOnly = true)
|
||||
Page<Owner> findByLastName(@Param("lastName") String lastName, Pageable pageable);
|
||||
|
||||
@Query("SELECT DISTINCT owner FROM Owner owner LEFT JOIN FETCH owner.pets LEFT JOIN FETCH pets.visits")
|
||||
@Transactional(readOnly = true)
|
||||
Page<Owner> findByLastNameWithPetsAndVisits(@Param("lastName") String lastName, Pageable pageable);
|
||||
|
||||
/**
|
||||
* Retrieve an {@link Owner} from the data store by id.
|
||||
* @param id the id to search for
|
||||
|
|
|
@ -15,10 +15,13 @@
|
|||
*/
|
||||
package org.springframework.samples.petclinic.owner;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.jobrunr.scheduling.BackgroundJob;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.samples.petclinic.domain.PetVaccinationStatusService;
|
||||
|
@ -47,6 +50,7 @@ class PetController implements InitializingBean {
|
|||
|
||||
private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm";
|
||||
|
||||
|
||||
private final OwnerRepository owners;
|
||||
|
||||
@Autowired
|
||||
|
@ -54,12 +58,10 @@ class PetController implements InitializingBean {
|
|||
|
||||
private ExecutorService executorService;
|
||||
|
||||
|
||||
public PetController(OwnerRepository owners) {
|
||||
this.owners = owners;
|
||||
}
|
||||
|
||||
|
||||
@ModelAttribute("types")
|
||||
public Collection<PetType> populatePetTypes() {
|
||||
return this.owners.findPetTypes();
|
||||
|
@ -106,12 +108,13 @@ class PetController implements InitializingBean {
|
|||
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
|
||||
}
|
||||
|
||||
|
||||
this.owners.save(owner);
|
||||
this.executorService.submit(() -> {
|
||||
petVaccinationStatus.UpdateVaccinationStatus(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();
|
||||
BackgroundJob.enqueue(() -> petVaccinationStatus.updateVaccinationStatus(petIds) );
|
||||
return "redirect:/owners/{ownerId}";
|
||||
}
|
||||
|
||||
|
@ -139,4 +142,5 @@ class PetController implements InitializingBean {
|
|||
this.executorService = Executors.newFixedThreadPool(5);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,4 @@ class WelcomeController {
|
|||
return "welcome";
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
database=h2
|
||||
spring.sql.init.schema-locations=classpath*:db/${database}/schema.sql
|
||||
spring.sql.init.data-locations=classpath*:db/${database}/data.sql
|
||||
|
||||
org.jobrunr.job-scheduler.enabled=true
|
||||
org.jobrunr.background-job-server.enabled=true
|
||||
org.jobrunr.dashboard.enabled=true
|
||||
# Web
|
||||
spring.thymeleaf.mode=HTML
|
||||
|
||||
|
|
|
@ -73,7 +73,6 @@ public class OwnerControllerTests {
|
|||
|
||||
Owner owner = CreateOwner();
|
||||
|
||||
|
||||
String newPetName = faker.dog().name();
|
||||
given().contentType("multipart/form-data")
|
||||
.multiPart("id", "")
|
||||
|
@ -85,12 +84,8 @@ public class OwnerControllerTests {
|
|||
.then()
|
||||
.statusCode(Matchers.not(Matchers.greaterThan(499)));
|
||||
|
||||
|
||||
var updatedOwner = ownerRepository.findById(owner.getId());
|
||||
assertThat(updatedOwner.getPets())
|
||||
.hasSize(2)
|
||||
.extracting(Pet::getName)
|
||||
.contains(newPetName);
|
||||
assertThat(updatedOwner.getPets()).hasSize(2).extracting(Pet::getName).contains(newPetName);
|
||||
|
||||
}
|
||||
|
||||
|
@ -99,18 +94,15 @@ public class OwnerControllerTests {
|
|||
|
||||
Owner owner = CreateOwner();
|
||||
|
||||
var ownerLinkMatcher =
|
||||
String.format("**.findAll { node -> node.@href=='/owners/%s'}",
|
||||
owner.getId());
|
||||
var ownerLinkMatcher = String.format("**.findAll { node -> node.@href=='/owners/%s'}", owner.getId());
|
||||
|
||||
given()
|
||||
.contentType(ContentType.JSON)
|
||||
given().contentType(ContentType.JSON)
|
||||
.when()
|
||||
.get("/owners")
|
||||
.then()
|
||||
.contentType(ContentType.HTML)
|
||||
.statusCode(200)
|
||||
.body(ownerLinkMatcher,Matchers.notNullValue());
|
||||
.body(ownerLinkMatcher, Matchers.notNullValue());
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue