This PetClinic example uses Spring for GraphQL, that is part of Spring Boot since version 2.7.
It implements a GraphQL API for the PetClinic and provides an example Frontend for the API.
Versions currently in use are Spring Boot 3.2.x and Spring for GraphQL 1.2.x.
Some features that are built in:
graphql/*Controller
-classes, e.g. SpecialtyController
and VetController
)VisitController#onNewVisit
) including integration test (see VisitSubscriptionTest
) and examples below PetClinicRuntimeWiringConfiguration
and DateCoercing
)Person
) and Unions (GraphQL Type AddVetPayload
), see class PetClinicRuntimeWiringConfiguration
/graphql
http and WebSocket endpoints are secured and can only be accessed using a JWT token. More fine grained security is implemented using @PreAuthorize
(see VetService
)
addVet
mutation is only allowed for users with ROLE_MANAGER
OwnerController
. The result of the owners
field is a Connection
object defined in the Cursor Connection specification.
relayStylePagination
helper function to automatically manage the Client-side cache with new objects read using the after
cursor query argument. (See OwnerSearchPage.tsx
) petclinic-graphiql
test
folder for typical GraphQL endpoint tests, including tests for security
e2e-tests
folder for some Playwright based end-to-end tests that test the running application in a real browser. Read description below how to run the tests..github/workflows/build-app.yml
)You can run the sample application with two ways:
To run the application (backend, GraphiQL and React frontend) in GitPod, simply click on the "Open in GitPod" button at the top of this README.
After clicking on the GitPod button, GitPod creates a new workspace including an Editor for you, builds the application and starts backend and frontend. That might take some time!
When backend and frontend are running, GitPod opens two new browser tabs, one with GraphiQL and one with the PetClinic backend. For login options, see below "Accessing the GraphQL API"
Note that the workspace is your personal workspace, you can make changes, save files, re-open the workspace at any time and you can even create git commits and pull requests from it. For more information see GitPod documentation.
In the GitPod editor you can make changes to the app, and after saving the app will be recompiled and redeployed automatically.
Recently GitPod has added support for JetBrain IDEs like IntelliJ. While this support is currenty beta only, you can try it and open the PetClinic in IntelliJ. Note that in this scenario you're still working on a complete, ready-to-use workspace in the cloud. Only the IntelliJ UI runs locally at your maching.
Please read the setup instructions here.
The server is implemented in the backend
folder and can be started either from your IDE (org.springframework.samples.petclinic.PetClinicApplication
) or
using maven from the root folder of the repository:
./mvnw spring-boot:run -pl backend
Note: the server runs on port 9977, so make sure, this port is available.
docker-compose
needs to be in your pathWhile you can access the whole GraphQL API from GraphiQL this demo application also contains a modified version of the classic PetClinic UI. Compared to the original client this client is built as a Single-Page-Application using React and Apollo GraphQL and has slightly different features to make it a more realistic use-case for GraphQL.
You can install and start the frontend by using pnpm:
cd ./frontend
pnpm install
pnpm codegen
pnpm start
The running frontend can be accessed on http://localhost:3080.
For valid users to login, see list above.
There are two scenarios: local development environment and "production" environment
Local development
In local development:
docker-compose.yml
file in the root folderIn this scenario, the vite server acts also as a reverse proxy, that proxies all requests to /api
, /graphql
and /graphqlws
to the backend server (localhost:9977). The proxy is configured in frontend/vite.config.ts
If you like you can run the customized graphiql with its own Vite development server (using pnpm dev
in petclinic-graphiql
) that runs on http://localhost:3081.
This is handy if you want to make changes to GraphiQL.
"Production" environment
In this setup, the backend and frontend process run as docker containers using a docker-compose setup that is described in docker-compose-petclinic.yml
:
Here the nginx acts as the proxy to the backend.
You can build the docker images for backend and frontend using the build-local.sh
scripts. Also, these images are build during the GitHub workflow.
You can access the GraphQL API via the included customized version of GraphiQL.
The included GraphiQL adds support for login to the original GraphiQL.
You can use the following users for login:
createVet
MutationAfter starting the server, GraphiQL runs on http://localhost:9977
Here you can find some sample queries that you can copy+paste and run in GraphiQL. Feel free to explore and try more 😊.
Query find first 2 owners whose lastname starts with "D" and their pets, order by lastname and firstname
query {
owners(
first: 2
filter: { lastName: "d" }
order: [{ field: lastName }, { field: firstName, direction: DESC }]
) {
edges {
cursor
node {
id
firstName
lastName
pets {
id
name
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
The following query should return two items, but we have more then two owners in the database staring with a d
. Thus, the pageInfo.hasNextPage
-field returned in the result of the query above is true
and the endCursor
points to the last object returned. Using this cursor as after
we can receive the next batch of Owners:
query {
owners(
first: 2
after: "T18y"
filter: { lastName: "d" }
order: [{ field: lastName }, { field: firstName, direction: DESC }]
) {
edges {
cursor
node {
id
firstName
lastName
pets {
id
name
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
Add a new Visit using a mutation (can be done with user joe
and susi
) and read id and pet of the
new created visit:
mutation {
addVisit(input:{
petId:3,
description:"Check teeth",
date:"2022/03/30",
vetId:1
}) {
newVisit:visit {
id
pet {
id
name
birthDate
}
}
}
}
Add a new veterinarian. This is only allowed for users with ROLE_MANAGER
and that is susi
:
mutation {
addVet(input: {
firstName: "Dagmar",
lastName: "Smith",
specialtyIds: [1, 3]}) {
... on AddVetSuccessPayload {
newVet: vet {
id
specialties {
id
name
}
}
}
... on AddVetErrorPayload {
error
}
}
}
Listen for new visits using a Subscription
This mutation selects the treating veterinarian of the new created Visit and the pet that will be visiting. You can either create a new Visit using the mutation above or using the frontend application.
subscription {
onNewVisit {
description
treatingVet {
id
firstName
lastName
}
pet {
id
name
}
}
}
Note: In the frontend application, you can open an Owner an see all its pets including their visits. If you add a new visit to one of the pets, in all other browser windows that have the Owner page with that Owner open, the new visit should be added to the table automatically, because the OwnerPage
React component uses a subscription to update the table contents in the background.
The backend includes a Spring Petclinic-specific customized version of GraphiQL. Compared to GraphiQL that is embedded by default, the customized version has a login form so that it can send JWT Authentication header with each request to the GraphQL backend.
Please see the subproject petclinic-graphiql
for more information.
Inside the folder e2e-tests
you find some Playwright-based end-to-end tests.
To run the test, please make sure, the backend and the frontend processes are running, as described above.
Then install playwright and all its dependencies including the required browsers by running
cd e2e-tests
pnpm install
Then you can use pnpm
to start the test:
pnpm test
will execute all tests in headless mode in all three configured browsers (Chrome, Firefox, Safari)
pnpm test:ui
opens the tests in Playwright's UI mode
pnpm test:headed
: runs the tests in a headed (i.e. visible) browser (by default Chrome).
pnpm test:docker-compose
runs the test agains the docker-compose-based setup (localhost:3090/localhost:3091)
For writing and running Playwright tests I prefer VS code with the Playwright extension
But if you want to develop and run the tests in IntelliJ, you can install the Test Automation Plug-in by Jetbrains.
If you like to help and contribute you're more than welcome! Please open an issue or a Pull Request
Initial implementation of this GraphQL-based PetClinic example: Nils Hartmann, Twitter