This commit is contained in:
Roni Dover 2023-09-19 23:09:31 -07:00
parent 9244518ff9
commit 0e5c72d5ec
12 changed files with 94 additions and 103 deletions

View file

@ -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

View file

@ -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]

View file

@ -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

View file

@ -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>

View file

@ -52,7 +52,6 @@ public class OwnerValidation {
}
// This function and classes were generated by ChatGPT
public boolean ValidateUserAccess(String usr, String pswd, String sysCode) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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

View file

@ -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);
}
}

View file

@ -28,6 +28,4 @@ class WelcomeController {
return "welcome";
}
}

View file

@ -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

View file

@ -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,12 +94,9 @@ 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()