my changes

This commit is contained in:
Roni Dover 2023-08-09 00:06:16 -07:00
parent 772502e98a
commit 7124afe527
17 changed files with 266 additions and 89 deletions

View file

@ -26,6 +26,11 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'javax.cache:cache-api'
implementation 'jakarta.xml.bind:jakarta.xml.bind-api'
implementation('io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:1.28.0')
implementation('io.opentelemetry:opentelemetry-api')
implementation 'com.squareup.okhttp3:okhttp'
implementation 'org.json:json:20171018'
runtimeOnly 'org.springframework.boot:spring-boot-starter-actuator'
runtimeOnly "org.webjars.npm:bootstrap:${webjarsBootstrapVersion}"
runtimeOnly "org.webjars.npm:font-awesome:${webjarsFontawesomeVersion}"
@ -37,6 +42,17 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named("bootRun") {
if (project.hasProperty('digma')) {
def tempDir = System.getProperty("java.io.tmpdir")
environment["JAVA_TOOL_OPTIONS"] = "-javaagent:${tempDir}/temp-digma-otel-jars/opentelemetry-javaagent.jar"
systemProperty 'otel.exporter.otlp.traces.endpoint', 'http://localhost:5050'
systemProperty 'otel.traces.exporter', 'otlp'
systemProperty 'otel.metrics.exporter', 'none'
systemProperty 'otel.service.name', "${project.name}"
systemProperty 'otel.javaagent.extensions', "${tempDir}/temp-digma-otel-jars/digma-otel-agent-extension.jar"
}
}
tasks.named('test') {
useJUnitPlatform()
}

1
digma-profile.gradle Normal file
View file

@ -0,0 +1 @@

BIN
opentelemetry-agent.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

86
pom.xml
View file

