├── .gitignore
├── README.md
├── images
├── Architecture.png
├── Cloud9.png
├── c9attachrole.png
├── c9disableiam.png
├── c9instancerole.png
├── createrole.png
├── docker-local-run.png
└── petclinic.png
├── petclinic
├── Dockerfile
├── docker-compose.yml
├── pom.xml
├── readme.md
└── src
│ ├── checkstyle
│ ├── nohttp-checkstyle-suppressions.xml
│ └── nohttp-checkstyle.xml
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── springframework
│ │ │ └── samples
│ │ │ └── petclinic
│ │ │ ├── PetClinicApplication.java
│ │ │ ├── model
│ │ │ ├── BaseEntity.java
│ │ │ ├── NamedEntity.java
│ │ │ ├── Person.java
│ │ │ └── package-info.java
│ │ │ ├── owner
│ │ │ ├── Owner.java
│ │ │ ├── OwnerController.java
│ │ │ ├── OwnerRepository.java
│ │ │ ├── Pet.java
│ │ │ ├── PetController.java
│ │ │ ├── PetRepository.java
│ │ │ ├── PetType.java
│ │ │ ├── PetTypeFormatter.java
│ │ │ ├── PetValidator.java
│ │ │ └── VisitController.java
│ │ │ ├── system
│ │ │ ├── CacheConfiguration.java
│ │ │ ├── CrashController.java
│ │ │ └── WelcomeController.java
│ │ │ ├── vet
│ │ │ ├── Specialty.java
│ │ │ ├── Vet.java
│ │ │ ├── VetController.java
│ │ │ ├── VetRepository.java
│ │ │ └── Vets.java
│ │ │ └── visit
│ │ │ ├── Visit.java
│ │ │ └── VisitRepository.java
│ ├── less
│ │ ├── header.less
│ │ ├── petclinic.less
│ │ ├── responsive.less
│ │ └── typography.less
│ ├── resources
│ │ ├── application-mysql.properties
│ │ ├── application.properties
│ │ ├── banner.txt
│ │ ├── db
│ │ │ ├── h2
│ │ │ │ ├── data.sql
│ │ │ │ └── schema.sql
│ │ │ ├── hsqldb
│ │ │ │ ├── data.sql
│ │ │ │ └── schema.sql
│ │ │ └── mysql
│ │ │ │ ├── data.sql
│ │ │ │ ├── petclinic_db_setup_mysql.txt
│ │ │ │ ├── schema.sql
│ │ │ │ └── user.sql
│ │ ├── messages
│ │ │ ├── messages.properties
│ │ │ ├── messages_de.properties
│ │ │ ├── messages_en.properties
│ │ │ └── messages_es.properties
│ │ ├── static
│ │ │ └── resources
│ │ │ │ ├── fonts
│ │ │ │ ├── montserrat-webfont.eot
│ │ │ │ ├── montserrat-webfont.svg
│ │ │ │ ├── montserrat-webfont.ttf
│ │ │ │ ├── montserrat-webfont.woff
│ │ │ │ ├── varela_round-webfont.eot
│ │ │ │ ├── varela_round-webfont.svg
│ │ │ │ ├── varela_round-webfont.ttf
│ │ │ │ └── varela_round-webfont.woff
│ │ │ │ └── images
│ │ │ │ ├── favicon.png
│ │ │ │ ├── pets.png
│ │ │ │ ├── platform-bg.png
│ │ │ │ ├── spring-logo-dataflow-mobile.png
│ │ │ │ ├── spring-logo-dataflow.png
│ │ │ │ └── spring-pivotal-logo.png
│ │ └── templates
│ │ │ ├── error.html
│ │ │ ├── fragments
│ │ │ ├── inputField.html
│ │ │ ├── layout.html
│ │ │ └── selectField.html
│ │ │ ├── owners
│ │ │ ├── createOrUpdateOwnerForm.html
│ │ │ ├── findOwners.html
│ │ │ ├── ownerDetails.html
│ │ │ └── ownersList.html
│ │ │ ├── pets
│ │ │ ├── createOrUpdatePetForm.html
│ │ │ └── createOrUpdateVisitForm.html
│ │ │ ├── vets
│ │ │ └── vetList.html
│ │ │ └── welcome.html
│ └── wro
│ │ ├── wro.properties
│ │ └── wro.xml
│ └── test
│ ├── java
│ └── org
│ │ └── springframework
│ │ └── samples
│ │ └── petclinic
│ │ ├── PetclinicIntegrationTests.java
│ │ ├── model
│ │ └── ValidatorTests.java
│ │ ├── owner
│ │ ├── OwnerControllerTests.java
│ │ ├── PetControllerTests.java
│ │ ├── PetTypeFormatterTests.java
│ │ └── VisitControllerTests.java
│ │ ├── service
│ │ ├── ClinicServiceTests.java
│ │ └── EntityUtils.java
│ │ ├── system
│ │ └── CrashControllerTests.java
│ │ └── vet
│ │ ├── VetControllerTests.java
│ │ └── VetTests.java
│ └── jmeter
│ └── petclinic_test_plan.jmx
└── terraform
├── appbuild.tf
├── autoscaling.tf
├── codebuild.tf
├── codecommit.tf
├── codepipeline.tf
├── ecr.tf
├── iam.tf
├── parameters.tf
├── provider.tf
├── push2codecommit.tf
├── rds.tf
├── security-groups.tf
├── services.tf
├── terraform.tfvars
├── variables.tf
└── vpc.tf
/.gitignore:
--------------------------------------------------------------------------------
1 | **/.terraform/**
2 | terraform.tfstate
3 | terraform.tfstate.backup
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/images/Architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-apprunner-terraform/f000687a298a05ec24581325d5325ed4e6e4c666/images/Architecture.png
--------------------------------------------------------------------------------
/images/Cloud9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-apprunner-terraform/f000687a298a05ec24581325d5325ed4e6e4c666/images/Cloud9.png
--------------------------------------------------------------------------------
/images/c9attachrole.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-apprunner-terraform/f000687a298a05ec24581325d5325ed4e6e4c666/images/c9attachrole.png
--------------------------------------------------------------------------------
/images/c9disableiam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-apprunner-terraform/f000687a298a05ec24581325d5325ed4e6e4c666/images/c9disableiam.png
--------------------------------------------------------------------------------
/images/c9instancerole.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-apprunner-terraform/f000687a298a05ec24581325d5325ed4e6e4c666/images/c9instancerole.png
--------------------------------------------------------------------------------
/images/createrole.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-apprunner-terraform/f000687a298a05ec24581325d5325ed4e6e4c666/images/createrole.png
--------------------------------------------------------------------------------
/images/docker-local-run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-apprunner-terraform/f000687a298a05ec24581325d5325ed4e6e4c666/images/docker-local-run.png
--------------------------------------------------------------------------------
/images/petclinic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aws-samples/aws-apprunner-terraform/f000687a298a05ec24581325d5325ed4e6e4c666/images/petclinic.png
--------------------------------------------------------------------------------
/petclinic/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM public.ecr.aws/bitnami/java:latest
2 | VOLUME /tmp
3 | ADD target/spring-petclinic-2.3.0.jar app.jar
4 | EXPOSE 80
5 | RUN apt-get update
6 | RUN apt-get -y install awscli
7 | ENTRYPOINT env spring.datasource.password=$(aws ssm get-parameter --name /database/password --with-decrypt --region $AWS_REGION | grep Value | cut -d '"' -f4) java -Djava.security.egd=file:/dev/./urandom -jar /app.jar
8 |
--------------------------------------------------------------------------------
/petclinic/docker-compose.yml:
--------------------------------------------------------------------------------
1 | mysql:
2 | image: mysql:5.7
3 | ports:
4 | - "3306:3306"
5 | environment:
6 | - MYSQL_ROOT_PASSWORD=petclinic
7 | - MYSQL_ALLOW_EMPTY_PASSWORD=true
8 | - MYSQL_USER=petclinic
9 | - MYSQL_PASSWORD=petclinic
10 | - MYSQL_DATABASE=petclinic
11 | volumes:
12 | - "./conf.d:/etc/mysql/conf.d:ro"
13 |
--------------------------------------------------------------------------------
/petclinic/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | org.springframework.samples
7 | spring-petclinic
8 | 2.3.0
9 |
10 |
11 | org.springframework.boot
12 | spring-boot-starter-parent
13 | 2.3.3.RELEASE
14 |
15 | petclinic
16 |
17 |
18 |
19 |
20 | 1.8
21 | UTF-8
22 | UTF-8
23 |
24 |
25 | 3.3.6
26 | 1.11.4
27 | 2.2.4
28 | 1.8.0
29 |
30 | 0.8.5
31 | 0.0.4.RELEASE
32 | 0.0.25
33 |
34 |
35 |
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-actuator
40 |
41 |
42 | org.springframework.boot
43 | spring-boot-starter-cache
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-data-jpa
48 |
49 |
50 | org.springframework.boot
51 | spring-boot-starter-web
52 |
53 |
54 | org.springframework.boot
55 | spring-boot-starter-validation
56 |
57 |
58 | org.springframework.boot
59 | spring-boot-starter-thymeleaf
60 |
61 |
62 | org.springframework.boot
63 | spring-boot-starter-test
64 | test
65 |
66 |
67 | org.junit.vintage
68 | junit-vintage-engine
69 |
70 |
71 |
72 |
73 |
74 |
75 | com.h2database
76 | h2
77 | runtime
78 |
79 |
80 | mysql
81 | mysql-connector-java
82 | runtime
83 |
84 |
85 |
86 |
87 | javax.cache
88 | cache-api
89 |
90 |
91 | org.ehcache
92 | ehcache
93 |
94 |
95 |
96 |
97 | org.webjars
98 | webjars-locator-core
99 |
100 |
101 | org.webjars
102 | jquery
103 | ${webjars-jquery.version}
104 |
105 |
106 | org.webjars
107 | jquery-ui
108 | ${webjars-jquery-ui.version}
109 |
110 |
111 | org.webjars
112 | bootstrap
113 | ${webjars-bootstrap.version}
114 |
115 |
116 |
117 |
118 |
119 | org.junit.jupiter
120 | junit-jupiter-engine
121 | test
122 |
123 |
124 | org.mockito
125 | mockito-junit-jupiter
126 | test
127 |
128 |
129 |
130 | org.springframework.boot
131 | spring-boot-devtools
132 | true
133 |
134 |
135 |
136 |
137 |
138 |
139 | io.spring.javaformat
140 | spring-javaformat-maven-plugin
141 | ${spring-format.version}
142 |
143 |
144 | validate
145 |
146 | validate
147 |
148 |
149 |
150 |
151 |
152 | org.apache.maven.plugins
153 | maven-checkstyle-plugin
154 | 3.1.1
155 |
156 |
157 | com.puppycrawl.tools
158 | checkstyle
159 | 8.32
160 |
161 |
162 | io.spring.nohttp
163 | nohttp-checkstyle
164 | ${nohttp-checkstyle.version}
165 |
166 |
167 |
168 |
169 | nohttp-checkstyle-validation
170 | validate
171 |
172 | src/checkstyle/nohttp-checkstyle.xml
173 | src/checkstyle/nohttp-checkstyle-suppressions.xml
174 | UTF-8
175 | ${basedir}
176 | **/*
177 | **/.git/**/*,**/.idea/**/*,**/target/**/,**/.flattened-pom.xml,**/*.class
178 |
179 |
180 | check
181 |
182 |
183 |
184 |
185 |
186 | org.springframework.boot
187 | spring-boot-maven-plugin
188 |
189 |
190 |
192 |
193 | build-info
194 |
195 |
196 |
197 | ${project.build.sourceEncoding}
198 | ${project.reporting.outputEncoding}
199 | ${maven.compiler.source}
200 | ${maven.compiler.target}
201 |
202 |
203 |
204 |
205 |
206 |
207 | org.jacoco
208 | jacoco-maven-plugin
209 | ${jacoco.version}
210 |
211 |
212 |
213 | prepare-agent
214 |
215 |
216 |
217 | report
218 | prepare-package
219 |
220 | report
221 |
222 |
223 |
224 |
225 |
226 |
228 |
229 | pl.project13.maven
230 | git-commit-id-plugin
231 |
232 |
233 |
234 | revision
235 |
236 |
237 |
238 |
239 | true
240 | yyyy-MM-dd'T'HH:mm:ssZ
241 | true
242 | ${project.build.outputDirectory}/git.properties
243 |
244 | false
245 |
246 |
247 |
248 |
249 | ro.isdc.wro4j
250 | wro4j-maven-plugin
251 | ${wro4j.version}
252 |
253 |
254 | generate-resources
255 |
256 | run
257 |
258 |
259 |
260 |
261 | ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory
262 | ${project.build.directory}/classes/static/resources/css
263 | ${basedir}/src/main/wro/wro.xml
264 | ${basedir}/src/main/wro/wro.properties
265 | ${basedir}/src/main/less
266 |
267 |
268 |
269 | org.webjars
270 | bootstrap
271 | ${webjars-bootstrap.version}
272 |
273 |
274 | org.mockito
275 | mockito-core
276 | ${mockito.version}
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 | Apache License, Version 2.0
286 | https://www.apache.org/licenses/LICENSE-2.0
287 |
288 |
289 |
290 |
291 |
292 | spring-snapshots
293 | Spring Snapshots
294 | https://repo.spring.io/snapshot
295 |
296 | true
297 |
298 |
299 |
300 | spring-milestones
301 | Spring Milestones
302 | https://repo.spring.io/milestone
303 |
304 | false
305 |
306 |
307 |
308 |
309 |
310 |
311 | spring-snapshots
312 | Spring Snapshots
313 | https://repo.spring.io/snapshot
314 |
315 | true
316 |
317 |
318 |
319 | spring-milestones
320 | Spring Milestones
321 | https://repo.spring.io/milestone
322 |
323 | false
324 |
325 |
326 |
327 |
328 |
329 |
330 | m2e
331 |
332 |
333 | m2e.version
334 |
335 |
336 |
337 |
338 |
339 |
341 |
342 | org.eclipse.m2e
343 | lifecycle-mapping
344 | 1.0.0
345 |
346 |
347 |
348 |
349 |
350 | org.apache.maven.plugins
351 | maven-checkstyle-plugin
352 | [1,)
353 |
354 | check
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 | org.springframework.boot
364 | spring-boot-maven-plugin
365 | [1,)
366 |
367 | build-info
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
--------------------------------------------------------------------------------
/petclinic/readme.md:
--------------------------------------------------------------------------------
1 | # Spring PetClinic Sample Application [](https://travis-ci.org/spring-projects/spring-petclinic/)
2 |
3 | ## Understanding the Spring Petclinic application with a few diagrams
4 | See the presentation here
5 |
6 | ## Running petclinic locally
7 | Petclinic is a [Spring Boot](https://spring.io/guides/gs/spring-boot) application built using [Maven](https://spring.io/guides/gs/maven/). You can build a jar file and run it from the command line:
8 |
9 | ```
10 | git clone https://github.com/spring-projects/spring-petclinic.git
11 | cd spring-petclinic
12 | ./mvnw package
13 | java -jar target/*.jar
14 | ```
15 |
16 | You can then access petclinic here: http://localhost:8080/
17 |
18 |
19 |
20 | Or you can run it from Maven directly using the Spring Boot Maven plugin. If you do this it will pick up changes that you make in the project immediately (changes to Java source files require a compile as well - most people use an IDE for this):
21 |
22 | ```
23 | ./mvnw spring-boot:run
24 | ```
25 |
26 | ## In case you find a bug/suggested improvement for Spring Petclinic
27 | Our issue tracker is available here: https://github.com/spring-projects/spring-petclinic/issues
28 |
29 |
30 | ## Database configuration
31 |
32 | In its default configuration, Petclinic uses an in-memory database (H2) which
33 | gets populated at startup with data. The h2 console is automatically exposed at `http://localhost:8080/h2-console`
34 | and it is possible to inspect the content of the database using the `jdbc:h2:mem:testdb` url.
35 |
36 | A similar setup is provided for MySql in case a persistent database configuration is needed. Note that whenever the database type is changed, the app needs to be run with a different profile: `spring.profiles.active=mysql` for MySql.
37 |
38 | You could start MySql locally with whatever installer works for your OS, or with docker:
39 |
40 | ```
41 | docker run -e MYSQL_USER=petclinic -e MYSQL_PASSWORD=petclinic -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=petclinic -p 3306:3306 mysql:5.7.8
42 | ```
43 |
44 | Further documentation is provided [here](https://github.com/spring-projects/spring-petclinic/blob/main/src/main/resources/db/mysql/petclinic_db_setup_mysql.txt).
45 |
46 | ## Working with Petclinic in your IDE
47 |
48 | ### Prerequisites
49 | The following items should be installed in your system:
50 | * Java 8 or newer.
51 | * git command line tool (https://help.github.com/articles/set-up-git)
52 | * Your preferred IDE
53 | * Eclipse with the m2e plugin. Note: when m2e is available, there is an m2 icon in `Help -> About` dialog. If m2e is
54 | not there, just follow the install process here: https://www.eclipse.org/m2e/
55 | * [Spring Tools Suite](https://spring.io/tools) (STS)
56 | * IntelliJ IDEA
57 | * [VS Code](https://code.visualstudio.com)
58 |
59 | ### Steps:
60 |
61 | 1) On the command line
62 | ```
63 | git clone https://github.com/spring-projects/spring-petclinic.git
64 | ```
65 | 2) Inside Eclipse or STS
66 | ```
67 | File -> Import -> Maven -> Existing Maven project
68 | ```
69 |
70 | Then either build on the command line `./mvnw generate-resources` or using the Eclipse launcher (right click on project and `Run As -> Maven install`) to generate the css. Run the application main method by right clicking on it and choosing `Run As -> Java Application`.
71 |
72 | 3) Inside IntelliJ IDEA
73 | In the main menu, choose `File -> Open` and select the Petclinic [pom.xml](pom.xml). Click on the `Open` button.
74 |
75 | CSS files are generated from the Maven build. You can either build them on the command line `./mvnw generate-resources` or right click on the `spring-petclinic` project then `Maven -> Generates sources and Update Folders`.
76 |
77 | A run configuration named `PetClinicApplication` should have been created for you if you're using a recent Ultimate version. Otherwise, run the application by right clicking on the `PetClinicApplication` main class and choosing `Run 'PetClinicApplication'`.
78 |
79 | 4) Navigate to Petclinic
80 |
81 | Visit [http://localhost:8080](http://localhost:8080) in your browser.
82 |
83 |
84 | ## Looking for something in particular?
85 |
86 | |Spring Boot Configuration | Class or Java property files |
87 | |--------------------------|---|
88 | |The Main Class | [PetClinicApplication](https://github.com/spring-projects/spring-petclinic/blob/main/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java) |
89 | |Properties Files | [application.properties](https://github.com/spring-projects/spring-petclinic/blob/main/src/main/resources) |
90 | |Caching | [CacheConfiguration](https://github.com/spring-projects/spring-petclinic/blob/main/src/main/java/org/springframework/samples/petclinic/system/CacheConfiguration.java) |
91 |
92 | ## Interesting Spring Petclinic branches and forks
93 |
94 | The Spring Petclinic "main" branch in the [spring-projects](https://github.com/spring-projects/spring-petclinic)
95 | GitHub org is the "canonical" implementation, currently based on Spring Boot and Thymeleaf. There are
96 | [quite a few forks](https://spring-petclinic.github.io/docs/forks.html) in a special GitHub org
97 | [spring-petclinic](https://github.com/spring-petclinic). If you have a special interest in a different technology stack
98 | that could be used to implement the Pet Clinic then please join the community there.
99 |
100 |
101 | ## Interaction with other open source projects
102 |
103 | One of the best parts about working on the Spring Petclinic application is that we have the opportunity to work in direct contact with many Open Source projects. We found some bugs/suggested improvements on various topics such as Spring, Spring Data, Bean Validation and even Eclipse! In many cases, they've been fixed/implemented in just a few days.
104 | Here is a list of them:
105 |
106 | | Name | Issue |
107 | |------|-------|
108 | | Spring JDBC: simplify usage of NamedParameterJdbcTemplate | [SPR-10256](https://jira.springsource.org/browse/SPR-10256) and [SPR-10257](https://jira.springsource.org/browse/SPR-10257) |
109 | | Bean Validation / Hibernate Validator: simplify Maven dependencies and backward compatibility |[HV-790](https://hibernate.atlassian.net/browse/HV-790) and [HV-792](https://hibernate.atlassian.net/browse/HV-792) |
110 | | Spring Data: provide more flexibility when working with JPQL queries | [DATAJPA-292](https://jira.springsource.org/browse/DATAJPA-292) |
111 |
112 |
113 | # Contributing
114 |
115 | The [issue tracker](https://github.com/spring-projects/spring-petclinic/issues) is the preferred channel for bug reports, features requests and submitting pull requests.
116 |
117 | For pull requests, editor preferences are available in the [editor config](.editorconfig) for easy use in common text editors. Read more and download plugins at . If you have not previously done so, please fill out and submit the [Contributor License Agreement](https://cla.pivotal.io/sign/spring).
118 |
119 | # License
120 |
121 | The Spring PetClinic sample application is released under version 2.0 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0).
122 |
123 | [spring-petclinic]: https://github.com/spring-projects/spring-petclinic
124 | [spring-framework-petclinic]: https://github.com/spring-petclinic/spring-framework-petclinic
125 | [spring-petclinic-angularjs]: https://github.com/spring-petclinic/spring-petclinic-angularjs
126 | [javaconfig branch]: https://github.com/spring-petclinic/spring-framework-petclinic/tree/javaconfig
127 | [spring-petclinic-angular]: https://github.com/spring-petclinic/spring-petclinic-angular
128 | [spring-petclinic-microservices]: https://github.com/spring-petclinic/spring-petclinic-microservices
129 | [spring-petclinic-reactjs]: https://github.com/spring-petclinic/spring-petclinic-reactjs
130 | [spring-petclinic-graphql]: https://github.com/spring-petclinic/spring-petclinic-graphql
131 | [spring-petclinic-kotlin]: https://github.com/spring-petclinic/spring-petclinic-kotlin
132 | [spring-petclinic-rest]: https://github.com/spring-petclinic/spring-petclinic-rest
133 |
--------------------------------------------------------------------------------
/petclinic/src/checkstyle/nohttp-checkstyle-suppressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/petclinic/src/checkstyle/nohttp-checkstyle.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.samples.petclinic;
18 |
19 | import org.springframework.boot.SpringApplication;
20 | import org.springframework.boot.autoconfigure.SpringBootApplication;
21 |
22 | /**
23 | * PetClinic Spring Boot Application.
24 | *
25 | * @author Dave Syer
26 | *
27 | */
28 | @SpringBootApplication(proxyBeanMethods = false)
29 | public class PetClinicApplication {
30 |
31 | public static void main(String[] args) {
32 | SpringApplication.run(PetClinicApplication.class, args);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.model;
17 |
18 | import java.io.Serializable;
19 |
20 | import javax.persistence.GeneratedValue;
21 | import javax.persistence.GenerationType;
22 | import javax.persistence.Id;
23 | import javax.persistence.MappedSuperclass;
24 |
25 | /**
26 | * Simple JavaBean domain object with an id property. Used as a base class for objects
27 | * needing this property.
28 | *
29 | * @author Ken Krebs
30 | * @author Juergen Hoeller
31 | */
32 | @MappedSuperclass
33 | public class BaseEntity implements Serializable {
34 |
35 | @Id
36 | @GeneratedValue(strategy = GenerationType.IDENTITY)
37 | private Integer id;
38 |
39 | public Integer getId() {
40 | return id;
41 | }
42 |
43 | public void setId(Integer id) {
44 | this.id = id;
45 | }
46 |
47 | public boolean isNew() {
48 | return this.id == null;
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.model;
17 |
18 | import javax.persistence.Column;
19 | import javax.persistence.MappedSuperclass;
20 |
21 | /**
22 | * Simple JavaBean domain object adds a name property to BaseEntity. Used as
23 | * a base class for objects needing these properties.
24 | *
25 | * @author Ken Krebs
26 | * @author Juergen Hoeller
27 | */
28 | @MappedSuperclass
29 | public class NamedEntity extends BaseEntity {
30 |
31 | @Column(name = "name")
32 | private String name;
33 |
34 | public String getName() {
35 | return this.name;
36 | }
37 |
38 | public void setName(String name) {
39 | this.name = name;
40 | }
41 |
42 | @Override
43 | public String toString() {
44 | return this.getName();
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/model/Person.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.model;
17 |
18 | import javax.persistence.Column;
19 | import javax.persistence.MappedSuperclass;
20 | import javax.validation.constraints.NotEmpty;
21 |
22 | /**
23 | * Simple JavaBean domain object representing an person.
24 | *
25 | * @author Ken Krebs
26 | */
27 | @MappedSuperclass
28 | public class Person extends BaseEntity {
29 |
30 | @Column(name = "first_name")
31 | @NotEmpty
32 | private String firstName;
33 |
34 | @Column(name = "last_name")
35 | @NotEmpty
36 | private String lastName;
37 |
38 | public String getFirstName() {
39 | return this.firstName;
40 | }
41 |
42 | public void setFirstName(String firstName) {
43 | this.firstName = firstName;
44 | }
45 |
46 | public String getLastName() {
47 | return this.lastName;
48 | }
49 |
50 | public void setLastName(String lastName) {
51 | this.lastName = lastName;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/model/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | /**
18 | * The classes in this package represent utilities used by the domain.
19 | */
20 | package org.springframework.samples.petclinic.model;
21 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/Owner.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import java.util.ArrayList;
19 | import java.util.Collections;
20 | import java.util.HashSet;
21 | import java.util.List;
22 | import java.util.Set;
23 |
24 | import javax.persistence.CascadeType;
25 | import javax.persistence.Column;
26 | import javax.persistence.Entity;
27 | import javax.persistence.OneToMany;
28 | import javax.persistence.Table;
29 | import javax.validation.constraints.Digits;
30 | import javax.validation.constraints.NotEmpty;
31 |
32 | import org.springframework.beans.support.MutableSortDefinition;
33 | import org.springframework.beans.support.PropertyComparator;
34 | import org.springframework.core.style.ToStringCreator;
35 | import org.springframework.samples.petclinic.model.Person;
36 |
37 | /**
38 | * Simple JavaBean domain object representing an owner.
39 | *
40 | * @author Ken Krebs
41 | * @author Juergen Hoeller
42 | * @author Sam Brannen
43 | * @author Michael Isvy
44 | */
45 | @Entity
46 | @Table(name = "owners")
47 | public class Owner extends Person {
48 |
49 | @Column(name = "address")
50 | @NotEmpty
51 | private String address;
52 |
53 | @Column(name = "city")
54 | @NotEmpty
55 | private String city;
56 |
57 | @Column(name = "telephone")
58 | @NotEmpty
59 | @Digits(fraction = 0, integer = 10)
60 | private String telephone;
61 |
62 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
63 | private Set pets;
64 |
65 | public String getAddress() {
66 | return this.address;
67 | }
68 |
69 | public void setAddress(String address) {
70 | this.address = address;
71 | }
72 |
73 | public String getCity() {
74 | return this.city;
75 | }
76 |
77 | public void setCity(String city) {
78 | this.city = city;
79 | }
80 |
81 | public String getTelephone() {
82 | return this.telephone;
83 | }
84 |
85 | public void setTelephone(String telephone) {
86 | this.telephone = telephone;
87 | }
88 |
89 | protected Set getPetsInternal() {
90 | if (this.pets == null) {
91 | this.pets = new HashSet<>();
92 | }
93 | return this.pets;
94 | }
95 |
96 | protected void setPetsInternal(Set pets) {
97 | this.pets = pets;
98 | }
99 |
100 | public List getPets() {
101 | List sortedPets = new ArrayList<>(getPetsInternal());
102 | PropertyComparator.sort(sortedPets, new MutableSortDefinition("name", true, true));
103 | return Collections.unmodifiableList(sortedPets);
104 | }
105 |
106 | public void addPet(Pet pet) {
107 | if (pet.isNew()) {
108 | getPetsInternal().add(pet);
109 | }
110 | pet.setOwner(this);
111 | }
112 |
113 | /**
114 | * Return the Pet with the given name, or null if none found for this Owner.
115 | * @param name to test
116 | * @return true if pet name is already in use
117 | */
118 | public Pet getPet(String name) {
119 | return getPet(name, false);
120 | }
121 |
122 | /**
123 | * Return the Pet with the given name, or null if none found for this Owner.
124 | * @param name to test
125 | * @return true if pet name is already in use
126 | */
127 | public Pet getPet(String name, boolean ignoreNew) {
128 | name = name.toLowerCase();
129 | for (Pet pet : getPetsInternal()) {
130 | if (!ignoreNew || !pet.isNew()) {
131 | String compName = pet.getName();
132 | compName = compName.toLowerCase();
133 | if (compName.equals(name)) {
134 | return pet;
135 | }
136 | }
137 | }
138 | return null;
139 | }
140 |
141 | @Override
142 | public String toString() {
143 | return new ToStringCreator(this)
144 |
145 | .append("id", this.getId()).append("new", this.isNew()).append("lastName", this.getLastName())
146 | .append("firstName", this.getFirstName()).append("address", this.address).append("city", this.city)
147 | .append("telephone", this.telephone).toString();
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/OwnerController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import org.springframework.samples.petclinic.visit.VisitRepository;
19 | import org.springframework.stereotype.Controller;
20 | import org.springframework.ui.Model;
21 | import org.springframework.validation.BindingResult;
22 | import org.springframework.web.bind.WebDataBinder;
23 | import org.springframework.web.bind.annotation.GetMapping;
24 | import org.springframework.web.bind.annotation.InitBinder;
25 | import org.springframework.web.bind.annotation.PathVariable;
26 | import org.springframework.web.bind.annotation.PostMapping;
27 | import org.springframework.web.servlet.ModelAndView;
28 |
29 | import javax.validation.Valid;
30 | import java.util.Collection;
31 | import java.util.Map;
32 |
33 | /**
34 | * @author Juergen Hoeller
35 | * @author Ken Krebs
36 | * @author Arjen Poutsma
37 | * @author Michael Isvy
38 | */
39 | @Controller
40 | class OwnerController {
41 |
42 | private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
43 |
44 | private final OwnerRepository owners;
45 |
46 | private VisitRepository visits;
47 |
48 | public OwnerController(OwnerRepository clinicService, VisitRepository visits) {
49 | this.owners = clinicService;
50 | this.visits = visits;
51 | }
52 |
53 | @InitBinder
54 | public void setAllowedFields(WebDataBinder dataBinder) {
55 | dataBinder.setDisallowedFields("id");
56 | }
57 |
58 | @GetMapping("/owners/new")
59 | public String initCreationForm(Map model) {
60 | Owner owner = new Owner();
61 | model.put("owner", owner);
62 | return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
63 | }
64 |
65 | @PostMapping("/owners/new")
66 | public String processCreationForm(@Valid Owner owner, BindingResult result) {
67 | if (result.hasErrors()) {
68 | return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
69 | }
70 | else {
71 | this.owners.save(owner);
72 | return "redirect:/owners/" + owner.getId();
73 | }
74 | }
75 |
76 | @GetMapping("/owners/find")
77 | public String initFindForm(Map model) {
78 | model.put("owner", new Owner());
79 | return "owners/findOwners";
80 | }
81 |
82 | @GetMapping("/owners")
83 | public String processFindForm(Owner owner, BindingResult result, Map model) {
84 |
85 | // allow parameterless GET request for /owners to return all records
86 | if (owner.getLastName() == null) {
87 | owner.setLastName(""); // empty string signifies broadest possible search
88 | }
89 |
90 | // find owners by last name
91 | Collection results = this.owners.findByLastName(owner.getLastName());
92 | if (results.isEmpty()) {
93 | // no owners found
94 | result.rejectValue("lastName", "notFound", "not found");
95 | return "owners/findOwners";
96 | }
97 | else if (results.size() == 1) {
98 | // 1 owner found
99 | owner = results.iterator().next();
100 | return "redirect:/owners/" + owner.getId();
101 | }
102 | else {
103 | // multiple owners found
104 | model.put("selections", results);
105 | return "owners/ownersList";
106 | }
107 | }
108 |
109 | @GetMapping("/owners/{ownerId}/edit")
110 | public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) {
111 | Owner owner = this.owners.findById(ownerId);
112 | model.addAttribute(owner);
113 | return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
114 | }
115 |
116 | @PostMapping("/owners/{ownerId}/edit")
117 | public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result,
118 | @PathVariable("ownerId") int ownerId) {
119 | if (result.hasErrors()) {
120 | return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
121 | }
122 | else {
123 | owner.setId(ownerId);
124 | this.owners.save(owner);
125 | return "redirect:/owners/{ownerId}";
126 | }
127 | }
128 |
129 | /**
130 | * Custom handler for displaying an owner.
131 | * @param ownerId the ID of the owner to display
132 | * @return a ModelMap with the model attributes for the view
133 | */
134 | @GetMapping("/owners/{ownerId}")
135 | public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) {
136 | ModelAndView mav = new ModelAndView("owners/ownerDetails");
137 | Owner owner = this.owners.findById(ownerId);
138 | for (Pet pet : owner.getPets()) {
139 | pet.setVisitsInternal(visits.findByPetId(pet.getId()));
140 | }
141 | mav.addObject(owner);
142 | return mav;
143 | }
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import java.util.Collection;
19 |
20 | import org.springframework.data.jpa.repository.Query;
21 | import org.springframework.data.repository.Repository;
22 | import org.springframework.data.repository.query.Param;
23 | import org.springframework.transaction.annotation.Transactional;
24 |
25 | /**
26 | * Repository class for Owner domain objects All method names are compliant
27 | * with Spring Data naming conventions so this interface can easily be extended for Spring
28 | * Data. See:
29 | * https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation
30 | *
31 | * @author Ken Krebs
32 | * @author Juergen Hoeller
33 | * @author Sam Brannen
34 | * @author Michael Isvy
35 | */
36 | public interface OwnerRepository extends Repository {
37 |
38 | /**
39 | * Retrieve {@link Owner}s from the data store by last name, returning all owners
40 | * whose last name starts with the given name.
41 | * @param lastName Value to search for
42 | * @return a Collection of matching {@link Owner}s (or an empty Collection if none
43 | * found)
44 | */
45 | @Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName%")
46 | @Transactional(readOnly = true)
47 | Collection findByLastName(@Param("lastName") String lastName);
48 |
49 | /**
50 | * Retrieve an {@link Owner} from the data store by id.
51 | * @param id the id to search for
52 | * @return the {@link Owner} if found
53 | */
54 | @Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id")
55 | @Transactional(readOnly = true)
56 | Owner findById(@Param("id") Integer id);
57 |
58 | /**
59 | * Save an {@link Owner} to the data store, either inserting or updating it.
60 | * @param owner the {@link Owner} to save
61 | */
62 | void save(Owner owner);
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/Pet.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import java.time.LocalDate;
19 | import java.util.ArrayList;
20 | import java.util.Collection;
21 | import java.util.Collections;
22 | import java.util.HashSet;
23 | import java.util.LinkedHashSet;
24 | import java.util.List;
25 | import java.util.Set;
26 |
27 | import javax.persistence.Column;
28 | import javax.persistence.Entity;
29 | import javax.persistence.JoinColumn;
30 | import javax.persistence.ManyToOne;
31 | import javax.persistence.Table;
32 | import javax.persistence.Transient;
33 |
34 | import org.springframework.beans.support.MutableSortDefinition;
35 | import org.springframework.beans.support.PropertyComparator;
36 | import org.springframework.format.annotation.DateTimeFormat;
37 | import org.springframework.samples.petclinic.model.NamedEntity;
38 | import org.springframework.samples.petclinic.visit.Visit;
39 |
40 | /**
41 | * Simple business object representing a pet.
42 | *
43 | * @author Ken Krebs
44 | * @author Juergen Hoeller
45 | * @author Sam Brannen
46 | */
47 | @Entity
48 | @Table(name = "pets")
49 | public class Pet extends NamedEntity {
50 |
51 | @Column(name = "birth_date")
52 | @DateTimeFormat(pattern = "yyyy-MM-dd")
53 | private LocalDate birthDate;
54 |
55 | @ManyToOne
56 | @JoinColumn(name = "type_id")
57 | private PetType type;
58 |
59 | @ManyToOne
60 | @JoinColumn(name = "owner_id")
61 | private Owner owner;
62 |
63 | @Transient
64 | private Set visits = new LinkedHashSet<>();
65 |
66 | public void setBirthDate(LocalDate birthDate) {
67 | this.birthDate = birthDate;
68 | }
69 |
70 | public LocalDate getBirthDate() {
71 | return this.birthDate;
72 | }
73 |
74 | public PetType getType() {
75 | return this.type;
76 | }
77 |
78 | public void setType(PetType type) {
79 | this.type = type;
80 | }
81 |
82 | public Owner getOwner() {
83 | return this.owner;
84 | }
85 |
86 | protected void setOwner(Owner owner) {
87 | this.owner = owner;
88 | }
89 |
90 | protected Set getVisitsInternal() {
91 | if (this.visits == null) {
92 | this.visits = new HashSet<>();
93 | }
94 | return this.visits;
95 | }
96 |
97 | protected void setVisitsInternal(Collection visits) {
98 | this.visits = new LinkedHashSet<>(visits);
99 | }
100 |
101 | public List getVisits() {
102 | List sortedVisits = new ArrayList<>(getVisitsInternal());
103 | PropertyComparator.sort(sortedVisits, new MutableSortDefinition("date", false, false));
104 | return Collections.unmodifiableList(sortedVisits);
105 | }
106 |
107 | public void addVisit(Visit visit) {
108 | getVisitsInternal().add(visit);
109 | visit.setPetId(this.getId());
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/PetController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import org.springframework.stereotype.Controller;
19 | import org.springframework.ui.ModelMap;
20 | import org.springframework.util.StringUtils;
21 | import org.springframework.validation.BindingResult;
22 | import org.springframework.web.bind.WebDataBinder;
23 | import org.springframework.web.bind.annotation.*;
24 |
25 | import javax.validation.Valid;
26 | import java.util.Collection;
27 |
28 | /**
29 | * @author Juergen Hoeller
30 | * @author Ken Krebs
31 | * @author Arjen Poutsma
32 | */
33 | @Controller
34 | @RequestMapping("/owners/{ownerId}")
35 | class PetController {
36 |
37 | private static final String VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm";
38 |
39 | private final PetRepository pets;
40 |
41 | private final OwnerRepository owners;
42 |
43 | public PetController(PetRepository pets, OwnerRepository owners) {
44 | this.pets = pets;
45 | this.owners = owners;
46 | }
47 |
48 | @ModelAttribute("types")
49 | public Collection populatePetTypes() {
50 | return this.pets.findPetTypes();
51 | }
52 |
53 | @ModelAttribute("owner")
54 | public Owner findOwner(@PathVariable("ownerId") int ownerId) {
55 | return this.owners.findById(ownerId);
56 | }
57 |
58 | @InitBinder("owner")
59 | public void initOwnerBinder(WebDataBinder dataBinder) {
60 | dataBinder.setDisallowedFields("id");
61 | }
62 |
63 | @InitBinder("pet")
64 | public void initPetBinder(WebDataBinder dataBinder) {
65 | dataBinder.setValidator(new PetValidator());
66 | }
67 |
68 | @GetMapping("/pets/new")
69 | public String initCreationForm(Owner owner, ModelMap model) {
70 | Pet pet = new Pet();
71 | owner.addPet(pet);
72 | model.put("pet", pet);
73 | return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
74 | }
75 |
76 | @PostMapping("/pets/new")
77 | public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult result, ModelMap model) {
78 | if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null) {
79 | result.rejectValue("name", "duplicate", "already exists");
80 | }
81 | owner.addPet(pet);
82 | if (result.hasErrors()) {
83 | model.put("pet", pet);
84 | return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
85 | }
86 | else {
87 | this.pets.save(pet);
88 | return "redirect:/owners/{ownerId}";
89 | }
90 | }
91 |
92 | @GetMapping("/pets/{petId}/edit")
93 | public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) {
94 | Pet pet = this.pets.findById(petId);
95 | model.put("pet", pet);
96 | return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
97 | }
98 |
99 | @PostMapping("/pets/{petId}/edit")
100 | public String processUpdateForm(@Valid Pet pet, BindingResult result, Owner owner, ModelMap model) {
101 | if (result.hasErrors()) {
102 | pet.setOwner(owner);
103 | model.put("pet", pet);
104 | return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
105 | }
106 | else {
107 | owner.addPet(pet);
108 | this.pets.save(pet);
109 | return "redirect:/owners/{ownerId}";
110 | }
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/PetRepository.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import java.util.List;
19 |
20 | import org.springframework.data.jpa.repository.Query;
21 | import org.springframework.data.repository.Repository;
22 | import org.springframework.transaction.annotation.Transactional;
23 |
24 | /**
25 | * Repository class for Pet domain objects All method names are compliant
26 | * with Spring Data naming conventions so this interface can easily be extended for Spring
27 | * Data. See:
28 | * https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation
29 | *
30 | * @author Ken Krebs
31 | * @author Juergen Hoeller
32 | * @author Sam Brannen
33 | * @author Michael Isvy
34 | */
35 | public interface PetRepository extends Repository {
36 |
37 | /**
38 | * Retrieve all {@link PetType}s from the data store.
39 | * @return a Collection of {@link PetType}s.
40 | */
41 | @Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name")
42 | @Transactional(readOnly = true)
43 | List findPetTypes();
44 |
45 | /**
46 | * Retrieve a {@link Pet} from the data store by id.
47 | * @param id the id to search for
48 | * @return the {@link Pet} if found
49 | */
50 | @Transactional(readOnly = true)
51 | Pet findById(Integer id);
52 |
53 | /**
54 | * Save a {@link Pet} to the data store, either inserting or updating it.
55 | * @param pet the {@link Pet} to save
56 | */
57 | void save(Pet pet);
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/PetType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import javax.persistence.Entity;
19 | import javax.persistence.Table;
20 |
21 | import org.springframework.samples.petclinic.model.NamedEntity;
22 |
23 | /**
24 | * @author Juergen Hoeller Can be Cat, Dog, Hamster...
25 | */
26 | @Entity
27 | @Table(name = "types")
28 | public class PetType extends NamedEntity {
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/PetTypeFormatter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import java.text.ParseException;
19 | import java.util.Collection;
20 | import java.util.Locale;
21 |
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.format.Formatter;
24 | import org.springframework.stereotype.Component;
25 |
26 | /**
27 | * Instructs Spring MVC on how to parse and print elements of type 'PetType'. Starting
28 | * from Spring 3.0, Formatters have come as an improvement in comparison to legacy
29 | * PropertyEditors. See the following links for more details: - The Spring ref doc:
30 | * https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#format
31 | *
32 | * @author Mark Fisher
33 | * @author Juergen Hoeller
34 | * @author Michael Isvy
35 | */
36 | @Component
37 | public class PetTypeFormatter implements Formatter {
38 |
39 | private final PetRepository pets;
40 |
41 | @Autowired
42 | public PetTypeFormatter(PetRepository pets) {
43 | this.pets = pets;
44 | }
45 |
46 | @Override
47 | public String print(PetType petType, Locale locale) {
48 | return petType.getName();
49 | }
50 |
51 | @Override
52 | public PetType parse(String text, Locale locale) throws ParseException {
53 | Collection findPetTypes = this.pets.findPetTypes();
54 | for (PetType type : findPetTypes) {
55 | if (type.getName().equals(text)) {
56 | return type;
57 | }
58 | }
59 | throw new ParseException("type not found: " + text, 0);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/PetValidator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import org.springframework.util.StringUtils;
19 | import org.springframework.validation.Errors;
20 | import org.springframework.validation.Validator;
21 |
22 | /**
23 | * Validator for Pet forms.
24 | *
25 | * We're not using Bean Validation annotations here because it is easier to define such
26 | * validation rule in Java.
27 | *
28 | *
29 | * @author Ken Krebs
30 | * @author Juergen Hoeller
31 | */
32 | public class PetValidator implements Validator {
33 |
34 | private static final String REQUIRED = "required";
35 |
36 | @Override
37 | public void validate(Object obj, Errors errors) {
38 | Pet pet = (Pet) obj;
39 | String name = pet.getName();
40 | // name validation
41 | if (!StringUtils.hasLength(name)) {
42 | errors.rejectValue("name", REQUIRED, REQUIRED);
43 | }
44 |
45 | // type validation
46 | if (pet.isNew() && pet.getType() == null) {
47 | errors.rejectValue("type", REQUIRED, REQUIRED);
48 | }
49 |
50 | // birth date validation
51 | if (pet.getBirthDate() == null) {
52 | errors.rejectValue("birthDate", REQUIRED, REQUIRED);
53 | }
54 | }
55 |
56 | /**
57 | * This Validator validates *just* Pet instances
58 | */
59 | @Override
60 | public boolean supports(Class> clazz) {
61 | return Pet.class.isAssignableFrom(clazz);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/owner/VisitController.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package org.springframework.samples.petclinic.owner;
17 |
18 | import java.util.Map;
19 |
20 | import javax.validation.Valid;
21 |
22 | import org.springframework.samples.petclinic.visit.Visit;
23 | import org.springframework.samples.petclinic.visit.VisitRepository;
24 | import org.springframework.stereotype.Controller;
25 | import org.springframework.validation.BindingResult;
26 | import org.springframework.web.bind.WebDataBinder;
27 | import org.springframework.web.bind.annotation.GetMapping;
28 | import org.springframework.web.bind.annotation.InitBinder;
29 | import org.springframework.web.bind.annotation.ModelAttribute;
30 | import org.springframework.web.bind.annotation.PathVariable;
31 | import org.springframework.web.bind.annotation.PostMapping;
32 |
33 | /**
34 | * @author Juergen Hoeller
35 | * @author Ken Krebs
36 | * @author Arjen Poutsma
37 | * @author Michael Isvy
38 | * @author Dave Syer
39 | */
40 | @Controller
41 | class VisitController {
42 |
43 | private final VisitRepository visits;
44 |
45 | private final PetRepository pets;
46 |
47 | public VisitController(VisitRepository visits, PetRepository pets) {
48 | this.visits = visits;
49 | this.pets = pets;
50 | }
51 |
52 | @InitBinder
53 | public void setAllowedFields(WebDataBinder dataBinder) {
54 | dataBinder.setDisallowedFields("id");
55 | }
56 |
57 | /**
58 | * Called before each and every @RequestMapping annotated method. 2 goals: - Make sure
59 | * we always have fresh data - Since we do not use the session scope, make sure that
60 | * Pet object always has an id (Even though id is not part of the form fields)
61 | * @param petId
62 | * @return Pet
63 | */
64 | @ModelAttribute("visit")
65 | public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map model) {
66 | Pet pet = this.pets.findById(petId);
67 | pet.setVisitsInternal(this.visits.findByPetId(petId));
68 | model.put("pet", pet);
69 | Visit visit = new Visit();
70 | pet.addVisit(visit);
71 | return visit;
72 | }
73 |
74 | // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called
75 | @GetMapping("/owners/*/pets/{petId}/visits/new")
76 | public String initNewVisitForm(@PathVariable("petId") int petId, Map model) {
77 | return "pets/createOrUpdateVisitForm";
78 | }
79 |
80 | // Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called
81 | @PostMapping("/owners/{ownerId}/pets/{petId}/visits/new")
82 | public String processNewVisitForm(@Valid Visit visit, BindingResult result) {
83 | if (result.hasErrors()) {
84 | return "pets/createOrUpdateVisitForm";
85 | }
86 | else {
87 | this.visits.save(visit);
88 | return "redirect:/owners/{ownerId}";
89 | }
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/petclinic/src/main/java/org/springframework/samples/petclinic/system/CacheConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.samples.petclinic.system;
18 |
19 | import javax.cache.configuration.MutableConfiguration;
20 |
21 | import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
22 | import org.springframework.cache.annotation.EnableCaching;
23 | import org.springframework.context.annotation.Bean;
24 | import org.springframework.context.annotation.Configuration;
25 |
26 | /**
27 | * Cache configuration intended for caches providing the JCache API. This configuration
28 | * creates the used cache for the application and enables statistics that become
29 | * accessible via JMX.
30 | */
31 | @Configuration(proxyBeanMethods = false)
32 | @EnableCaching
33 | class CacheConfiguration {
34 |
35 | @Bean
36 | public JCacheManagerCustomizer petclinicCacheConfigurationCustomizer() {
37 | return cm -> {
38 | cm.createCache("vets", cacheConfiguration());
39 | };
40 | }
41 |
42 | /**
43 | * Create a simple configuration that enable statistics via the JCache programmatic
44 | * configuration API.
45 | *
46 | * Within the configuration object that is provided by the JCache API standard, there
47 | * is only a very limited set of configuration options. The really relevant
48 | * configuration options (like the size limit) must be set via a configuration
49 | * mechanism that is provided by the selected JCache implementation.
50 | */
51 | private javax.cache.configuration.Configuration