From 144a09b3cb33a1f190bd2ec416207dbef844c967 Mon Sep 17 00:00:00 2001 From: Omur Sahin Date: Sun, 4 Oct 2026 11:50:13 +0300 Subject: [PATCH] petclinic drivers --- .gitignore | 3 + README.md | 4 +- dockerfiles/petclinic-rest.dockerfile | 13 + dockerfiles/petclinic-rest.yaml | 30 + experiments/bb-exp.py | 1 + experiments/wb-exp.py | 1 + jacoco.dockerfile | 1 + jdk_17_maven/cs/rest/petclinic-rest/pom.xml | 6 + jdk_17_maven/cs/rest/pom.xml | 1 + .../em/embedded/rest/petclinic-rest/pom.xml | 37 + .../EmbeddedEvoMasterController.java | 132 + jdk_17_maven/em/embedded/rest/pom.xml | 1 + .../em/external/rest/petclinic-rest/pom.xml | 81 + .../ExternalEvoMasterController.java | 205 + jdk_17_maven/em/external/rest/pom.xml | 1 + openapi/petclinic-rest.json | 3296 +++++++++++++++++ scripts/build/docker-compose.build.yml | 2 + scripts/dist-wb.py | 3 + scripts/dockerize/data/sut.csv | 1 + statistics/data.csv | 1 + statistics/http-verbs.csv | 1 + statistics/http-verbs.md | 3 +- statistics/table_wfd.md | 1 + 23 files changed, 3823 insertions(+), 2 deletions(-) create mode 100644 dockerfiles/petclinic-rest.dockerfile create mode 100644 dockerfiles/petclinic-rest.yaml create mode 100644 jdk_17_maven/em/embedded/rest/petclinic-rest/pom.xml create mode 100644 jdk_17_maven/em/embedded/rest/petclinic-rest/src/main/java/em/embedded/org/springframework/samples/petclinic/EmbeddedEvoMasterController.java create mode 100644 jdk_17_maven/em/external/rest/petclinic-rest/pom.xml create mode 100644 jdk_17_maven/em/external/rest/petclinic-rest/src/main/java/em/external/org/springframework/samples/petclinic/ExternalEvoMasterController.java create mode 100644 openapi/petclinic-rest.json diff --git a/.gitignore b/.gitignore index 4358ea9ef..ab0580e86 100644 --- a/.gitignore +++ b/.gitignore @@ -382,6 +382,9 @@ jdk_8_maven/em/external/rest/spring-batch-rest/target /jdk_17_maven/cs/rest/kafka-rest/kafka-rest/target/ /jdk_17_maven/em/embedded/rest/kafka-rest/target/ /jdk_17_maven/em/external/rest/kafka-rest/target/ +/jdk_17_maven/cs/rest/petclinic-rest/target/ +/jdk_17_maven/em/embedded/rest/petclinic-rest/target/ +/jdk_17_maven/em/external/rest/petclinic-rest/target/ /jdk_17_maven/em/embedded/rest/spring-rest-example/target/ /jdk_17_maven/em/external/rest/spring-rest-example/target/ diff --git a/README.md b/README.md index 7d5b6ad13..3d05bca85 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ How to setup authentication information, based on the current content of the ini Auth configuration files can found in the [auth](auth) folder. -### REST: Java/Kotlin (49) +### REST: Java/Kotlin (50) * **AdoptMe** (not-known license), [jdk_21_maven/cs/rest/adoptme](jdk_21_maven/cs/rest/adoptme), from [https://github.com/daanimelian/Programacion3-TPO](https://github.com/daanimelian/Programacion3-TPO) @@ -173,6 +173,8 @@ Auth configuration files can found in the [auth](auth) folder. * **Spring ECommerce** (not-known license), [jdk_8_maven/cs/rest/original/spring-ecommerce](jdk_8_maven/cs/rest/original/spring-ecommerce), from [https://github.com/SaiUpadhyayula/SpringAngularEcommerce](https://github.com/SaiUpadhyayula/SpringAngularEcommerce) +* **Spring PetClinic REST** (Apache), [jdk_17_maven/cs/rest/petclinic-rest](jdk_17_maven/cs/rest/petclinic-rest), from [https://github.com/spring-petclinic/spring-petclinic-rest](https://github.com/spring-petclinic/spring-petclinic-rest) + * **Swagger Petstore** (Apache), [jdk_8_maven/cs/rest/original/swagger-petstore](jdk_8_maven/cs/rest/original/swagger-petstore), from [https://github.com/swagger-api/swagger-petstore](https://github.com/swagger-api/swagger-petstore) * **Testing System** (MIT), [jdk_21_maven/cs/rest/testing-system](jdk_21_maven/cs/rest/testing-system), from [https://github.com/mirodilkamilov/testing-system](https://github.com/mirodilkamilov/testing-system) diff --git a/dockerfiles/petclinic-rest.dockerfile b/dockerfiles/petclinic-rest.dockerfile new file mode 100644 index 000000000..9677f87fa --- /dev/null +++ b/dockerfiles/petclinic-rest.dockerfile @@ -0,0 +1,13 @@ +FROM amazoncorretto:17-alpine-jdk + +COPY ./dist/petclinic-rest-sut.jar . +COPY ./dist/jacocoagent.jar . + + + + +ENTRYPOINT \ + java \ + -javaagent:jacocoagent.jar=output=tcpserver,address=*,port=6300,append=false,dumponexit=false \ + -jar petclinic-rest-sut.jar \ + --server.port=8080 --spring.jpa.show-sql=false \ No newline at end of file diff --git a/dockerfiles/petclinic-rest.yaml b/dockerfiles/petclinic-rest.yaml new file mode 100644 index 000000000..a0220c4b8 --- /dev/null +++ b/dockerfiles/petclinic-rest.yaml @@ -0,0 +1,30 @@ +services: + mitmproxy: + image: mitmproxy/mitmproxy:10.2.4 + user: "0:0" + environment: + MITM_LOG_DIR: /custom-logs + MITM_LOG_FILE: ${MITM_LOG_FILE:-minlog.csv} + command: > + mitmdump + --mode reverse:http://sut-petclinic-rest:8080 + --listen-host 0.0.0.0 + --listen-port 8080 + --set keep_host_header=true + -s /addons/minlog.py + volumes: + - ${HOST_LOG_DIR:-./mitm-logs}:/custom-logs + - ./addons:/addons:ro + ports: + - "${HOST_PORT:-8080}:8080" + depends_on: + - sut-petclinic-rest + sut-petclinic-rest: + image: webfuzzing/wfd-petclinic-rest:FINAL +# build: +# dockerfile: ./dockerfiles/petclinic-rest.dockerfile +# context: .. + environment: + AUTH_PORT: ${AUTH_PORT:-8081} + ports: + - "${JACOCO_PORT:-6300}:6300" \ No newline at end of file diff --git a/experiments/bb-exp.py b/experiments/bb-exp.py index 38e5b5514..64f035a4d 100644 --- a/experiments/bb-exp.py +++ b/experiments/bb-exp.py @@ -153,6 +153,7 @@ def __init__(self, name, auth, sleep, schemaformat, classfiles): Sut("ohsome-api",False,SLEEP,JSON,["jdk_17_maven/cs/rest/ohsome-api/target/classes"]), Sut("pay-publicapi",True,SLEEP,JSON,["jdk_11_maven/cs/rest/pay-publicapi/target/classes"]), Sut("person-controller",False,SLEEP,JSON,["jdk_21_maven/cs/rest/person-controller/target/classes"]), + Sut("petclinic-rest",False,SLEEP,JSON,["jdk_17_maven/cs/rest/petclinic-rest/target/classes"]), Sut("proxyprint",True,SLEEP,JSON,["jdk_8_maven/cs/rest/original/proxyprint/target/classes"]), Sut("quartz-manager",True,SLEEP,JSON,["jdk_11_maven/cs/rest-gui/quartz-manager/quartz-manager-parent/quartz-manager-common/target/classes", "jdk_11_maven/cs/rest-gui/quartz-manager/quartz-manager-parent/quartz-manager-starter-api/target/classes", diff --git a/experiments/wb-exp.py b/experiments/wb-exp.py index 139d642ba..4443b169b 100644 --- a/experiments/wb-exp.py +++ b/experiments/wb-exp.py @@ -210,6 +210,7 @@ def __init__(self, name, platform): Sut("ohsome-api", JDK_17), Sut("pay-publicapi",JDK_11), Sut("person-controller",JDK_21), + Sut("petclinic-rest", JDK_17), Sut("proxyprint", JDK_8), Sut("quartz-manager", JDK_11), Sut("redis-sample", JDK_21), diff --git a/jacoco.dockerfile b/jacoco.dockerfile index b68bd4d57..9544e6060 100644 --- a/jacoco.dockerfile +++ b/jacoco.dockerfile @@ -89,6 +89,7 @@ COPY jdk_8_maven/cs/rest-gui/ocvn/web/target/classes ${CLASS_FILES}/jdk_8_maven COPY jdk_17_maven/cs/rest/ohsome-api/target/classes ${CLASS_FILES}/jdk_17_maven/cs/rest/ohsome-api/target/classes COPY jdk_11_maven/cs/rest/pay-publicapi/target/classes ${CLASS_FILES}/jdk_11_maven/cs/rest/pay-publicapi/target/classes COPY jdk_21_maven/cs/rest/person-controller/target/classes ${CLASS_FILES}/jdk_21_maven/cs/rest/person-controller/target/classes +COPY jdk_17_maven/cs/rest/petclinic-rest/target/classes ${CLASS_FILES}/jdk_17_maven/cs/rest/petclinic-rest/target/classes COPY jdk_8_maven/cs/rest/original/proxyprint/target/classes ${CLASS_FILES}/jdk_8_maven/cs/rest/original/proxyprint/target/classes COPY jdk_11_maven/cs/rest-gui/quartz-manager/quartz-manager-parent/quartz-manager-common/target/classes ${CLASS_FILES}/jdk_11_maven/cs/rest-gui/quartz-manager/quartz-manager-parent/quartz-manager-common/target/classes COPY jdk_11_maven/cs/rest-gui/quartz-manager/quartz-manager-parent/quartz-manager-starter-api/target/classes ${CLASS_FILES}/jdk_11_maven/cs/rest-gui/quartz-manager/quartz-manager-parent/quartz-manager-starter-api/target/classes diff --git a/jdk_17_maven/cs/rest/petclinic-rest/pom.xml b/jdk_17_maven/cs/rest/petclinic-rest/pom.xml index db95be99a..32e6f6c54 100644 --- a/jdk_17_maven/cs/rest/petclinic-rest/pom.xml +++ b/jdk_17_maven/cs/rest/petclinic-rest/pom.xml @@ -252,6 +252,12 @@ org.springframework.boot spring-boot-maven-plugin + + + petclinic-rest + sut + + diff --git a/jdk_17_maven/em/embedded/rest/petclinic-rest/pom.xml b/jdk_17_maven/em/embedded/rest/petclinic-rest/pom.xml new file mode 100644 index 000000000..42bcfdfb6 --- /dev/null +++ b/jdk_17_maven/em/embedded/rest/petclinic-rest/pom.xml @@ -0,0 +1,37 @@ + + + + 4.0.0 + + evomaster-benchmark-jdk17-em-embedded-rest-petclinic-rest + jar + + + org.evomaster + evomaster-benchmark-jdk17-em-embedded-rest + 4.3.1-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-dependencies + 4.1.1 + pom + import + + + + + + + + org.springframework.samples + spring-petclinic-rest + 4.0.2 + + + + diff --git a/jdk_17_maven/em/embedded/rest/petclinic-rest/src/main/java/em/embedded/org/springframework/samples/petclinic/EmbeddedEvoMasterController.java b/jdk_17_maven/em/embedded/rest/petclinic-rest/src/main/java/em/embedded/org/springframework/samples/petclinic/EmbeddedEvoMasterController.java new file mode 100644 index 000000000..831909b54 --- /dev/null +++ b/jdk_17_maven/em/embedded/rest/petclinic-rest/src/main/java/em/embedded/org/springframework/samples/petclinic/EmbeddedEvoMasterController.java @@ -0,0 +1,132 @@ +package em.embedded.org.springframework.samples.petclinic; + +import org.evomaster.client.java.controller.EmbeddedSutController; +import org.evomaster.client.java.controller.InstrumentedSutStarter; +import org.evomaster.client.java.controller.api.dto.SutInfoDto; +import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto; +import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType; +import org.evomaster.client.java.controller.problem.ProblemInfo; +import org.evomaster.client.java.controller.problem.RestProblem; +import org.evomaster.client.java.sql.DbSpecification; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.samples.petclinic.PetClinicApplication; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class EmbeddedEvoMasterController extends EmbeddedSutController { + + public static void main(String[] args) { + + int port = 40100; + if (args.length > 0) { + port = Integer.parseInt(args[0]); + } + + EmbeddedEvoMasterController controller = new EmbeddedEvoMasterController(port); + InstrumentedSutStarter starter = new InstrumentedSutStarter(controller); + + starter.start(); + } + + private ConfigurableApplicationContext ctx; + private Connection sqlConnection; + private List dbSpecification; + private int dbCounter; + + public EmbeddedEvoMasterController() { + this(40100); + } + + public EmbeddedEvoMasterController(int port) { + setControllerPort(port); + } + + @Override + public String startSut() { + + ctx = SpringApplication.run(PetClinicApplication.class, new String[]{ + "--server.port=0", + "--spring.datasource.url=jdbc:h2:mem:petclinic_" + (++dbCounter) + ";DB_CLOSE_DELAY=-1", + "--spring.sql.init.data-locations=", + "--spring.jpa.show-sql=false" + }); + + closeDataBaseConnection(); + try { + sqlConnection = ctx.getBean(JdbcTemplate.class).getDataSource().getConnection(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + dbSpecification = Arrays.asList(new DbSpecification(DatabaseType.H2, sqlConnection) + .withInitSqlOnResourcePath("/db/h2/data.sql")); + + return "http://localhost:" + getSutPort(); + } + + protected int getSutPort() { + return (Integer) ((Map) ctx.getEnvironment() + .getPropertySources().get("server.ports").getSource()) + .get("local.server.port"); + } + + @Override + public boolean isSutRunning() { + return ctx != null && ctx.isRunning(); + } + + @Override + public void stopSut() { + closeDataBaseConnection(); + ctx.stop(); + ctx.close(); + } + + private void closeDataBaseConnection() { + if (sqlConnection != null) { + try { + sqlConnection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + sqlConnection = null; + } + } + + @Override + public String getPackagePrefixesToCover() { + return "org.springframework.samples.petclinic."; + } + + @Override + public void resetStateOfSUT() { + } + + @Override + public List getDbSpecifications() { + return dbSpecification; + } + + @Override + public List getInfoForAuthentication() { + return null; + } + + @Override + public ProblemInfo getProblemInfo() { + return new RestProblem( + "http://localhost:" + getSutPort() + "/petclinic/v3/api-docs", + null + ); + } + + @Override + public SutInfoDto.OutputFormat getPreferredOutputFormat() { + return SutInfoDto.OutputFormat.JAVA_JUNIT_5; + } +} diff --git a/jdk_17_maven/em/embedded/rest/pom.xml b/jdk_17_maven/em/embedded/rest/pom.xml index 69e66b3f9..4dc379408 100644 --- a/jdk_17_maven/em/embedded/rest/pom.xml +++ b/jdk_17_maven/em/embedded/rest/pom.xml @@ -18,6 +18,7 @@ spring-rest-example digitalbanking kafka-rest + petclinic-rest diff --git a/jdk_17_maven/em/external/rest/petclinic-rest/pom.xml b/jdk_17_maven/em/external/rest/petclinic-rest/pom.xml new file mode 100644 index 000000000..ff22f822e --- /dev/null +++ b/jdk_17_maven/em/external/rest/petclinic-rest/pom.xml @@ -0,0 +1,81 @@ + + + + 4.0.0 + + evomaster-benchmark-jdk17-em-external-rest-petclinic-rest + jar + + + org.evomaster + evomaster-benchmark-jdk17-em-external-rest + 4.3.1-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-dependencies + 4.1.1 + pom + import + + + + + + + + com.h2database + h2 + + + + + + + + ${project.basedir}/../../../../cs/rest/petclinic-rest/src/main/resources/db/h2 + petclinic-rest + + data.sql + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + petclinic-rest-evomaster-runner + + + + em.external.org.springframework.samples.petclinic.ExternalEvoMasterController + + org.evomaster.client.java.instrumentation.InstrumentingAgent + + org.evomaster.client.java.instrumentation.InstrumentingAgent + + true + true + + + + + + + + + + + diff --git a/jdk_17_maven/em/external/rest/petclinic-rest/src/main/java/em/external/org/springframework/samples/petclinic/ExternalEvoMasterController.java b/jdk_17_maven/em/external/rest/petclinic-rest/src/main/java/em/external/org/springframework/samples/petclinic/ExternalEvoMasterController.java new file mode 100644 index 000000000..8858cb878 --- /dev/null +++ b/jdk_17_maven/em/external/rest/petclinic-rest/src/main/java/em/external/org/springframework/samples/petclinic/ExternalEvoMasterController.java @@ -0,0 +1,205 @@ +package em.external.org.springframework.samples.petclinic; + +import org.evomaster.client.java.controller.ExternalSutController; +import org.evomaster.client.java.controller.InstrumentedSutStarter; +import org.evomaster.client.java.controller.api.dto.SutInfoDto; +import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto; +import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType; +import org.evomaster.client.java.controller.problem.ProblemInfo; +import org.evomaster.client.java.controller.problem.RestProblem; +import org.evomaster.client.java.sql.DbSpecification; +import org.h2.tools.Server; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; + +public class ExternalEvoMasterController extends ExternalSutController { + + public static void main(String[] args) { + + int controllerPort = 40100; + if (args.length > 0) { + controllerPort = Integer.parseInt(args[0]); + } + int sutPort = 12345; + if (args.length > 1) { + sutPort = Integer.parseInt(args[1]); + } + String jarLocation = "cs/rest/petclinic-rest/target"; + if (args.length > 2) { + jarLocation = args[2]; + } + if (!jarLocation.endsWith(".jar")) { + jarLocation += "/petclinic-rest-sut.jar"; + } + int timeoutSeconds = 120; + if (args.length > 3) { + timeoutSeconds = Integer.parseInt(args[3]); + } + String command = "java"; + if (args.length > 4) { + command = args[4]; + } + + ExternalEvoMasterController controller = + new ExternalEvoMasterController(controllerPort, jarLocation, sutPort, timeoutSeconds, command); + controller.setNeedsJdk17Options(true); + + InstrumentedSutStarter starter = new InstrumentedSutStarter(controller); + starter.start(); + } + + private final int timeoutSeconds; + private final int sutPort; + private final int dbPort; + private String jarLocation; + private Connection sqlConnection; + private List dbSpecification; + private Server h2; + private int dbCounter; + + public ExternalEvoMasterController() { + this(40100, "cs/rest/petclinic-rest/target", 12345, 120, "java"); + } + + public ExternalEvoMasterController(String jarLocation) { + this(); + this.jarLocation = jarLocation; + } + + public ExternalEvoMasterController( + int controllerPort, String jarLocation, int sutPort, int timeoutSeconds, String command) { + + if (jarLocation == null || jarLocation.isEmpty()) { + throw new IllegalArgumentException("Missing jar location"); + } + + this.sutPort = sutPort; + this.dbPort = sutPort + 1; + this.jarLocation = jarLocation; + this.timeoutSeconds = timeoutSeconds; + setControllerPort(controllerPort); + setJavaCommand(command); + } + + private String dbUrl() { + return "jdbc:h2:tcp://localhost:" + dbPort + "/mem:petclinic_" + dbPort + "_" + dbCounter + ";DB_CLOSE_DELAY=-1"; + } + + @Override + public String[] getInputParameters() { + return new String[]{ + "--server.port=" + sutPort, + "--spring.datasource.url=" + dbUrl(), + "--spring.sql.init.data-locations=", + "--spring.jpa.show-sql=false" + }; + } + + @Override + public String[] getJVMParameters() { + return new String[]{}; + } + + @Override + public String getBaseURL() { + return "http://localhost:" + sutPort; + } + + @Override + public String getPathToExecutableJar() { + return jarLocation; + } + + @Override + public String getLogMessageOfInitializedServer() { + return "Started PetClinicApplication in "; + } + + @Override + public long getMaxAwaitForInitializationInSeconds() { + return timeoutSeconds; + } + + @Override + public void preStart() { + dbCounter++; + try { + h2 = Server.createTcpServer("-tcp", "-tcpAllowOthers", "-tcpPort", "" + dbPort, "-ifNotExists"); + h2.start(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + @Override + public void postStart() { + closeDataBaseConnection(); + + try { + sqlConnection = DriverManager.getConnection(dbUrl(), "sa", ""); + } catch (SQLException e) { + throw new RuntimeException(e); + } + dbSpecification = Arrays.asList(new DbSpecification(DatabaseType.H2, sqlConnection) + .withInitSqlOnResourcePath("/petclinic-rest/data.sql")); + } + + @Override + public void resetStateOfSUT() { + } + + @Override + public void preStop() { + closeDataBaseConnection(); + } + + @Override + public void postStop() { + if (h2 != null) { + h2.stop(); + } + } + + private void closeDataBaseConnection() { + if (sqlConnection != null) { + try { + sqlConnection.close(); + } catch (SQLException e) { + e.printStackTrace(); + } + sqlConnection = null; + } + } + + @Override + public String getPackagePrefixesToCover() { + return "org.springframework.samples.petclinic."; + } + + @Override + public ProblemInfo getProblemInfo() { + return new RestProblem( + getBaseURL() + "/petclinic/v3/api-docs", + null + ); + } + + @Override + public SutInfoDto.OutputFormat getPreferredOutputFormat() { + return SutInfoDto.OutputFormat.JAVA_JUNIT_5; + } + + @Override + public List getInfoForAuthentication() { + return null; + } + + @Override + public List getDbSpecifications() { + return dbSpecification; + } +} diff --git a/jdk_17_maven/em/external/rest/pom.xml b/jdk_17_maven/em/external/rest/pom.xml index f2ed0b61d..b810c1bf5 100644 --- a/jdk_17_maven/em/external/rest/pom.xml +++ b/jdk_17_maven/em/external/rest/pom.xml @@ -19,6 +19,7 @@ spring-rest-example digitalbanking kafka-rest + petclinic-rest \ No newline at end of file diff --git a/openapi/petclinic-rest.json b/openapi/petclinic-rest.json new file mode 100644 index 000000000..0be872e03 --- /dev/null +++ b/openapi/petclinic-rest.json @@ -0,0 +1,3296 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "REST Petclinic backend API documentation", + "description": "This is the REST API documentation of the Spring Petclinic backend. If authentication is enabled, use admin/admin when calling the APIs", + "termsOfService": "https://github.com/spring-petclinic/spring-petclinic-rest/blob/master/terms.txt", + "contact": { + "name": "Vitaliy Fedoriv", + "url": "https://github.com/spring-petclinic/spring-petclinic-rest", + "email": "vitaliy.fedoriv@gmail.com" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0", + "extensions": {} + }, + "version": "1.0" + }, + "servers": [ + { + "url": "http://localhost:8080/petclinic", + "description": "Generated server url" + } + ], + "tags": [ + { + "name": "pettypes", + "description": "Endpoints related to pet types." + }, + { + "name": "users", + "description": "Endpoints related to users." + }, + { + "name": "vets", + "description": "Endpoints related to vets." + }, + { + "name": "owner-v2", + "description": "Version 2 endpoints related to pet owners." + }, + { + "name": "owners", + "description": "Endpoints related to pet owners." + }, + { + "name": "pets", + "description": "Endpoints related to pets." + }, + { + "name": "specialties", + "description": "Endpoints related to vet specialties." + }, + { + "name": "visits", + "description": "Endpoints related to vet visits." + }, + { + "name": "pet-v2", + "description": "Version 2 endpoints related to pets." + } + ], + "paths": { + "/api/visits/{visitId}": { + "get": { + "tags": [ + "visits" + ], + "summary": "Get a visit by ID", + "description": "Returns the visit or a 404 error.", + "operationId": "getVisit", + "parameters": [ + { + "name": "visitId", + "in": "path", + "description": "The ID of the visit.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Visit details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Visit not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "put": { + "tags": [ + "visits" + ], + "summary": "Update a visit by ID", + "description": "Returns the visit or a 404 error.", + "operationId": "updateVisit", + "parameters": [ + { + "name": "visitId", + "in": "path", + "description": "The ID of the visit.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VisitFields" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Visit details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Visit not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "delete": { + "tags": [ + "visits" + ], + "summary": "Delete a visit by ID", + "description": "Returns the visit or a 404 error.", + "operationId": "deleteVisit", + "parameters": [ + { + "name": "visitId", + "in": "path", + "description": "The ID of the visit.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Visit details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Visit not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/vets/{vetId}": { + "get": { + "tags": [ + "vets" + ], + "summary": "Get a vet by ID", + "description": "Returns the vet or a 404 error.", + "operationId": "getVet", + "parameters": [ + { + "name": "vetId", + "in": "path", + "description": "The ID of the vet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Vet details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Vet not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "put": { + "tags": [ + "vets" + ], + "summary": "Update a vet by ID", + "description": "Returns the vet or a 404 error.", + "operationId": "updateVet", + "parameters": [ + { + "name": "vetId", + "in": "path", + "description": "The ID of the vet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Pet type details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Vet not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "delete": { + "tags": [ + "vets" + ], + "summary": "Delete a vet by ID", + "description": "Returns the vet or a 404 error.", + "operationId": "deleteVet", + "parameters": [ + { + "name": "vetId", + "in": "path", + "description": "The ID of the vet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Vet details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Vet not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/specialties/{specialtyId}": { + "get": { + "tags": [ + "specialties" + ], + "summary": "Get a specialty by ID", + "description": "Returns the specialty or a 404 error.", + "operationId": "getSpecialty", + "parameters": [ + { + "name": "specialtyId", + "in": "path", + "description": "The ID of the speciality.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Specialty details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Specialty not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "put": { + "tags": [ + "specialties" + ], + "summary": "Update a specialty by ID", + "description": "Returns the specialty or a 404 error.", + "operationId": "updateSpecialty", + "parameters": [ + { + "name": "specialtyId", + "in": "path", + "description": "The ID of the specialty.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Specialty details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Specialty not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "delete": { + "tags": [ + "specialties" + ], + "summary": "Delete a specialty by ID", + "description": "Returns the specialty or a 404 error.", + "operationId": "deleteSpecialty", + "parameters": [ + { + "name": "specialtyId", + "in": "path", + "description": "The ID of the specialty.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Specialty details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Specialty not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/pettypes/{petTypeId}": { + "get": { + "tags": [ + "pettypes" + ], + "summary": "Get a pet type by ID", + "description": "Returns the pet type or a 404 error.", + "operationId": "getPetType", + "parameters": [ + { + "name": "petTypeId", + "in": "path", + "description": "The ID of the pet type.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Pet type details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet Type not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "put": { + "tags": [ + "pettypes" + ], + "summary": "Update a pet type by ID", + "description": "Returns the pet type or a 404 error.", + "operationId": "updatePetType", + "parameters": [ + { + "name": "petTypeId", + "in": "path", + "description": "The ID of the pet type.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Pet type details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet Type not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "delete": { + "tags": [ + "pettypes" + ], + "summary": "Delete a pet type by ID", + "description": "Returns the pet type or a 404 error.", + "operationId": "deletePetType", + "parameters": [ + { + "name": "petTypeId", + "in": "path", + "description": "The ID of the pet type.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Pet type details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet type not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/pets/{petId}": { + "get": { + "tags": [ + "pets" + ], + "summary": "Get a pet by ID", + "description": "Returns the pet or a 404 error.", + "operationId": "getPet", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "The ID of the pet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Pet details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "put": { + "tags": [ + "pets" + ], + "summary": "Update a pet by ID", + "description": "Returns the pet or a 404 error.", + "operationId": "updatePet", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "The ID of the pet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Pet details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "delete": { + "tags": [ + "pets" + ], + "summary": "Delete a pet by ID", + "description": "Returns the pet or a 404 error.", + "operationId": "deletePet", + "parameters": [ + { + "name": "petId", + "in": "path", + "description": "The ID of the pet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Pet details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/owners/{ownerId}": { + "get": { + "tags": [ + "owners" + ], + "summary": "Get a pet owner by ID", + "description": "Returns the pet owner or a 404 error.", + "operationId": "getOwner", + "parameters": [ + { + "name": "ownerId", + "in": "path", + "description": "The ID of the pet owner.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Owner details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Owner" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Owner" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Owner not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "put": { + "tags": [ + "owners" + ], + "summary": "Update a pet owner's details", + "description": "Updates the pet owner record with the specified details.", + "operationId": "updateOwner", + "parameters": [ + { + "name": "ownerId", + "in": "path", + "description": "The ID of the pet owner.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OwnerFields" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Update successful.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Owner" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Owner not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "delete": { + "tags": [ + "owners" + ], + "summary": "Delete an owner by ID", + "description": "Returns the owner or a 404 error.", + "operationId": "deleteOwner", + "parameters": [ + { + "name": "ownerId", + "in": "path", + "description": "The ID of the owner.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Owner details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Owner" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Owner" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Owner not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/owners/{ownerId}/pets/{petId}": { + "get": { + "tags": [ + "owners" + ], + "summary": "Get a pet by ID", + "description": "Returns the pet or a 404 error.", + "operationId": "getOwnersPet", + "parameters": [ + { + "name": "ownerId", + "in": "path", + "description": "The ID of the pet owner.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + }, + { + "name": "petId", + "in": "path", + "description": "The ID of the pet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "responses": { + "200": { + "description": "Pet details found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Owner or pet not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "put": { + "tags": [ + "owners" + ], + "summary": "Update a pet's details", + "description": "Updates the pet record with the specified details.", + "operationId": "updateOwnersPet", + "parameters": [ + { + "name": "ownerId", + "in": "path", + "description": "The ID of the pet owner.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + }, + { + "name": "petId", + "in": "path", + "description": "The ID of the pet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetFields" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "Update successful." + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet not found for this owner.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/visits": { + "get": { + "tags": [ + "visits" + ], + "summary": "Lists visits", + "description": "Returns an array of visit .", + "operationId": "listVisits", + "responses": { + "200": { + "description": "visits found and returned.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Visit" + } + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Visit" + } + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "post": { + "tags": [ + "visits" + ], + "summary": "Create a visit", + "description": "Creates a visit.", + "operationId": "addVisit", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "visit created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Visit not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/vets": { + "get": { + "tags": [ + "vets" + ], + "summary": "Lists vets", + "description": "Returns an array of vets.", + "operationId": "listVets", + "responses": { + "200": { + "description": "Vets found and returned.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Vet" + } + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Vet" + } + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "post": { + "tags": [ + "vets" + ], + "summary": "Create a Vet", + "description": "Creates a vet .", + "operationId": "addVet", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Vet created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Vet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Vet not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/users": { + "post": { + "tags": [ + "users" + ], + "summary": "Create a user", + "description": "Creates a user.", + "operationId": "addUser", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "User created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/User" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "User not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/specialties": { + "get": { + "tags": [ + "specialties" + ], + "summary": "Lists specialties", + "description": "Returns an array of specialty .", + "operationId": "listSpecialties", + "responses": { + "200": { + "description": "Specialties found and returned.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Specialty" + } + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Specialty" + } + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "post": { + "tags": [ + "specialties" + ], + "summary": "Create a specialty", + "description": "Creates a specialty .", + "operationId": "addSpecialty", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Specialty created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Specialty" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Specialty not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/pettypes": { + "get": { + "tags": [ + "pettypes" + ], + "summary": "Lists pet types", + "description": "Returns an array of pet types.", + "operationId": "listPetTypes", + "responses": { + "200": { + "description": "Pet types found and returned.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PetType" + } + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PetType" + } + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "post": { + "tags": [ + "pettypes" + ], + "summary": "Create a pet type", + "description": "Creates a pet type .", + "operationId": "addPetType", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetTypeFields" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Pet type created successfully.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetType" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet Type not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/owners": { + "get": { + "tags": [ + "owners" + ], + "summary": "Lists pet owners", + "description": "Returns an array of pet owners.", + "operationId": "listOwners", + "parameters": [ + { + "name": "lastName", + "in": "query", + "description": "Last name.", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Owner details found and returned.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Owner" + } + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Owner" + } + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + }, + "post": { + "tags": [ + "owners" + ], + "summary": "Adds a pet owner", + "description": "Records the details of a new pet owner.", + "operationId": "addOwner", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OwnerFields" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The pet owner was successfully added.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Owner" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/owners/{ownerId}/pets": { + "post": { + "tags": [ + "owners" + ], + "summary": "Adds a pet to an owner", + "description": "Records the details of a new pet.", + "operationId": "addPetToOwner", + "parameters": [ + { + "name": "ownerId", + "in": "path", + "description": "The ID of the pet owner.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetFields" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The pet was successfully added.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet or Owner not found.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/owners/{ownerId}/pets/{petId}/visits": { + "post": { + "tags": [ + "owners" + ], + "summary": "Adds a vet visit", + "description": "Records the details of a new vet visit.", + "operationId": "addVisitToOwner", + "parameters": [ + { + "name": "ownerId", + "in": "path", + "description": "The ID of the pet owner.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + }, + { + "name": "petId", + "in": "path", + "description": "The ID of the pet.", + "required": true, + "schema": { + "type": "integer", + "format": "int32", + "minimum": 0 + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VisitFields" + } + } + }, + "required": true + }, + "responses": { + "201": { + "description": "The vet visit was successfully added.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Visit" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "404": { + "description": "Pet not found for this owner.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/v2/pets": { + "get": { + "tags": [ + "pet-v2" + ], + "summary": "Lists pets with pagination.", + "description": "Returns a page of pets.", + "operationId": "listPetsPage", + "parameters": [ + { + "name": "page", + "in": "query", + "description": "Zero-based page index.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 0, + "minimum": 0 + } + }, + { + "name": "size", + "in": "query", + "description": "Number of items per page.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 20, + "maximum": 100, + "minimum": 1 + } + } + ], + "responses": { + "200": { + "description": "Page of pets found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PetPage" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/v2/owners": { + "get": { + "tags": [ + "owner-v2" + ], + "summary": "Lists pet owners with pagination", + "description": "Returns a page of pet owners.", + "operationId": "listOwnersPage", + "parameters": [ + { + "name": "lastName", + "in": "query", + "description": "Last name.", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "page", + "in": "query", + "description": "Zero-based page index.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 0, + "minimum": 0 + } + }, + { + "name": "size", + "in": "query", + "description": "Number of items per page.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 20, + "maximum": 100, + "minimum": 1 + } + } + ], + "responses": { + "200": { + "description": "Owner page found and returned.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OwnerPage" + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OwnerPage" + } + } + } + }, + "400": { + "description": "Bad request.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/api/pets": { + "get": { + "tags": [ + "pets" + ], + "summary": "Lists pet", + "description": "Returns an array of pet .", + "operationId": "listPets", + "responses": { + "200": { + "description": "Pet types found and returned.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "304": { + "description": "Not modified.", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Pet" + } + } + } + } + }, + "500": { + "description": "Server error.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetail" + } + } + } + } + } + } + }, + "/": { + "get": { + "tags": [ + "root-rest-controller-v-1" + ], + "operationId": "redirectToSwagger", + "responses": { + "200": { + "description": "OK" + } + } + }, + "put": { + "tags": [ + "root-rest-controller-v-1" + ], + "operationId": "redirectToSwagger_2", + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "tags": [ + "root-rest-controller-v-1" + ], + "operationId": "redirectToSwagger_1", + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "tags": [ + "root-rest-controller-v-1" + ], + "operationId": "redirectToSwagger_3", + "responses": { + "200": { + "description": "OK" + } + } + }, + "options": { + "tags": [ + "root-rest-controller-v-1" + ], + "operationId": "redirectToSwagger_6", + "responses": { + "200": { + "description": "OK" + } + } + }, + "head": { + "tags": [ + "root-rest-controller-v-1" + ], + "operationId": "redirectToSwagger_5", + "responses": { + "200": { + "description": "OK" + } + } + }, + "patch": { + "tags": [ + "root-rest-controller-v-1" + ], + "operationId": "redirectToSwagger_4", + "responses": { + "200": { + "description": "OK" + } + } + } + } + }, + "components": { + "schemas": { + "Visit": { + "type": "object", + "description": "A booking for a vet visit.", + "properties": { + "date": { + "type": "string", + "format": "date", + "description": "The date of the visit.", + "example": "2013-01-01" + }, + "description": { + "type": "string", + "description": "The description for the visit.", + "example": "rabies shot", + "maxLength": 255, + "minLength": 1 + }, + "id": { + "type": "integer", + "format": "int32", + "description": "The ID of the visit.", + "example": 1, + "minimum": 0, + "readOnly": true + }, + "petId": { + "type": "integer", + "format": "int32", + "description": "The ID of the pet.", + "example": 1, + "minimum": 0 + } + }, + "required": [ + "description", + "id", + "petId" + ] + }, + "ProblemDetail": { + "type": "object", + "description": "The schema for all error responses.", + "properties": { + "type": { + "type": "string", + "format": "uri", + "description": "Full URL that originated the error response.", + "example": "http://localhost:9966/petclinic/api/owner", + "readOnly": true + }, + "title": { + "type": "string", + "description": "The short error title.", + "example": "NoResourceFoundException", + "readOnly": true + }, + "status": { + "type": "integer", + "format": "int32", + "description": "HTTP status code", + "example": 500, + "maximum": 600, + "minimum": 400, + "readOnly": true + }, + "detail": { + "type": "string", + "description": "The long error message.", + "example": "No static resource api/owner.", + "readOnly": true + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The time the error occurred.", + "example": "2024-11-23T13:59:21.382040700Z", + "readOnly": true + }, + "schemaValidationErrors": { + "type": "array", + "description": "Validation errors against the OpenAPI schema.", + "items": { + "$ref": "#/components/schemas/ValidationMessage" + } + } + }, + "required": [ + "detail", + "schemaValidationErrors", + "status", + "timestamp", + "title", + "type" + ] + }, + "ValidationMessage": { + "type": "object", + "description": "Messages describing a validation error.", + "properties": { + "message": { + "type": "string", + "description": "The validation message.", + "example": "[Path '/lastName'] Instance type (null) does not match any allowed primitive type (allowed: ['string'])", + "readOnly": true + }, + "additionalProperties": { + "type": "object", + "additionalProperties": {} + } + }, + "required": [ + "message" + ] + }, + "VisitFields": { + "type": "object", + "description": "The details of the new vet visit.", + "properties": { + "date": { + "type": "string", + "format": "date", + "description": "The date of the visit.", + "example": "2013-01-01" + }, + "description": { + "type": "string", + "description": "The description for the visit.", + "example": "rabies shot", + "maxLength": 255, + "minLength": 1 + } + }, + "required": [ + "description" + ] + }, + "Specialty": { + "type": "object", + "description": "Fields of specialty of vets.", + "properties": { + "id": { + "type": "integer", + "format": "int32", + "description": "The ID of the specialty.", + "example": 1, + "minimum": 0, + "readOnly": true + }, + "name": { + "type": "string", + "description": "The name of the specialty.", + "example": "radiology", + "maxLength": 80, + "minLength": 1 + } + }, + "required": [ + "id", + "name" + ] + }, + "Vet": { + "type": "object", + "description": "A veterinarian.", + "properties": { + "firstName": { + "type": "string", + "description": "The first name of the vet.", + "example": "James", + "maxLength": 30, + "minLength": 1, + "pattern": "^[\\p{L}]+([ '-][\\p{L}]+){0,2}$" + }, + "lastName": { + "type": "string", + "description": "The last name of the vet.", + "example": "Carter", + "maxLength": 30, + "minLength": 1, + "pattern": "^[\\p{L}]+([ '-][\\p{L}]+){0,2}\\.?$" + }, + "specialties": { + "type": "array", + "description": "The specialties of the vet.", + "items": { + "$ref": "#/components/schemas/Specialty" + } + }, + "id": { + "type": "integer", + "format": "int32", + "description": "The ID of the vet.", + "example": 1, + "minimum": 0, + "readOnly": true + } + }, + "required": [ + "firstName", + "id", + "lastName", + "specialties" + ] + }, + "PetType": { + "type": "object", + "description": "A pet type.", + "properties": { + "name": { + "type": "string", + "description": "The name of the pet type.", + "example": "cat", + "maxLength": 80, + "minLength": 1 + }, + "id": { + "type": "integer", + "format": "int32", + "description": "The ID of the pet type.", + "example": 1, + "minimum": 0 + } + }, + "required": [ + "id", + "name" + ] + }, + "Pet": { + "type": "object", + "description": "A pet.", + "properties": { + "name": { + "type": "string", + "description": "The name of the pet.", + "example": "Leo", + "maxLength": 30, + "minLength": 0 + }, + "birthDate": { + "type": "string", + "format": "date", + "description": "The date of birth of the pet.", + "example": "2010-09-07" + }, + "type": { + "$ref": "#/components/schemas/PetType" + }, + "id": { + "type": "integer", + "format": "int32", + "description": "The ID of the pet.", + "example": 1, + "minimum": 0, + "readOnly": true + }, + "ownerId": { + "type": "integer", + "format": "int32", + "description": "The ID of the pet's owner.", + "example": 1, + "minimum": 0, + "readOnly": true + }, + "visits": { + "type": "array", + "description": "Vet visit bookings for this pet.", + "items": { + "$ref": "#/components/schemas/Visit" + }, + "readOnly": true + } + }, + "required": [ + "birthDate", + "id", + "name", + "type", + "visits" + ] + }, + "Owner": { + "type": "object", + "description": "A pet owner.", + "properties": { + "firstName": { + "type": "string", + "description": "The first name of the pet owner.", + "example": "George", + "maxLength": 30, + "minLength": 1, + "pattern": "^[\\p{L}]+([ '-][\\p{L}]+){0,2}$" + }, + "lastName": { + "type": "string", + "description": "The last name of the pet owner.", + "example": "Franklin", + "maxLength": 30, + "minLength": 1, + "pattern": "^[\\p{L}]+([ '-][\\p{L}]+){0,2}\\.?$" + }, + "address": { + "type": "string", + "description": "The postal address of the pet owner.", + "example": "110 W. Liberty St.", + "maxLength": 255, + "minLength": 1 + }, + "city": { + "type": "string", + "description": "The city of the pet owner.", + "example": "Madison", + "maxLength": 80, + "minLength": 1 + }, + "telephone": { + "type": "string", + "description": "The telephone number of the pet owner.", + "example": "6085551023", + "maxLength": 20, + "minLength": 1, + "pattern": "^[0-9]*$" + }, + "id": { + "type": "integer", + "format": "int32", + "description": "The ID of the pet owner.", + "example": 1, + "minimum": 0, + "readOnly": true + }, + "pets": { + "type": "array", + "description": "The pets owned by this individual including any booked vet visits.", + "items": { + "$ref": "#/components/schemas/Pet" + }, + "readOnly": true + } + }, + "required": [ + "address", + "city", + "firstName", + "lastName", + "pets", + "telephone" + ] + }, + "OwnerFields": { + "type": "object", + "description": "The pet owner", + "properties": { + "firstName": { + "type": "string", + "description": "The first name of the pet owner.", + "example": "George", + "maxLength": 30, + "minLength": 1, + "pattern": "^[\\p{L}]+([ '-][\\p{L}]+){0,2}$" + }, + "lastName": { + "type": "string", + "description": "The last name of the pet owner.", + "example": "Franklin", + "maxLength": 30, + "minLength": 1, + "pattern": "^[\\p{L}]+([ '-][\\p{L}]+){0,2}\\.?$" + }, + "address": { + "type": "string", + "description": "The postal address of the pet owner.", + "example": "110 W. Liberty St.", + "maxLength": 255, + "minLength": 1 + }, + "city": { + "type": "string", + "description": "The city of the pet owner.", + "example": "Madison", + "maxLength": 80, + "minLength": 1 + }, + "telephone": { + "type": "string", + "description": "The telephone number of the pet owner.", + "example": "6085551023", + "maxLength": 20, + "minLength": 1, + "pattern": "^[0-9]*$" + } + }, + "required": [ + "address", + "city", + "firstName", + "lastName", + "telephone" + ] + }, + "PetFields": { + "type": "object", + "description": "The details of the new pet.", + "properties": { + "name": { + "type": "string", + "description": "The name of the pet.", + "example": "Leo", + "maxLength": 30, + "minLength": 0 + }, + "birthDate": { + "type": "string", + "format": "date", + "description": "The date of birth of the pet.", + "example": "2010-09-07" + }, + "type": { + "$ref": "#/components/schemas/PetType" + } + }, + "required": [ + "birthDate", + "name", + "type" + ] + }, + "Role": { + "type": "object", + "description": "A role.", + "properties": { + "name": { + "type": "string", + "description": "The role's name", + "example": "admin", + "maxLength": 80, + "minLength": 1 + } + }, + "required": [ + "name" + ] + }, + "User": { + "type": "object", + "description": "The user", + "properties": { + "username": { + "type": "string", + "description": "The username", + "example": "john.doe", + "maxLength": 80, + "minLength": 1 + }, + "password": { + "type": "string", + "description": "The password", + "example": "1234abc", + "maxLength": 80, + "minLength": 1 + }, + "enabled": { + "type": "boolean", + "description": "Indicates if the user is enabled", + "example": true + }, + "roles": { + "type": "array", + "description": "The roles of an user", + "items": { + "$ref": "#/components/schemas/Role" + } + } + }, + "required": [ + "username" + ] + }, + "PetTypeFields": { + "type": "object", + "description": "The pet type", + "properties": { + "name": { + "type": "string", + "description": "The name of the pet type.", + "example": "cat", + "maxLength": 80, + "minLength": 1 + } + }, + "required": [ + "name" + ] + }, + "PetPage": { + "type": "object", + "description": "A page of pets.", + "properties": { + "content": { + "type": "array", + "description": "Pets in the requested page.", + "items": { + "$ref": "#/components/schemas/Pet" + } + }, + "page": { + "type": "integer", + "format": "int32", + "description": "Zero-based page index.", + "example": 0, + "minimum": 0 + }, + "size": { + "type": "integer", + "format": "int32", + "description": "Requested page size.", + "example": 5, + "minimum": 1 + }, + "totalElements": { + "type": "integer", + "format": "int64", + "description": "Total number of pets matching the request.", + "example": 10, + "minimum": 0 + }, + "totalPages": { + "type": "integer", + "format": "int32", + "description": "Total number of pages matching the request.", + "example": 2, + "minimum": 0 + } + }, + "required": [ + "content", + "page", + "size", + "totalElements", + "totalPages" + ] + }, + "OwnerPage": { + "type": "object", + "description": "A page of pet owners.", + "properties": { + "content": { + "type": "array", + "description": "Pet owners in the requested page.", + "items": { + "$ref": "#/components/schemas/Owner" + } + }, + "page": { + "type": "integer", + "format": "int32", + "description": "Zero-based page index.", + "example": 0, + "minimum": 0 + }, + "size": { + "type": "integer", + "format": "int32", + "description": "Requested page size.", + "example": 5, + "minimum": 1 + }, + "totalElements": { + "type": "integer", + "format": "int64", + "description": "Total number of owners matching the request.", + "example": 10, + "minimum": 0 + }, + "totalPages": { + "type": "integer", + "format": "int32", + "description": "Total number of pages matching the request.", + "example": 2, + "minimum": 0 + } + }, + "required": [ + "content", + "page", + "size", + "totalElements", + "totalPages" + ] + } + } + } +} diff --git a/scripts/build/docker-compose.build.yml b/scripts/build/docker-compose.build.yml index 457700259..19f025a4c 100644 --- a/scripts/build/docker-compose.build.yml +++ b/scripts/build/docker-compose.build.yml @@ -199,6 +199,7 @@ services: cp cs/rest/spring-rest-example/target/spring-rest-example-sut.jar /dist/ cp cs/rest/digitalbanking/target/digitalbanking-sut.jar /dist/ cp cs/rest/kafka-rest/kafka-rest/target/kafka-rest-sut.jar /dist/ + cp cs/rest/petclinic-rest/target/petclinic-rest-sut.jar /dist/ if [ "$${BUILD_EVOMASTER:-false}" = "true" ]; then cp em/external/web/spring-petclinic/target/spring-petclinic-evomaster-runner.jar /dist/ cp em/external/grpc/signal-registration/target/signal-registration-evomaster-runner.jar /dist/ @@ -208,6 +209,7 @@ services: cp em/external/rest/spring-rest-example/target/spring-rest-example-evomaster-runner.jar /dist/ cp em/external/rest/digitalbanking/target/digitalbanking-evomaster-runner.jar /dist/ cp em/external/rest/kafka-rest/target/kafka-rest-evomaster-runner.jar /dist/ + cp em/external/rest/petclinic-rest/target/petclinic-rest-evomaster-runner.jar /dist/ fi echo 'JDK 17 Maven build completed' diff --git a/scripts/dist-wb.py b/scripts/dist-wb.py index fb08e2fe0..b0e4f1f00 100644 --- a/scripts/dist-wb.py +++ b/scripts/dist-wb.py @@ -292,6 +292,9 @@ def build_jdk_17_maven(): copy(folder + "/cs/rest/kafka-rest/kafka-rest/target/kafka-rest-sut.jar", DIST) copy(folder + "/em/external/rest/kafka-rest/target/kafka-rest-evomaster-runner.jar", DIST) + copy(folder + "/cs/rest/petclinic-rest/target/petclinic-rest-sut.jar", DIST) + copy(folder + "/em/external/rest/petclinic-rest/target/petclinic-rest-evomaster-runner.jar", DIST) + #################### def build_jdk_21_maven(): folder = "jdk_21_maven" diff --git a/scripts/dockerize/data/sut.csv b/scripts/dockerize/data/sut.csv index ffd487d56..5b20bc228 100644 --- a/scripts/dockerize/data/sut.csv +++ b/scripts/dockerize/data/sut.csv @@ -48,3 +48,4 @@ komga,TRUE,,--server.port=8080 --komga.config-dir=/tmp/komga --komga.database.fi movies-xml,TRUE,,--server.port=8080,http://localhost:8080/v3/api-docs,http://localhost:8080,FALSE,, gdpr-kv,TRUE,,--server.port=8080 --server.aws.endpoint=http://db:4566 --server.aws.region=us-west-2 --server.aws.use-localstack=true,http://localhost:8080/v3/api-docs,http://localhost:8080,FALSE,db,"[{""image_name"": ""localstack/localstack:3.6"", ""tmp_fs"": """", ""environment"": ""SERVICES: dynamodb;DEFAULT_REGION: us-west-2;AWS_DEFAULT_REGION: us-west-2"", ""volume"": ""./additional_files/gdpr-kv/init-dynamodb.sh:/etc/localstack/init/ready.d/init-dynamodb.sh"", ""health_check_command"": ""awslocal dynamodb get-item --table-name policies --key '{\""purpose\"":{\""S\"":\""DEMO_PURPOSE\""}}' | grep -q DEMO_PURPOSE""}]" kafka-rest,TRUE,-Dorg.apache.logging.log4j.level=INFO,kafka-rest.properties,,http://localhost:8080,TRUE,kafka,"[{""name"": ""kafka"", ""image_name"": ""apache/kafka:4.3.1"", ""tmp_fs"": """", ""environment"": ""KAFKA_NODE_ID: 1;KAFKA_PROCESS_ROLES: broker,controller;KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093;KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092;KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER;KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT;KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:9093;KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1;KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1;KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1;KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0"", ""volume"": """", ""health_check_command"": ""/opt/kafka/bin/kafka-broker-api-versions.sh --bootstrap-server localhost:9092 > /dev/null""}]" +petclinic-rest,TRUE,,--server.port=8080 --spring.jpa.show-sql=false,http://localhost:8080/petclinic/v3/api-docs,http://localhost:8080,FALSE,, diff --git a/statistics/data.csv b/statistics/data.csv index ac11b3317..045009ebc 100644 --- a/statistics/data.csv +++ b/statistics/data.csv @@ -60,4 +60,5 @@ FALSE,ind0,REST,Java,JDK 8,Gradle,103,17039,PostgreSQL,Proprietary,20,FALSE,UNDE FALSE,ind1,REST,Java;Kotlin,JDK 11,Gradle,163,15240,PostgreSQL,Proprietary,53,FALSE,UNDEFINED TRUE,movies-xml,REST,Java,JDK 21,Maven,22,2502,H2,LGPL,7,FALSE,https://github.com/suarezrominajulieta/movies-xml TRUE,kafka-rest,REST,Java,JDK 17,Maven,475,81418,Kafka,Confluent,50,FALSE,https://github.com/confluentinc/kafka-rest +TRUE,petclinic-rest,REST,Java,JDK 17,Maven,109,8675,H2,Apache,43,FALSE,https://github.com/spring-petclinic/spring-petclinic-rest diff --git a/statistics/http-verbs.csv b/statistics/http-verbs.csv index d420d45b2..1471f9e31 100644 --- a/statistics/http-verbs.csv +++ b/statistics/http-verbs.csv @@ -27,6 +27,7 @@ ocvn,96,0,96,0,0,0,0,0,0,0 ohsome-api,67,0,67,0,0,0,0,0,0,0 pay-publicapi,9,0,7,0,0,0,0,0,0,0 person-controller,5,2,2,3,0,0,0,0,0,0 +petclinic-rest,16,8,9,7,1,1,1,0,0,0 proxyprint,48,14,30,10,5,4,4,0,0,0 quartz-manager,8,1,2,0,0,0,0,0,0,0 redis-sample,4,0,0,0,0,0,0,0,0,0 diff --git a/statistics/http-verbs.md b/statistics/http-verbs.md index b16f008cc..0b825e60e 100644 --- a/statistics/http-verbs.md +++ b/statistics/http-verbs.md @@ -28,6 +28,7 @@ | ohsome-api | 67 | 0 | 67 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 134 | | pay-publicapi | 9 | 0 | 7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 16 | | person-controller | 5 | 2 | 2 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 12 | +| petclinic-rest | 16 | 8 | 9 | 7 | 1 | 1 | 1 | 0 | 0 | 0 | 43 | | proxyprint | 48 | 14 | 30 | 10 | 5 | 4 | 4 | 0 | 0 | 0 | 115 | | quartz-manager | 8 | 1 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 11 | | redis-sample | 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 4 | @@ -49,4 +50,4 @@ | user-management | 7 | 2 | 7 | 5 | 0 | 0 | 0 | 0 | 0 | 0 | 21 | | webgoat | 50 | 10 | 112 | 8 | 8 | 8 | 8 | 0 | 0 | 0 | 204 | | youtube-mock | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | -| Total | 932 | 152 | 679 | 144 | 20 | 19 | 52 | 0 | 0 | 0 | 1998 | +| Total | 948 | 160 | 688 | 151 | 21 | 20 | 53 | 0 | 0 | 0 | 2041 | diff --git a/statistics/table_wfd.md b/statistics/table_wfd.md index 3dfc641f7..d262fb45a 100644 --- a/statistics/table_wfd.md +++ b/statistics/table_wfd.md @@ -36,6 +36,7 @@ |REST|__ohsome-api__|14166|87|134|Java|JDK 17|Maven|OSHDB|| |REST|__pay-publicapi__|34576|377|10|Java|JDK 11|Maven|Redis|✓| |REST|__person-controller__|1112|16|12|Java|JDK 21|Maven|MongoDB|| +|REST|__petclinic-rest__|8675|109|43|Java|JDK 17|Maven|H2|| |REST|__proxyprint__|8338|73|74|Java|JDK 8|Maven|H2|✓| |REST|__quartz-manager__|5068|129|11|Java|JDK 11|Maven||✓| |REST|__redis-sample__|1006|18|4|Java|JDK 21|Maven|Redis||