@ -5,6 +5,8 @@
<artifactId>spring-petclinic</artifactId>
<version>3.1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
@ -67,6 +69,27 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<!-- Databases - Uses H2 by default -->
<dependency>
<groupId>com.h2database</groupId>
@ -120,7 +143,12 @@
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
@ -135,9 +163,20 @@
<artifactId>android-json</artifactId>
<version>0.0.20131108.vaadin1</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-bom</artifactId>
<version>${testcontainers.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
@ -183,28 +222,8 @@
<artifactId>checkstyle</artifactId>
<version>${checkstyle.version}</version>
</dependency>
<dependency>
<groupId>io.spring.nohttp</groupId>
<artifactId>nohttp-checkstyle</artifactId>
<version>${nohttp-checkstyle.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>nohttp-checkstyle-validation</id>
<phase>validate</phase>
<configuration>
<configLocation>src/checkstyle/nohttp-checkstyle.xml</configLocation>
<suppressionsLocation>src/checkstyle/nohttp-checkstyle-suppressions.xml</suppressionsLocation>
<sourceDirectories>${basedir}</sourceDirectories>
<includes>**/*</includes>
<excludes>**/.git/**/*,**/.idea/**/*,**/target/**/,**/.flattened-pom.xml,**/*.class</excludes>
</configuration>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
@ -311,6 +330,27 @@
</pluginRepositories>
<profiles>
<profile>
<id>digma</id>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jvmArguments>-javaagent:${env.TMPDIR}/temp-digma-otel-jars/opentelemetry-javaagent.jar</jvmArguments>
<systemPropertyVariables>
<otel.exporter.otlp.traces.endpoint>http://localhost:5050</otel.exporter.otlp.traces.endpoint>
<otel.traces.exporter>otlp</otel.traces.exporter>
<otel.metrics.exporter>none</otel.metrics.exporter>
<otel.service.name>${pom.artifactId}</otel.service.name>
<otel.javaagent.extensions>${env.TMPDIR}/temp-digma-otel-jars/digma-otel-agent-extension.jar</otel.javaagent.extensions>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>css</id>
<build>

View file

@ -16,8 +16,13 @@
package org.springframework.samples.petclinic;
import jakarta.servlet.ServletContext;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public class PetClinicRuntimeHints implements RuntimeHintsRegistrar {

View file

@ -6,9 +6,11 @@ import org.json.JSONException;
import java.io.IOException;
public interface PetVaccinationService {
@WithSpan
VaccinnationRecord[] AllVaccines() throws JSONException, IOException;
@WithSpan
VaccinnationRecord VaccineRecord(int vaccinationRecordId) throws JSONException, IOException;
}

View file

@ -20,7 +20,7 @@ public class PetVaccinationServiceFacade implements PetVaccinationService {
public static final String VACCINES_RECORDS_URL = "https://647f4bb4c246f166da9084c7.mockapi.io/api/vetcheck/vaccines";
private String MakeHttpCall(String url) throws IOException{
private String MakeHttpCall(String url) throws IOException {
Request getAllVaccinesRequest = new Request.Builder().url(url).build();
OkHttpClient client = new OkHttpClient();
@ -34,8 +34,7 @@ public class PetVaccinationServiceFacade implements PetVaccinationService {
var vaccineListString = MakeHttpCall(VACCINES_RECORDS_URL);
JSONArray jArr = new JSONArray(vaccineListString);
var vaccinnationRecords =
new ArrayList<VaccinnationRecord>();
var vaccinnationRecords = new ArrayList<VaccinnationRecord>();
for (int i = 0; i < jArr.length(); i++) {
@ -69,6 +68,4 @@ public class PetVaccinationServiceFacade implements PetVaccinationService {
return new VaccinnationRecord(id, petId, vaccineDate);
}
}

View file

@ -52,7 +52,7 @@ public class OwnerValidation {
}
@WithSpan
// This function and classes were generated by ChatGPT
public boolean ValidateUserAccess(String usr, String pswd, String sysCode) {
@ -62,7 +62,6 @@ public class OwnerValidation {
return false;
}
boolean vldPswd = pwdUtils.vldtPswd(usr, pswd);
if (!vldPswd) {
return false;

View file

@ -1,6 +1,7 @@
package org.springframework.samples.petclinic.domain;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.instrumentation.annotations.WithSpan;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.samples.petclinic.adapters.PetVaccinationService;
@ -20,15 +21,16 @@ public class PetVaccinationStatusService {
@Autowired
private PetVaccinationService adapter;
public void UpdateVaccinationStatus(Pet[] pets){
@WithSpan
public void UpdateVaccinationStatus(Pet[] pets) {
for (Pet pet: pets){
for (Pet pet : pets) {
try {
var vaccinationRecords = this.adapter.AllVaccines();
for (VaccinnationRecord record : vaccinationRecords){
for (VaccinnationRecord record : vaccinationRecords) {
var recordInfo = this.adapter.VaccineRecord(record.recordId());
if (recordInfo.petId()==pet.getId()){
if (recordInfo.petId() == pet.getId()) {
var date = LocalDateTime.ofInstant(recordInfo.vaccineDate(), ZoneId.systemDefault());
PetVaccine petVaccine = new PetVaccine();
petVaccine.setDate(date.toLocalDate());
@ -36,13 +38,14 @@ public class PetVaccinationStatusService {
}
}
} catch (JSONException |IOException e) {
//Fail silently
}
catch (JSONException | IOException e) {
// Fail silently
Span.current().recordException(e);
}
}
}
}

View file

@ -129,11 +129,6 @@ class OwnerController {
return addPaginationModel(page, model, ownersResults);
}
private String addPaginationModel(int page, Model model, Page<Owner> paginated) {
model.addAttribute("listOwners", paginated);
List<Owner> listOwners = paginated.getContent();
@ -151,11 +146,6 @@ class OwnerController {
return owners.findByLastName(lastname, pageable);
}
@GetMapping("/owners/{ownerId}/edit")
public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
Owner owner = this.owners.findById(ownerId);
@ -163,24 +153,6 @@ class OwnerController {
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/owners/{ownerId}/edit")
public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result,
@PathVariable("ownerId") int ownerId) {
@ -199,10 +171,8 @@ class OwnerController {
* @return a ModelMap with the model attributes for the view
*/
@GetMapping("/owners/{ownerId}")
public ModelAndView showOwner(@PathVariable("ownerId")
int ownerId) {
ModelAndView mav =
new ModelAndView("owners/ownerDetails");
public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
ModelAndView mav = new ModelAndView("owners/ownerDetails");
Owner owner = this.owners.findById(ownerId);
mav.addObject(owner);
return mav;

View file

@ -79,4 +79,8 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
@Transactional(readOnly = true)
Page<Owner> findAll(Pageable pageable);
// @Query("DROP Table Owner")
// @Transactional(readOnly = true)
// void deleteAll();
}

View file

@ -87,20 +87,9 @@ class PetController {
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/pets/new")
public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult result, ModelMap model) {
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");
}
@ -110,19 +99,13 @@ class PetController {
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
}
this.owners.save(owner);
petVaccinationStatus.UpdateVaccinationStatus(owner.getPets().toArray(Pet[]::new));
return "redirect:/owners/{ownerId}";
}
@GetMapping("/pets/{petId}/edit")
public String initUpdateForm(Owner owner, @PathVariable("petId") int petId, ModelMap model) {
Pet pet = owner.getPet(petId);

View file

@ -16,6 +16,7 @@
package org.springframework.samples.petclinic.system;
import io.opentelemetry.instrumentation.annotations.WithSpan;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@ -27,4 +28,6 @@ class WelcomeController {
return "welcome";
}
}

View file

@ -54,5 +54,5 @@ CREATE INDEX ON visits (pet_id);
CREATE TABLE IF NOT EXISTS pet_vaccines (
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
pet_id INT REFERENCES pets (id),
vaccine_date DATE,
vaccine_date DATE
);

View file

@ -0,0 +1,154 @@
package org.springframework.samples.petclinic.integration;
import com.github.javafaker.Faker;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.annotations.WithSpan;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import jakarta.persistence.EntityManagerFactory;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.samples.petclinic.owner.*;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.time.ZoneId;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThat;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.hasSize;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
@ActiveProfiles(value = "postgres")
public class OwnerControllerTests {
@LocalServerPort
private Integer port;
@BeforeAll
static void beforeAll() {
postgres.start();
}
@AfterAll
static void afterAll() {
postgres.stop();
}
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15-alpine");
@BeforeEach
void setUp() {
// ownerRepository.deleteAll();
RestAssured.baseURI = "http://localhost:" + port;
}
Faker faker = new Faker();
@Autowired
EntityManagerFactory emf;
@Autowired
OwnerRepository ownerRepository;
@Test
@WithSpan(kind = SpanKind.SERVER)
void shouldSaveNewOwnerPet() {
Owner owner = CreateOwner();
for (int i = 0; i < 3; i++) {
String newPetName = faker.dog().name();
given().contentType("multipart/form-data")
.multiPart("id", "")
.multiPart("birthDate", "0222-02-02")
.multiPart("name", newPetName)
.multiPart("type", "dog")
.when()
.post(String.format("/owners/%s/pets/new", owner.getId()))
.then()
.statusCode(Matchers.not(Matchers.greaterThan(499)));
try {
Thread.sleep(800);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
// var updatedOwner = ownerRepository.findById(owner.getId());
// assertThat(updatedOwner.getPets())
// .hasSize(2)
// .extracting(Pet::getName)
// .contains(newPetName);
}
@Test
void shouldGetAllOwners() {
Owner owner = CreateOwner();
var ownerLinkMatcher =
String.format("**.findAll { node -> node.@href=='/owners/%s'}",
owner.getId());
given()
.contentType(ContentType.JSON)
.when()
.get("/owners")
.then()
.contentType(ContentType.HTML)
.statusCode(200)
.body(ownerLinkMatcher,Matchers.notNullValue());
}
@NotNull
private Owner CreateOwner() {
var owner = new Owner();
owner.setFirstName(faker.name().firstName());
owner.setLastName(faker.name().lastName());
owner.setAddress(faker.address().streetAddress());
owner.setTelephone("5555555");
owner.setCity(faker.address().city());
Pet pet = new Pet();
pet.setName(faker.dog().name());
pet.setBirthDate(faker.date().birthday().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
PetType dog = new PetType();
dog.setName(faker.dog().name());
dog.setId(2);
pet.setType(dog);
PetVaccine vaccine = new PetVaccine();
vaccine.setDate(faker.date()
.past(30, TimeUnit.DAYS, new java.util.Date())
.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate());
pet.addVaccine(vaccine);
owner.addPet(pet);
ownerRepository.save(owner);
return owner;
}
}