├── .github └── workflows │ └── ci.yml ├── .gitignore ├── README.md ├── THIRDPARTY ├── buildspec.yml ├── docs ├── architecture.md ├── assets │ └── images │ │ ├── aws-favicon.ico │ │ ├── aws_smile_logo.png │ │ └── second-nav-blue.png ├── cleanup.md ├── contribute.md ├── deploy.md ├── images │ ├── Architecture.png │ ├── Cloud9.png │ ├── Fargate.png │ ├── c9attachrole.png │ ├── c9disableiam.png │ ├── c9instancerole.png │ └── createrole.png ├── index.md ├── infrastructure.md ├── license.md ├── pipeline.md ├── prerequisites.md └── stylesheets │ └── custom.css ├── images ├── Architecture.png ├── Cloud9.png ├── c9attachrole.png ├── c9disableiam.png ├── c9instancerole.png └── createrole.png ├── mkdocs.yml ├── 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 ├── requirements.txt ├── site ├── 404.html ├── architecture │ └── index.html ├── assets │ ├── images │ │ └── favicon.png │ ├── javascripts │ │ ├── bundle.6627ddf3.min.js │ │ ├── bundle.6627ddf3.min.js.map │ │ ├── lunr │ │ │ ├── min │ │ │ │ ├── lunr.ar.min.js │ │ │ │ ├── lunr.da.min.js │ │ │ │ ├── lunr.de.min.js │ │ │ │ ├── lunr.du.min.js │ │ │ │ ├── lunr.es.min.js │ │ │ │ ├── lunr.fi.min.js │ │ │ │ ├── lunr.fr.min.js │ │ │ │ ├── lunr.hu.min.js │ │ │ │ ├── lunr.it.min.js │ │ │ │ ├── lunr.ja.min.js │ │ │ │ ├── lunr.jp.min.js │ │ │ │ ├── lunr.multi.min.js │ │ │ │ ├── lunr.nl.min.js │ │ │ │ ├── lunr.no.min.js │ │ │ │ ├── lunr.pt.min.js │ │ │ │ ├── lunr.ro.min.js │ │ │ │ ├── lunr.ru.min.js │ │ │ │ ├── lunr.stemmer.support.min.js │ │ │ │ ├── lunr.sv.min.js │ │ │ │ ├── lunr.tr.min.js │ │ │ │ └── lunr.vi.min.js │ │ │ └── tinyseg.min.js │ │ ├── vendor.2d1db4bd.min.js │ │ ├── vendor.2d1db4bd.min.js.map │ │ └── worker │ │ │ ├── search.5eca75d3.min.js │ │ │ └── search.5eca75d3.min.js.map │ └── stylesheets │ │ ├── main.d3202873.min.css │ │ ├── main.d3202873.min.css.map │ │ ├── palette.ff0a5ce4.min.css │ │ └── palette.ff0a5ce4.min.css.map ├── cleanup │ └── index.html ├── deploy │ └── index.html ├── images │ ├── Architecture.png │ ├── Cloud9.png │ ├── Fargate.png │ ├── c9attachrole.png │ ├── c9disableiam.png │ ├── c9instancerole.png │ └── createrole.png ├── index.html ├── infrastructure │ └── index.html ├── pipeline │ └── index.html ├── prerequisites │ └── index.html ├── search │ └── search_index.json ├── sitemap.xml └── sitemap.xml.gz └── terraform ├── alb.tf ├── codebuild.tf ├── codecommit.tf ├── codepipeline.tf ├── ecr.tf ├── ecs-fargate.tf ├── getssmParameters.sh ├── iam-fargate.tf ├── parameters.tf ├── provider.tf ├── rds.tf ├── security-groups.tf ├── terraform.tfvars ├── variables.tf └── vpc.tf /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [master] 4 | pull_request: 5 | branches: [master] 6 | 7 | jobs: 8 | build: 9 | name: Build and Deploy Documentation 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout Master 13 | uses: actions/checkout@v2 14 | 15 | - name: Set up Python 3.7 16 | uses: actions/setup-python@v2 17 | with: 18 | python-version: '3.x' 19 | 20 | - name: Install dependencies 21 | run: | 22 | python -m pip install --upgrade pip 23 | pip install mkdocs-material 24 | 25 | - name: Deploy 26 | run: | 27 | git pull 28 | mkdocs gh-deploy -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | terraform/.terraform 2 | terraform/.terraform.lock.hcl 3 | terraform.tfstate 4 | terraform.tfstate.backup 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /buildspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.2 2 | 3 | phases: 4 | install: 5 | runtime-versions: 6 | python: 3.7 7 | build: 8 | commands: 9 | - pip3 install -r requirements.txt 10 | - mkdocs build 11 | - aws s3 sync --acl public-read site/ s3://workshop.reinforce.awsdemo.me/ 12 | -------------------------------------------------------------------------------- /docs/architecture.md: -------------------------------------------------------------------------------- 1 | # Architecture 2 | Time Estimate: 15 - 20 minutes 3 | 4 | ![Architecture](./images/Architecture.png) 5 | 6 | ??? info "What is AWS Fargate?" 7 | AWS Fargate is a serverless compute engine for containers that works with both Amazon Elastic Container Service (ECS) and Amazon Elastic Kubernetes Service (EKS). Fargate makes it easy for you to focus on building your applications. Fargate removes the need to provision and manage servers, lets you specify and pay for resources per application, and improves security through application isolation by design. 8 | With Fargate, you can focus on building and operating your applications whether you are running it with ECS or EKS. You only interact with and pay for your containers, and you avoid the operational overhead of scaling, patching, securing, and managing servers. Fargate ensures that the infrastructure your containers run on is always up-to-date with the required patches. 9 | ![Fargate](./images/Fargate.png) 10 | 11 | With Fargate, you get out-of-box observability through built-in integrations with other AWS services including Amazon CloudWatch Container Insights. Fargate allows you to gather metrics and logs for monitoring your applications through an extensive selection of third party tools with open interfaces. 12 | 13 | 14 | ??? info "What is Terraform?" 15 | Terraform is a tool for building, changing, and versioning infrastructure safely and efficiently. Terraform can manage existing and popular service providers as well as custom in-house solutions. 16 | 17 | Configuration files describe to Terraform the components needed to run a single application or your entire datacenter. Terraform generates an execution plan describing what it will do to reach the desired state, and then executes it to build the described infrastructure. As the configuration changes, Terraform is able to determine what changed and create incremental execution plans which can be applied. 18 | 19 | The infrastructure Terraform can manage includes low-level components such as compute instances, storage, and networking, as well as high-level components such as DNS entries, SaaS features, etc. 20 | 21 | -------------------------------------------------------------------------------- /docs/assets/images/aws-favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/assets/images/aws-favicon.ico -------------------------------------------------------------------------------- /docs/assets/images/aws_smile_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/assets/images/aws_smile_logo.png -------------------------------------------------------------------------------- /docs/assets/images/second-nav-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/assets/images/second-nav-blue.png -------------------------------------------------------------------------------- /docs/cleanup.md: -------------------------------------------------------------------------------- 1 | # Tearing down the stack 2 | 3 | When finished, you can free up resources as follows: 4 | 5 | ``` 6 | cd ../terraform 7 | terraform destroy 8 | ``` 9 | 10 | When prompted enter `yes` to allow the stack termination to proceed. 11 | 12 | Once complete, note that you will have to manually empty and delete the S3 bucket used by the pipeline. -------------------------------------------------------------------------------- /docs/contribute.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/aws-samples/aws-ecs-cicd-terraform/issues), or [recently closed](https://github.com/aws-samples/aws-ecs-cicd-terraform/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/aws-ecs-cicd-terraform/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/aaws-samples/aws-ecs-cicd-terraform/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /docs/deploy.md: -------------------------------------------------------------------------------- 1 | # Deploy petclinic application using the pipeline 2 | Time Estimate: 15 - 20 minutes 3 | 4 | ??? info "What is AWS CodePipeline?" 5 | AWS CodePipeline is a fully managed continuous delivery service that helps you automate your release pipelines for fast and reliable application and infrastructure updates. CodePipeline automates the build, test, and deploy phases of your release process every time there is a code change, based on the release model you define. This enables you to rapidly and reliably deliver features and updates. You can easily integrate AWS CodePipeline with third-party services such as GitHub or with your own custom plugin. With AWS CodePipeline, you only pay for what you use. There are no upfront fees or long-term commitments. 6 | 7 | You will now use git to push the petclinic application through the pipeline. 8 | 9 | 10 | ### Set up a local git repo for the petclinic application 11 | 12 | Start by switching to the `petclinic` directory: 13 | 14 | ```bash 15 | cd ../petclinic 16 | ``` 17 | 18 | Set up your git username and email address: 19 | 20 | ```bash 21 | git config --global user.name "Your Name" 22 | git config --global user.email you@example.com 23 | ``` 24 | 25 | Now ceate a local git repo for petclinic as follows: 26 | 27 | ```bash 28 | git init 29 | git add . 30 | git commit -m "Baseline commit" 31 | ``` 32 | 33 | ### Set up the remote CodeCommit repo 34 | 35 | An AWS CodeCommit repo was built as part of the pipeline you created. You will now set this up as a remote repo for your local petclinic repo. 36 | 37 | For authentication purposes, you can use the AWS IAM git credential helper to generate git credentials based on your IAM role permissions. Run: 38 | 39 | ```bash 40 | git config --global credential.helper '!aws codecommit credential-helper $@' 41 | git config --global credential.UseHttpPath true 42 | ``` 43 | 44 | From the output of the Terraform build, note the Terraform output `source_repo_clone_url_http`. 45 | 46 | ```bash 47 | cd ../terraform 48 | export tf_source_repo_clone_url_http=$(terraform output source_repo_clone_url_http) 49 | ``` 50 | 51 | Set this up as a remote for your git repo as follows: 52 | 53 | ```bash 54 | cd ../petclinic 55 | git remote add origin $tf_source_repo_clone_url_http 56 | git remote -v 57 | ``` 58 | 59 | You should see something like: 60 | 61 | ```bash 62 | origin https://git-codecommit.eu-west-2.amazonaws.com/v1/repos/petclinic (fetch) 63 | origin https://git-codecommit.eu-west-2.amazonaws.com/v1/repos/petclinic (push) 64 | ``` 65 | -------------------------------------------------------------------------------- /docs/images/Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/images/Architecture.png -------------------------------------------------------------------------------- /docs/images/Cloud9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/images/Cloud9.png -------------------------------------------------------------------------------- /docs/images/Fargate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/images/Fargate.png -------------------------------------------------------------------------------- /docs/images/c9attachrole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/images/c9attachrole.png -------------------------------------------------------------------------------- /docs/images/c9disableiam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/images/c9disableiam.png -------------------------------------------------------------------------------- /docs/images/c9instancerole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/images/c9instancerole.png -------------------------------------------------------------------------------- /docs/images/createrole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/docs/images/createrole.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Workshop - Build and Deploy Spring Petclinic Application to Amazon ECS using Terraform and AWS CodePipeline 2 | 3 | ### Introduction 4 | 5 | This workshop is designed to enable Solutions Architects and engineers to get some hands-on experience using Terraform with AWS Continuous Ingration and Continuous Devlivery tools and services. The workshop consists of a sequence of steps to build a pipeline for an Amazon ECS workload using the Java PetClinic sample application. The pipeline itself uses AWS CodePipeline, AWS CodeCommit, AWS CodeBuild, Amazon ECS/Fargate and Amazon ECR. 6 | 7 | 8 | ### Background 9 | 10 | The Spring PetClinic sample application is designed to show how the Spring application framework can be used to build simple, but powerful database-oriented applications. It uses AWS RDS (MySQL) at the backend and it will demonstrate the use of Spring's core functionality. The Spring Framework is a collection of small, well-focused, loosely coupled Java frameworks that can be used independently or collectively to build industrial strength applications of many different types. 11 | 12 | ### Contributors 13 | 14 | - Irshad A Buchh, Amazon Web Services 15 | - Mike Rizzo, Amazon Web Services 16 | -------------------------------------------------------------------------------- /docs/infrastructure.md: -------------------------------------------------------------------------------- 1 | # Build the infrastructure and pipeline 2 | Time Estimate: 10 - 15 minutes 3 | 4 | We shall use Terraform to build the above architecture including the AWS CodePipeline. 5 | 6 | ### Set up SSM parameter for DB passwd 7 | 8 | ```bash 9 | aws ssm put-parameter --name /database/password --value mysqlpassword --type SecureString 10 | ``` 11 | 12 | ### Edit terraform variables 13 | 14 | ```bash 15 | cd terraform 16 | ``` 17 | 18 | Edit `terraform.tfvars`, leave the `aws_profile` as `"default"`, and set `aws_region` to the correct value for your environment. 19 | 20 | ### Build 21 | 22 | Initialise Terraform: 23 | 24 | ```bash 25 | terraform init 26 | ``` 27 | 28 | Build the infrastructure and pipeline using terraform: 29 | 30 | ```bash 31 | terraform apply 32 | ``` 33 | 34 | Terraform will display an action plan. When asked whether you want to proceed with the actions, enter `yes`. 35 | 36 | Wait for Terraform to complete the build before proceeding. It will take few minutes to complete “terraform apply” 37 | 38 | ### Explore the stack you have built 39 | 40 | Once the build is complete, you can explore your environment using the AWS console: 41 | - View the RDS database using the [Amazon RDS console](https://console.aws.amazon.com/rds). 42 | 43 | - View the ALB using the [Amazon EC2 console](https://console.aws.amazon.com/ec2). 44 | 45 | - View the ECS cluster using the [Amazon ECS console](https://console.aws.amazon.com/ecs). 46 | 47 | - View the ECR repo using the [Amazon ECR console](https://console.aws.amazon.com/ecr). 48 | 49 | - View the CodeCommit repo using the [AWS CodeCommit console](https://console.aws.amazon.com/codecommit). 50 | 51 | - View the CodeBuild project using the [AWS CodeBuild console](https://console.aws.amazon.com/codebuild). 52 | 53 | - View the pipeline using the [AWS CodePipeline console](https://console.aws.amazon.com/codepipeline). 54 | 55 | 56 | Note that your pipeline starts in a failed state. That is because there is no code to build in the CodeCommit repo! In the next step you will push the petclinic app into the repo to trigger the pipeline. 57 | 58 | -------------------------------------------------------------------------------- /docs/license.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | **MIT License** 4 | 5 | Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | software and associated documentation files (the "Software"), to deal in the Software 9 | without restriction, including without limitation the rights to use, copy, modify, 10 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 14 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 15 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 16 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 17 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 18 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /docs/pipeline.md: -------------------------------------------------------------------------------- 1 | # Trigger the pipeline 2 | Time Estimate: 15 - 20 minutes 3 | 4 | To trigger the pipeline, push the master branch to the remote as follows: 5 | 6 | ```bash 7 | git push -u origin master 8 | ``` 9 | 10 | The pipeline will pull the code, build the docker image, push it to ECR, and deploy it to your ECS cluster. This will take a few minutes. 11 | You can monitor the pipeline in the [AWS CodePipeline console](https://console.aws.amazon.com/codepipeline). 12 | 13 | 14 | ### Test the application 15 | 16 | From the output of the Terraform build, note the Terraform output `alb_address`. 17 | 18 | ```bash 19 | cd ../terraform 20 | export tf_alb_address=$(terraform output alb_address) 21 | echo $tf_alb_address 22 | ``` 23 | 24 | Use this in your browser to access the application. 25 | 26 | 27 | ## Push a change through the pipeline and re-test 28 | 29 | The pipeline can now be used to deploy any changes to the application. 30 | 31 | You can try this out by changing the welcome message as follows: 32 | 33 | ``` 34 | cd ../petclinic 35 | vi src/main/resources/messages/messages.properties 36 | ``` 37 | Change the value for the welcome string, for example, to "Hello". 38 | 39 | Commit the change: 40 | 41 | ``` 42 | git add . 43 | git commit -m "Changed welcome string" 44 | ``` 45 | 46 | Push the change to trigger pipeline: 47 | 48 | ```bash 49 | git push origin master 50 | ``` 51 | 52 | As before, you can use the console to observe the progression of the change through the pipeline. Once done, verify that the application is working with the modified welcome message. 53 | -------------------------------------------------------------------------------- /docs/prerequisites.md: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | 3 | Before you build the whole infrastructure, including your CI/CD pipeline, you will need to meet the following pre-requisites. 4 | 5 | ### AWS account 6 | 7 | Ensure you have access to an AWS account, and a set of credentials with Administrator permissions. Note: In a production environment we would recommend locking permissions down to the bare minimum needed to operate the pipeline. 8 | 9 | ### Create an AWS Cloud9 environment 10 | 11 | ??? info "What is AWS Cloud9?" 12 | AWS Cloud9 is a cloud-based integrated development environment (IDE) that lets you write, run, and debug your code with just a browser. It includes a code editor, debugger, and terminal. Cloud9 comes prepackaged with essential tools for popular programming languages, including JavaScript, Python, PHP, and more, so you don’t need to install files or configure your development machine to start new projects. Since your Cloud9 IDE is cloud-based, you can work on your projects from your office, home, or anywhere using an internet-connected machine. Cloud9 also provides a seamless experience for developing serverless applications enabling you to easily define resources, debug, and switch between local and remote execution of serverless applications. With Cloud9, you can quickly share your development environment with your team, enabling you to pair program and track each other's inputs in real time. 13 | Log into the AWS Management Console and search for Cloud9 services in the search bar. Click Cloud9 and create an AWS Cloud9 environment in the us-east-1 region based on Amazon Linux 2. 14 | 15 | ### Configure the AWS Cloud9 environment 16 | 17 | Launch the AWS Cloud9 IDE. Close the Welcome tab and open a new Terminal tab. 18 | 19 | ![Cloud9](./images/Cloud9.png) 20 | 21 | #### Create and attach an IAM role for your Cloud9 instance 22 | 23 | By default, Cloud9 manages temporary IAM credentials for you. Unfortunately these are incomaptible with Terraform. To get around this you need to disable Cloud9 temporary credentials, and create and attach an IAM role for your Cloud9 instance. 24 | 25 | 1. Follow [this deep link to create an IAM role with Administrator access.](https://console.aws.amazon.com/iam/home#/roles$new?step=review&commonUseCase=EC2%2BEC2&selectedUseCase=EC2&policies=arn:aws:iam::aws:policy%2FAdministratorAccess) 26 | 1. Confirm that **AWS service** and **EC2** are selected, then click **Next** to view permissions. 27 | 1. Confirm that **AdministratorAccess** is checked, then click **Next: Tags** to assign tags. 28 | 1. Take the defaults, and click **Next: Review** to review. 29 | 1. Enter **workshop-admin** for the Name, and click **Create role**. 30 | ![createrole](./images/createrole.png) 31 | 1. Follow [this deep link to find your Cloud9 EC2 instance](https://console.aws.amazon.com/ec2/v2/home?#Instances:tag:Name=aws-cloud9-;sort=desc:launchTime) 32 | 1. Select the instance, then choose **Actions / Instance Settings / Modify IAM Role**. Note: If you cannot find this menu option, then look under **Actions / Security / Modify IAM Role** instead. 33 | ![c9instancerole](./images/c9instancerole.png) 34 | 1. Choose **workshop-admin** from the **IAM Role** drop down, and select **Apply** 35 | ![c9attachrole](./images/c9attachrole.png) 36 | 1. Return to your workspace and click the gear icon (in top right corner), or click to open a new tab and choose "Open Preferences" 37 | 1. Select **AWS SETTINGS** 38 | 1. Turn off **AWS managed temporary credentials** 39 | 1. Close the Preferences tab 40 | ![c9disableiam](./images/c9disableiam.png) 41 | 1. In the Cloud9 terminal pane, execute the command: 42 | ```bash 43 | rm -vf ${HOME}/.aws/credentials 44 | ``` 45 | 1. As a final check, use the [GetCallerIdentity](https://docs.aws.amazon.com/cli/latest/reference/sts/get-caller-identity.html) CLI command to validate that the Cloud9 IDE is using the correct IAM role. 46 | ```bash 47 | aws sts get-caller-identity --query Arn | grep workshop-admin -q && echo "IAM role valid" || echo "IAM role NOT valid" 48 | ``` 49 | 50 | #### Upgrade awscli 51 | Ensure you are running the latest version of AWS CLI: 52 | 53 | ```bash 54 | aws --version 55 | pip install awscli --upgrade --user 56 | ``` 57 | 58 | Run `aws configure` to configure your region. Leave all the other fields blank. You should have something like: 59 | 60 | ``` 61 | admin:~/environment $ aws configure 62 | AWS Access Key ID [None]: 63 | AWS Secret Access Key [None]: 64 | Default region name [None]: us-east-1 65 | Default output format [None]: 66 | ``` 67 | 68 | 69 | #### Install Terraform 70 | 71 | Download and install Terraform: 72 | 73 | ```bash 74 | wget https://releases.hashicorp.com/terraform/0.13.4/terraform_0.13.4_linux_amd64.zip 75 | unzip terraform_0.13.4_linux_amd64.zip 76 | sudo mv terraform /usr/local/bin/ 77 | export PATH=$PATH:/usr/local/bin/terraform 78 | ``` 79 | 80 | Verify that you can run Terraform: 81 | 82 | ```bash 83 | terraform version 84 | ``` 85 | 86 | 91 | 92 | 93 | #### Install workshop files 94 | 95 | You will need to import the workshop files into your Cloud9 environment: 96 | 97 | ```bash 98 | wget https://github.com/aws-samples/aws-ecs-cicd-terraform/archive/master.zip 99 | unzip master.zip 100 | cd aws-ecs-cicd-terraform-master 101 | ``` 102 | 103 | -------------------------------------------------------------------------------- /docs/stylesheets/custom.css: -------------------------------------------------------------------------------- 1 | 2 | .md-header { 3 | background-color: #232f3e !important; 4 | border-bottom: 1px solid #1b2532 !important; 5 | } 6 | 7 | @media only screen and (max-width: 76.1875em) { 8 | 9 | html .md-nav--primary .md-nav__title--site { 10 | background-color: #232f3e !important; 11 | border-bottom: 1px solid #1b2532 !important; 12 | } 13 | 14 | .md-nav__source { 15 | background-color: #1f4e79 !important; 16 | } 17 | 18 | html .md-nav--primary .md-nav__title { 19 | background-color: #232f3e !important; 20 | border-bottom: 1px solid #1b2532 !important; 21 | color: #ffffff; 22 | } 23 | 24 | html .md-nav--primary .md-nav__title::before { 25 | color: #ffffff; 26 | } 27 | 28 | } 29 | 30 | .md-tabs__link { 31 | font-weight: bold !important; 32 | font-size: .8rem !important; 33 | } 34 | 35 | .md-header-nav__source { 36 | margin-left: 0; 37 | } 38 | 39 | /* Language Drop Down */ 40 | .md-header-nav__lang { 41 | display: block; 42 | width: 2rem; 43 | margin-left: .5rem; 44 | margin-right: .2rem; 45 | padding-right: .6rem; 46 | } 47 | 48 | .md-lang-drop { 49 | line-height: 2.6rem; 50 | padding: 0 0.5rem; 51 | font-size: 1.2rem; 52 | width: 1px 53 | } 54 | 55 | .md-lang-dropbtn { 56 | color: white; 57 | border: none; 58 | cursor: pointer; 59 | font-weight: bold; 60 | } 61 | 62 | .md-lang-dropbtn:hover, .md-lang-dropbtn:focus { 63 | color: #f8991d; 64 | } 65 | 66 | .md-dropdown-content { 67 | display: none; 68 | width: 100%; 69 | background-color: #f1f1f1; 70 | box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); 71 | z-index: 1; 72 | overflow: auto; 73 | } 74 | 75 | .md-dropdown-content a { 76 | color: black; 77 | padding: 0px 10px; 78 | text-decoration: none; 79 | display: block; 80 | line-height: 3rem; 81 | font-weight: bold; 82 | font-size: 1.3rem; 83 | } 84 | 85 | .md-dropdown-content a:hover { 86 | color: #f8991d; 87 | } 88 | 89 | .show { 90 | display:block; 91 | } 92 | 93 | /* Second Navigation */ 94 | 95 | .md-tabs { 96 | background-image: url(../assets/images/second-nav-blue.png); 97 | background-color: #1f4e79 !important; 98 | } 99 | 100 | .md-tabs__item { 101 | margin-right: 15px; 102 | } 103 | 104 | .md-content__button { 105 | display: none; 106 | } 107 | 108 | .md-typeset table:not([class]) th { 109 | min-width: 15rem; 110 | background-color: #6c6c6c !important; 111 | font-size: medium; 112 | } 113 | 114 | .md-typeset table:not([class]) td { 115 | vertical-align: middle; 116 | } 117 | 118 | .table { 119 | font-size: medium; 120 | } 121 | 122 | .md-header-nav__button.md-logo img, .md-header-nav__button.md-logo svg { 123 | width: 40px 124 | } 125 | 126 | /* Footer */ 127 | 128 | .md-footer-nav { 129 | background-image: url(../assets/images/second-nav-blue.png); 130 | background-color: #1f4e79 !important; 131 | } 132 | 133 | .md-footer-meta { 134 | background-color: #232f3e !important; 135 | border-top: 1px solid #1b2532 !important; 136 | } 137 | -------------------------------------------------------------------------------- /images/Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/images/Architecture.png -------------------------------------------------------------------------------- /images/Cloud9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/images/Cloud9.png -------------------------------------------------------------------------------- /images/c9attachrole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/images/c9attachrole.png -------------------------------------------------------------------------------- /images/c9disableiam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/images/c9disableiam.png -------------------------------------------------------------------------------- /images/c9instancerole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/images/c9instancerole.png -------------------------------------------------------------------------------- /images/createrole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/images/createrole.png -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # Project information 2 | 3 | site_name: Build and Deploy Spring Petclinic to Amazon ECS using Terraform 4 | site_short_name: DevOps Pipelines 5 | site_author: 'irsbuchh@amazon.com' 6 | 7 | # Repository 8 | repo_name: 'aws-samples/aws-ecs-cicd-terraform' 9 | repo_url: 'https://github.com/aws-samples/aws-ecs-cicd-terraform' 10 | 11 | # Copyright 12 | copyright: 'Privacy | Site terms | © 2020, Amazon Web Services, Inc. or its affiliates. All rights reserved.' 13 | 14 | # Configuration 15 | theme: 16 | name: 'material' 17 | logo: 'assets/images/aws_smile_logo.png' 18 | favicon: 'assets/images/aws-favicon.ico' 19 | 20 | # Customization 21 | extra_css: 22 | - 'stylesheets/custom.css' 23 | 24 | nav: 25 | - Module 1 - Architecture: architecture.md 26 | - Module 2 - Prerequisites: prerequisites.md 27 | - Module 3 - Build the infrastructure: infrastructure.md 28 | - Module 4 - Deploy: deploy.md 29 | - Module 5 - Trigger pipeline: pipeline.md 30 | - Module 6 - Cleanup: cleanup.md 31 | - Contributing: 'contribute.md' 32 | - License: 'license.md' 33 | 34 | # Extensions 35 | markdown_extensions: 36 | - admonition 37 | - codehilite 38 | - pymdownx.details 39 | -------------------------------------------------------------------------------- /petclinic/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8 2 | VOLUME /tmp 3 | ADD target/spring-petclinic-2.3.0.jar app.jar 4 | EXPOSE 8080 5 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] 6 | -------------------------------------------------------------------------------- /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/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 cacheConfiguration() { 52 | return new MutableConfiguration<>().setStatisticsEnabled(true); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/system/CrashController.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.system; 17 | 18 | import org.springframework.stereotype.Controller; 19 | import org.springframework.web.bind.annotation.GetMapping; 20 | 21 | /** 22 | * Controller used to showcase what happens when an exception is thrown 23 | * 24 | * @author Michael Isvy 25 | *

26 | * Also see how a view that resolves to "error" has been added ("error.html"). 27 | */ 28 | @Controller 29 | class CrashController { 30 | 31 | @GetMapping("/oups") 32 | public String triggerException() { 33 | throw new RuntimeException( 34 | "Expected: controller used to showcase what " + "happens when an exception is thrown"); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/system/WelcomeController.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 org.springframework.stereotype.Controller; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | 22 | @Controller 23 | class WelcomeController { 24 | 25 | @GetMapping("/") 26 | public String welcome() { 27 | return "welcome"; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/vet/Specialty.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.vet; 17 | 18 | import java.io.Serializable; 19 | 20 | import javax.persistence.Entity; 21 | import javax.persistence.Table; 22 | 23 | import org.springframework.samples.petclinic.model.NamedEntity; 24 | 25 | /** 26 | * Models a {@link Vet Vet's} specialty (for example, dentistry). 27 | * 28 | * @author Juergen Hoeller 29 | */ 30 | @Entity 31 | @Table(name = "specialties") 32 | public class Specialty extends NamedEntity implements Serializable { 33 | 34 | } 35 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/vet/Vet.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.vet; 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.Entity; 25 | import javax.persistence.FetchType; 26 | import javax.persistence.JoinColumn; 27 | import javax.persistence.JoinTable; 28 | import javax.persistence.ManyToMany; 29 | import javax.persistence.Table; 30 | import javax.xml.bind.annotation.XmlElement; 31 | 32 | import org.springframework.beans.support.MutableSortDefinition; 33 | import org.springframework.beans.support.PropertyComparator; 34 | import org.springframework.samples.petclinic.model.Person; 35 | 36 | /** 37 | * Simple JavaBean domain object representing a veterinarian. 38 | * 39 | * @author Ken Krebs 40 | * @author Juergen Hoeller 41 | * @author Sam Brannen 42 | * @author Arjen Poutsma 43 | */ 44 | @Entity 45 | @Table(name = "vets") 46 | public class Vet extends Person { 47 | 48 | @ManyToMany(fetch = FetchType.EAGER) 49 | @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), 50 | inverseJoinColumns = @JoinColumn(name = "specialty_id")) 51 | private Set specialties; 52 | 53 | protected Set getSpecialtiesInternal() { 54 | if (this.specialties == null) { 55 | this.specialties = new HashSet<>(); 56 | } 57 | return this.specialties; 58 | } 59 | 60 | protected void setSpecialtiesInternal(Set specialties) { 61 | this.specialties = specialties; 62 | } 63 | 64 | @XmlElement 65 | public List getSpecialties() { 66 | List sortedSpecs = new ArrayList<>(getSpecialtiesInternal()); 67 | PropertyComparator.sort(sortedSpecs, new MutableSortDefinition("name", true, true)); 68 | return Collections.unmodifiableList(sortedSpecs); 69 | } 70 | 71 | public int getNrOfSpecialties() { 72 | return getSpecialtiesInternal().size(); 73 | } 74 | 75 | public void addSpecialty(Specialty specialty) { 76 | getSpecialtiesInternal().add(specialty); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/vet/VetController.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.vet; 17 | 18 | import org.springframework.stereotype.Controller; 19 | import org.springframework.web.bind.annotation.GetMapping; 20 | import org.springframework.web.bind.annotation.ResponseBody; 21 | 22 | import java.util.Map; 23 | 24 | /** 25 | * @author Juergen Hoeller 26 | * @author Mark Fisher 27 | * @author Ken Krebs 28 | * @author Arjen Poutsma 29 | */ 30 | @Controller 31 | class VetController { 32 | 33 | private final VetRepository vets; 34 | 35 | public VetController(VetRepository clinicService) { 36 | this.vets = clinicService; 37 | } 38 | 39 | @GetMapping("/vets.html") 40 | public String showVetList(Map model) { 41 | // Here we are returning an object of type 'Vets' rather than a collection of Vet 42 | // objects so it is simpler for Object-Xml mapping 43 | Vets vets = new Vets(); 44 | vets.getVetList().addAll(this.vets.findAll()); 45 | model.put("vets", vets); 46 | return "vets/vetList"; 47 | } 48 | 49 | @GetMapping({ "/vets" }) 50 | public @ResponseBody Vets showResourcesVetList() { 51 | // Here we are returning an object of type 'Vets' rather than a collection of Vet 52 | // objects so it is simpler for JSon/Object mapping 53 | Vets vets = new Vets(); 54 | vets.getVetList().addAll(this.vets.findAll()); 55 | return vets; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.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.vet; 17 | 18 | import java.util.Collection; 19 | 20 | import org.springframework.cache.annotation.Cacheable; 21 | import org.springframework.dao.DataAccessException; 22 | import org.springframework.data.repository.Repository; 23 | import org.springframework.transaction.annotation.Transactional; 24 | 25 | /** 26 | * Repository class for Vet 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 VetRepository extends Repository { 37 | 38 | /** 39 | * Retrieve all Vets from the data store. 40 | * @return a Collection of Vets 41 | */ 42 | @Transactional(readOnly = true) 43 | @Cacheable("vets") 44 | Collection findAll() throws DataAccessException; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/vet/Vets.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.vet; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import javax.xml.bind.annotation.XmlElement; 22 | import javax.xml.bind.annotation.XmlRootElement; 23 | 24 | /** 25 | * Simple domain object representing a list of veterinarians. Mostly here to be used for 26 | * the 'vets' {@link org.springframework.web.servlet.view.xml.MarshallingView}. 27 | * 28 | * @author Arjen Poutsma 29 | */ 30 | @XmlRootElement 31 | public class Vets { 32 | 33 | private List vets; 34 | 35 | @XmlElement 36 | public List getVetList() { 37 | if (vets == null) { 38 | vets = new ArrayList<>(); 39 | } 40 | return vets; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/visit/Visit.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.visit; 17 | 18 | import java.time.LocalDate; 19 | 20 | import javax.persistence.Column; 21 | import javax.persistence.Entity; 22 | import javax.persistence.Table; 23 | import javax.validation.constraints.NotEmpty; 24 | 25 | import org.springframework.format.annotation.DateTimeFormat; 26 | import org.springframework.samples.petclinic.model.BaseEntity; 27 | 28 | /** 29 | * Simple JavaBean domain object representing a visit. 30 | * 31 | * @author Ken Krebs 32 | * @author Dave Syer 33 | */ 34 | @Entity 35 | @Table(name = "visits") 36 | public class Visit extends BaseEntity { 37 | 38 | @Column(name = "visit_date") 39 | @DateTimeFormat(pattern = "yyyy-MM-dd") 40 | private LocalDate date; 41 | 42 | @NotEmpty 43 | @Column(name = "description") 44 | private String description; 45 | 46 | @Column(name = "pet_id") 47 | private Integer petId; 48 | 49 | /** 50 | * Creates a new instance of Visit for the current date 51 | */ 52 | public Visit() { 53 | this.date = LocalDate.now(); 54 | } 55 | 56 | public LocalDate getDate() { 57 | return this.date; 58 | } 59 | 60 | public void setDate(LocalDate date) { 61 | this.date = date; 62 | } 63 | 64 | public String getDescription() { 65 | return this.description; 66 | } 67 | 68 | public void setDescription(String description) { 69 | this.description = description; 70 | } 71 | 72 | public Integer getPetId() { 73 | return this.petId; 74 | } 75 | 76 | public void setPetId(Integer petId) { 77 | this.petId = petId; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /petclinic/src/main/java/org/springframework/samples/petclinic/visit/VisitRepository.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.visit; 17 | 18 | import java.util.List; 19 | 20 | import org.springframework.dao.DataAccessException; 21 | import org.springframework.data.repository.Repository; 22 | import org.springframework.samples.petclinic.model.BaseEntity; 23 | 24 | /** 25 | * Repository class for Visit 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 VisitRepository extends Repository { 36 | 37 | /** 38 | * Save a Visit to the data store, either inserting or updating it. 39 | * @param visit the Visit to save 40 | * @see BaseEntity#isNew 41 | */ 42 | void save(Visit visit) throws DataAccessException; 43 | 44 | List findByPetId(Integer petId); 45 | 46 | } 47 | -------------------------------------------------------------------------------- /petclinic/src/main/less/header.less: -------------------------------------------------------------------------------- 1 | .navbar { 2 | border-top: 4px solid #6db33f; 3 | background-color: #34302d; 4 | margin-bottom: 0px; 5 | border-bottom: 0; 6 | border-left: 0; 7 | border-right: 0; 8 | } 9 | 10 | .navbar a.navbar-brand { 11 | background: url("../images/spring-logo-dataflow.png") -1px -1px no-repeat; 12 | margin: 12px 0 6px; 13 | width: 229px; 14 | height: 46px; 15 | display: inline-block; 16 | text-decoration: none; 17 | padding: 0; 18 | } 19 | 20 | .navbar a.navbar-brand span { 21 | display: block; 22 | width: 229px; 23 | height: 46px; 24 | background: url("../images/spring-logo-dataflow.png") -1px -48px no-repeat; 25 | opacity: 0; 26 | -moz-transition: opacity 0.12s ease-in-out; 27 | -webkit-transition: opacity 0.12s ease-in-out; 28 | -o-transition: opacity 0.12s ease-in-out; 29 | } 30 | 31 | .navbar a:hover.navbar-brand span { 32 | opacity: 1; 33 | } 34 | 35 | .navbar li > a, .navbar-text { 36 | font-family: "montserratregular", sans-serif; 37 | text-shadow: none; 38 | font-size: 14px; 39 | 40 | /* line-height: 14px; */ 41 | padding: 28px 20px; 42 | transition: all 0.15s; 43 | -webkit-transition: all 0.15s; 44 | -moz-transition: all 0.15s; 45 | -o-transition: all 0.15s; 46 | -ms-transition: all 0.15s; 47 | } 48 | 49 | .navbar li > a { 50 | text-transform: uppercase; 51 | } 52 | 53 | .navbar .navbar-text { 54 | margin-top: 0; 55 | margin-bottom: 0; 56 | } 57 | .navbar li:hover > a { 58 | color: #eeeeee; 59 | background-color: #6db33f; 60 | } 61 | 62 | .navbar-toggle { 63 | border-width: 0; 64 | 65 | .icon-bar + .icon-bar { 66 | margin-top: 3px; 67 | } 68 | .icon-bar { 69 | width: 19px; 70 | height: 3px; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /petclinic/src/main/less/responsive.less: -------------------------------------------------------------------------------- 1 | @media (max-width: 768px) { 2 | .navbar-toggle { 3 | position:absolute; 4 | z-index: 9999; 5 | left:0px; 6 | top:0px; 7 | } 8 | 9 | .navbar a.navbar-brand { 10 | display: block; 11 | margin: 0 auto 0 auto; 12 | width: 148px; 13 | height: 50px; 14 | float: none; 15 | background: url("../images/spring-logo-dataflow-mobile.png") 0 center no-repeat; 16 | } 17 | 18 | .homepage-billboard .homepage-subtitle { 19 | font-size: 21px; 20 | line-height: 21px; 21 | } 22 | 23 | .navbar a.navbar-brand span { 24 | display: none; 25 | } 26 | 27 | .navbar { 28 | border-top-width: 0; 29 | } 30 | 31 | .xd-container { 32 | margin-top: 20px; 33 | margin-bottom: 30px; 34 | } 35 | 36 | .index-page--subtitle { 37 | margin-top: 10px; 38 | margin-bottom: 30px; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /petclinic/src/main/less/typography.less: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'varela_roundregular'; 3 | 4 | src: url('../fonts/varela_round-webfont.eot'); 5 | src: url('../fonts/varela_round-webfont.eot?#iefix') format('embedded-opentype'), 6 | url('../fonts/varela_round-webfont.woff') format('woff'), 7 | url('../fonts/varela_round-webfont.ttf') format('truetype'), 8 | url('../fonts/varela_round-webfont.svg#varela_roundregular') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | @font-face { 14 | font-family: 'montserratregular'; 15 | src: url('../fonts/montserrat-webfont.eot'); 16 | src: url('../fonts/montserrat-webfont.eot?#iefix') format('embedded-opentype'), 17 | url('../fonts/montserrat-webfont.woff') format('woff'), 18 | url('../fonts/montserrat-webfont.ttf') format('truetype'), 19 | url('../fonts/montserrat-webfont.svg#montserratregular') format('svg'); 20 | font-weight: normal; 21 | font-style: normal; 22 | } 23 | 24 | body, h1, h2, h3, p, input { 25 | margin: 0; 26 | font-weight: 400; 27 | font-family: "varela_roundregular", sans-serif; 28 | color: #34302d; 29 | } 30 | 31 | h1 { 32 | font-size: 24px; 33 | line-height: 30px; 34 | font-family: "montserratregular", sans-serif; 35 | } 36 | 37 | h2 { 38 | font-size: 18px; 39 | font-weight: 700; 40 | line-height: 24px; 41 | margin-bottom: 10px; 42 | font-family: "montserratregular", sans-serif; 43 | } 44 | 45 | h3 { 46 | font-size: 16px; 47 | line-height: 24px; 48 | margin-bottom: 10px; 49 | font-weight: 700; 50 | } 51 | 52 | p { 53 | //font-size: 15px; 54 | //line-height: 24px; 55 | } 56 | 57 | strong { 58 | font-weight: 700; 59 | font-family: "montserratregular", sans-serif; 60 | } 61 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/application-mysql.properties: -------------------------------------------------------------------------------- 1 | # database init, supports mysql too 2 | database=mysql 3 | spring.datasource.url=${MYSQL_URL:jdbc:mysql://localhost/petclinic} 4 | spring.datasource.username=${MYSQL_USER:petclinic} 5 | spring.datasource.password=${MYSQL_PASS:petclinic} 6 | # SQL is written to be idempotent so this is safe 7 | spring.datasource.initialization-mode=always 8 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # database init, supports mysql too 2 | database=h2 3 | spring.datasource.schema=classpath*:db/${database}/schema.sql 4 | spring.datasource.data=classpath*:db/${database}/data.sql 5 | 6 | # Web 7 | spring.thymeleaf.mode=HTML 8 | 9 | # JPA 10 | spring.jpa.hibernate.ddl-auto=none 11 | spring.jpa.open-in-view=false 12 | 13 | # Internationalization 14 | spring.messages.basename=messages/messages 15 | 16 | # Actuator 17 | management.endpoints.web.exposure.include=* 18 | 19 | # Logging 20 | logging.level.org.springframework=INFO 21 | # logging.level.org.springframework.web=DEBUG 22 | # logging.level.org.springframework.context.annotation=TRACE 23 | 24 | # Maximum time static resources should be cached 25 | spring.resources.cache.cachecontrol.max-age=12h 26 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | |\ _,,,--,,_ 4 | /,`.-'`' ._ \-;;,_ 5 | _______ __|,4- ) )_ .;.(__`'-'__ ___ __ _ ___ _______ 6 | | | '---''(_/._)-'(_\_) | | | | | | | | | 7 | | _ | ___|_ _| | | | | |_| | | | __ _ _ 8 | | |_| | |___ | | | | | | | | | | \ \ \ \ 9 | | ___| ___| | | | _| |___| | _ | | _| \ \ \ \ 10 | | | | |___ | | | |_| | | | | | | |_ ) ) ) ) 11 | |___| |_______| |___| |_______|_______|___|_| |__|___|_______| / / / / 12 | ==================================================================/_/_/_/ 13 | 14 | :: Built with Spring Boot :: ${spring-boot.version} 15 | 16 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/db/h2/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO vets VALUES (1, 'James', 'Carter'); 2 | INSERT INTO vets VALUES (2, 'Helen', 'Leary'); 3 | INSERT INTO vets VALUES (3, 'Linda', 'Douglas'); 4 | INSERT INTO vets VALUES (4, 'Rafael', 'Ortega'); 5 | INSERT INTO vets VALUES (5, 'Henry', 'Stevens'); 6 | INSERT INTO vets VALUES (6, 'Sharon', 'Jenkins'); 7 | 8 | INSERT INTO specialties VALUES (1, 'radiology'); 9 | INSERT INTO specialties VALUES (2, 'surgery'); 10 | INSERT INTO specialties VALUES (3, 'dentistry'); 11 | 12 | INSERT INTO vet_specialties VALUES (2, 1); 13 | INSERT INTO vet_specialties VALUES (3, 2); 14 | INSERT INTO vet_specialties VALUES (3, 3); 15 | INSERT INTO vet_specialties VALUES (4, 2); 16 | INSERT INTO vet_specialties VALUES (5, 1); 17 | 18 | INSERT INTO types VALUES (1, 'cat'); 19 | INSERT INTO types VALUES (2, 'dog'); 20 | INSERT INTO types VALUES (3, 'lizard'); 21 | INSERT INTO types VALUES (4, 'snake'); 22 | INSERT INTO types VALUES (5, 'bird'); 23 | INSERT INTO types VALUES (6, 'hamster'); 24 | 25 | INSERT INTO owners VALUES (1, 'George', 'Franklin', '110 W. Liberty St.', 'Madison', '6085551023'); 26 | INSERT INTO owners VALUES (2, 'Betty', 'Davis', '638 Cardinal Ave.', 'Sun Prairie', '6085551749'); 27 | INSERT INTO owners VALUES (3, 'Eduardo', 'Rodriquez', '2693 Commerce St.', 'McFarland', '6085558763'); 28 | INSERT INTO owners VALUES (4, 'Harold', 'Davis', '563 Friendly St.', 'Windsor', '6085553198'); 29 | INSERT INTO owners VALUES (5, 'Peter', 'McTavish', '2387 S. Fair Way', 'Madison', '6085552765'); 30 | INSERT INTO owners VALUES (6, 'Jean', 'Coleman', '105 N. Lake St.', 'Monona', '6085552654'); 31 | INSERT INTO owners VALUES (7, 'Jeff', 'Black', '1450 Oak Blvd.', 'Monona', '6085555387'); 32 | INSERT INTO owners VALUES (8, 'Maria', 'Escobito', '345 Maple St.', 'Madison', '6085557683'); 33 | INSERT INTO owners VALUES (9, 'David', 'Schroeder', '2749 Blackhawk Trail', 'Madison', '6085559435'); 34 | INSERT INTO owners VALUES (10, 'Carlos', 'Estaban', '2335 Independence La.', 'Waunakee', '6085555487'); 35 | 36 | INSERT INTO pets VALUES (1, 'Leo', '2010-09-07', 1, 1); 37 | INSERT INTO pets VALUES (2, 'Basil', '2012-08-06', 6, 2); 38 | INSERT INTO pets VALUES (3, 'Rosy', '2011-04-17', 2, 3); 39 | INSERT INTO pets VALUES (4, 'Jewel', '2010-03-07', 2, 3); 40 | INSERT INTO pets VALUES (5, 'Iggy', '2010-11-30', 3, 4); 41 | INSERT INTO pets VALUES (6, 'George', '2010-01-20', 4, 5); 42 | INSERT INTO pets VALUES (7, 'Samantha', '2012-09-04', 1, 6); 43 | INSERT INTO pets VALUES (8, 'Max', '2012-09-04', 1, 6); 44 | INSERT INTO pets VALUES (9, 'Lucky', '2011-08-06', 5, 7); 45 | INSERT INTO pets VALUES (10, 'Mulligan', '2007-02-24', 2, 8); 46 | INSERT INTO pets VALUES (11, 'Freddy', '2010-03-09', 5, 9); 47 | INSERT INTO pets VALUES (12, 'Lucky', '2010-06-24', 2, 10); 48 | INSERT INTO pets VALUES (13, 'Sly', '2012-06-08', 1, 10); 49 | 50 | INSERT INTO visits VALUES (1, 7, '2013-01-01', 'rabies shot'); 51 | INSERT INTO visits VALUES (2, 8, '2013-01-02', 'rabies shot'); 52 | INSERT INTO visits VALUES (3, 8, '2013-01-03', 'neutered'); 53 | INSERT INTO visits VALUES (4, 7, '2013-01-04', 'spayed'); 54 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/db/h2/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE vet_specialties IF EXISTS; 2 | DROP TABLE vets IF EXISTS; 3 | DROP TABLE specialties IF EXISTS; 4 | DROP TABLE visits IF EXISTS; 5 | DROP TABLE pets IF EXISTS; 6 | DROP TABLE types IF EXISTS; 7 | DROP TABLE owners IF EXISTS; 8 | 9 | 10 | CREATE TABLE vets ( 11 | id INTEGER IDENTITY PRIMARY KEY, 12 | first_name VARCHAR(30), 13 | last_name VARCHAR(30) 14 | ); 15 | CREATE INDEX vets_last_name ON vets (last_name); 16 | 17 | CREATE TABLE specialties ( 18 | id INTEGER IDENTITY PRIMARY KEY, 19 | name VARCHAR(80) 20 | ); 21 | CREATE INDEX specialties_name ON specialties (name); 22 | 23 | CREATE TABLE vet_specialties ( 24 | vet_id INTEGER NOT NULL, 25 | specialty_id INTEGER NOT NULL 26 | ); 27 | ALTER TABLE vet_specialties ADD CONSTRAINT fk_vet_specialties_vets FOREIGN KEY (vet_id) REFERENCES vets (id); 28 | ALTER TABLE vet_specialties ADD CONSTRAINT fk_vet_specialties_specialties FOREIGN KEY (specialty_id) REFERENCES specialties (id); 29 | 30 | CREATE TABLE types ( 31 | id INTEGER IDENTITY PRIMARY KEY, 32 | name VARCHAR(80) 33 | ); 34 | CREATE INDEX types_name ON types (name); 35 | 36 | CREATE TABLE owners ( 37 | id INTEGER IDENTITY PRIMARY KEY, 38 | first_name VARCHAR(30), 39 | last_name VARCHAR_IGNORECASE(30), 40 | address VARCHAR(255), 41 | city VARCHAR(80), 42 | telephone VARCHAR(20) 43 | ); 44 | CREATE INDEX owners_last_name ON owners (last_name); 45 | 46 | CREATE TABLE pets ( 47 | id INTEGER IDENTITY PRIMARY KEY, 48 | name VARCHAR(30), 49 | birth_date DATE, 50 | type_id INTEGER NOT NULL, 51 | owner_id INTEGER NOT NULL 52 | ); 53 | ALTER TABLE pets ADD CONSTRAINT fk_pets_owners FOREIGN KEY (owner_id) REFERENCES owners (id); 54 | ALTER TABLE pets ADD CONSTRAINT fk_pets_types FOREIGN KEY (type_id) REFERENCES types (id); 55 | CREATE INDEX pets_name ON pets (name); 56 | 57 | CREATE TABLE visits ( 58 | id INTEGER IDENTITY PRIMARY KEY, 59 | pet_id INTEGER NOT NULL, 60 | visit_date DATE, 61 | description VARCHAR(255) 62 | ); 63 | ALTER TABLE visits ADD CONSTRAINT fk_visits_pets FOREIGN KEY (pet_id) REFERENCES pets (id); 64 | CREATE INDEX visits_pet_id ON visits (pet_id); 65 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/db/hsqldb/data.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO vets VALUES (1, 'James', 'Carter'); 2 | INSERT INTO vets VALUES (2, 'Helen', 'Leary'); 3 | INSERT INTO vets VALUES (3, 'Linda', 'Douglas'); 4 | INSERT INTO vets VALUES (4, 'Rafael', 'Ortega'); 5 | INSERT INTO vets VALUES (5, 'Henry', 'Stevens'); 6 | INSERT INTO vets VALUES (6, 'Sharon', 'Jenkins'); 7 | 8 | INSERT INTO specialties VALUES (1, 'radiology'); 9 | INSERT INTO specialties VALUES (2, 'surgery'); 10 | INSERT INTO specialties VALUES (3, 'dentistry'); 11 | 12 | INSERT INTO vet_specialties VALUES (2, 1); 13 | INSERT INTO vet_specialties VALUES (3, 2); 14 | INSERT INTO vet_specialties VALUES (3, 3); 15 | INSERT INTO vet_specialties VALUES (4, 2); 16 | INSERT INTO vet_specialties VALUES (5, 1); 17 | 18 | INSERT INTO types VALUES (1, 'cat'); 19 | INSERT INTO types VALUES (2, 'dog'); 20 | INSERT INTO types VALUES (3, 'lizard'); 21 | INSERT INTO types VALUES (4, 'snake'); 22 | INSERT INTO types VALUES (5, 'bird'); 23 | INSERT INTO types VALUES (6, 'hamster'); 24 | 25 | INSERT INTO owners VALUES (1, 'George', 'Franklin', '110 W. Liberty St.', 'Madison', '6085551023'); 26 | INSERT INTO owners VALUES (2, 'Betty', 'Davis', '638 Cardinal Ave.', 'Sun Prairie', '6085551749'); 27 | INSERT INTO owners VALUES (3, 'Eduardo', 'Rodriquez', '2693 Commerce St.', 'McFarland', '6085558763'); 28 | INSERT INTO owners VALUES (4, 'Harold', 'Davis', '563 Friendly St.', 'Windsor', '6085553198'); 29 | INSERT INTO owners VALUES (5, 'Peter', 'McTavish', '2387 S. Fair Way', 'Madison', '6085552765'); 30 | INSERT INTO owners VALUES (6, 'Jean', 'Coleman', '105 N. Lake St.', 'Monona', '6085552654'); 31 | INSERT INTO owners VALUES (7, 'Jeff', 'Black', '1450 Oak Blvd.', 'Monona', '6085555387'); 32 | INSERT INTO owners VALUES (8, 'Maria', 'Escobito', '345 Maple St.', 'Madison', '6085557683'); 33 | INSERT INTO owners VALUES (9, 'David', 'Schroeder', '2749 Blackhawk Trail', 'Madison', '6085559435'); 34 | INSERT INTO owners VALUES (10, 'Carlos', 'Estaban', '2335 Independence La.', 'Waunakee', '6085555487'); 35 | 36 | INSERT INTO pets VALUES (1, 'Leo', '2010-09-07', 1, 1); 37 | INSERT INTO pets VALUES (2, 'Basil', '2012-08-06', 6, 2); 38 | INSERT INTO pets VALUES (3, 'Rosy', '2011-04-17', 2, 3); 39 | INSERT INTO pets VALUES (4, 'Jewel', '2010-03-07', 2, 3); 40 | INSERT INTO pets VALUES (5, 'Iggy', '2010-11-30', 3, 4); 41 | INSERT INTO pets VALUES (6, 'George', '2010-01-20', 4, 5); 42 | INSERT INTO pets VALUES (7, 'Samantha', '2012-09-04', 1, 6); 43 | INSERT INTO pets VALUES (8, 'Max', '2012-09-04', 1, 6); 44 | INSERT INTO pets VALUES (9, 'Lucky', '2011-08-06', 5, 7); 45 | INSERT INTO pets VALUES (10, 'Mulligan', '2007-02-24', 2, 8); 46 | INSERT INTO pets VALUES (11, 'Freddy', '2010-03-09', 5, 9); 47 | INSERT INTO pets VALUES (12, 'Lucky', '2010-06-24', 2, 10); 48 | INSERT INTO pets VALUES (13, 'Sly', '2012-06-08', 1, 10); 49 | 50 | INSERT INTO visits VALUES (1, 7, '2013-01-01', 'rabies shot'); 51 | INSERT INTO visits VALUES (2, 8, '2013-01-02', 'rabies shot'); 52 | INSERT INTO visits VALUES (3, 8, '2013-01-03', 'neutered'); 53 | INSERT INTO visits VALUES (4, 7, '2013-01-04', 'spayed'); 54 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/db/hsqldb/schema.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE vet_specialties IF EXISTS; 2 | DROP TABLE vets IF EXISTS; 3 | DROP TABLE specialties IF EXISTS; 4 | DROP TABLE visits IF EXISTS; 5 | DROP TABLE pets IF EXISTS; 6 | DROP TABLE types IF EXISTS; 7 | DROP TABLE owners IF EXISTS; 8 | 9 | 10 | CREATE TABLE vets ( 11 | id INTEGER IDENTITY PRIMARY KEY, 12 | first_name VARCHAR(30), 13 | last_name VARCHAR(30) 14 | ); 15 | CREATE INDEX vets_last_name ON vets (last_name); 16 | 17 | CREATE TABLE specialties ( 18 | id INTEGER IDENTITY PRIMARY KEY, 19 | name VARCHAR(80) 20 | ); 21 | CREATE INDEX specialties_name ON specialties (name); 22 | 23 | CREATE TABLE vet_specialties ( 24 | vet_id INTEGER NOT NULL, 25 | specialty_id INTEGER NOT NULL 26 | ); 27 | ALTER TABLE vet_specialties ADD CONSTRAINT fk_vet_specialties_vets FOREIGN KEY (vet_id) REFERENCES vets (id); 28 | ALTER TABLE vet_specialties ADD CONSTRAINT fk_vet_specialties_specialties FOREIGN KEY (specialty_id) REFERENCES specialties (id); 29 | 30 | CREATE TABLE types ( 31 | id INTEGER IDENTITY PRIMARY KEY, 32 | name VARCHAR(80) 33 | ); 34 | CREATE INDEX types_name ON types (name); 35 | 36 | CREATE TABLE owners ( 37 | id INTEGER IDENTITY PRIMARY KEY, 38 | first_name VARCHAR(30), 39 | last_name VARCHAR_IGNORECASE(30), 40 | address VARCHAR(255), 41 | city VARCHAR(80), 42 | telephone VARCHAR(20) 43 | ); 44 | CREATE INDEX owners_last_name ON owners (last_name); 45 | 46 | CREATE TABLE pets ( 47 | id INTEGER IDENTITY PRIMARY KEY, 48 | name VARCHAR(30), 49 | birth_date DATE, 50 | type_id INTEGER NOT NULL, 51 | owner_id INTEGER NOT NULL 52 | ); 53 | ALTER TABLE pets ADD CONSTRAINT fk_pets_owners FOREIGN KEY (owner_id) REFERENCES owners (id); 54 | ALTER TABLE pets ADD CONSTRAINT fk_pets_types FOREIGN KEY (type_id) REFERENCES types (id); 55 | CREATE INDEX pets_name ON pets (name); 56 | 57 | CREATE TABLE visits ( 58 | id INTEGER IDENTITY PRIMARY KEY, 59 | pet_id INTEGER NOT NULL, 60 | visit_date DATE, 61 | description VARCHAR(255) 62 | ); 63 | ALTER TABLE visits ADD CONSTRAINT fk_visits_pets FOREIGN KEY (pet_id) REFERENCES pets (id); 64 | CREATE INDEX visits_pet_id ON visits (pet_id); 65 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/db/mysql/data.sql: -------------------------------------------------------------------------------- 1 | INSERT IGNORE INTO vets VALUES (1, 'James', 'Carter'); 2 | INSERT IGNORE INTO vets VALUES (2, 'Helen', 'Leary'); 3 | INSERT IGNORE INTO vets VALUES (3, 'Linda', 'Douglas'); 4 | INSERT IGNORE INTO vets VALUES (4, 'Rafael', 'Ortega'); 5 | INSERT IGNORE INTO vets VALUES (5, 'Henry', 'Stevens'); 6 | INSERT IGNORE INTO vets VALUES (6, 'Sharon', 'Jenkins'); 7 | 8 | INSERT IGNORE INTO specialties VALUES (1, 'radiology'); 9 | INSERT IGNORE INTO specialties VALUES (2, 'surgery'); 10 | INSERT IGNORE INTO specialties VALUES (3, 'dentistry'); 11 | 12 | INSERT IGNORE INTO vet_specialties VALUES (2, 1); 13 | INSERT IGNORE INTO vet_specialties VALUES (3, 2); 14 | INSERT IGNORE INTO vet_specialties VALUES (3, 3); 15 | INSERT IGNORE INTO vet_specialties VALUES (4, 2); 16 | INSERT IGNORE INTO vet_specialties VALUES (5, 1); 17 | 18 | INSERT IGNORE INTO types VALUES (1, 'cat'); 19 | INSERT IGNORE INTO types VALUES (2, 'dog'); 20 | INSERT IGNORE INTO types VALUES (3, 'lizard'); 21 | INSERT IGNORE INTO types VALUES (4, 'snake'); 22 | INSERT IGNORE INTO types VALUES (5, 'bird'); 23 | INSERT IGNORE INTO types VALUES (6, 'hamster'); 24 | 25 | INSERT IGNORE INTO owners VALUES (1, 'George', 'Franklin', '110 W. Liberty St.', 'Madison', '6085551023'); 26 | INSERT IGNORE INTO owners VALUES (2, 'Betty', 'Davis', '638 Cardinal Ave.', 'Sun Prairie', '6085551749'); 27 | INSERT IGNORE INTO owners VALUES (3, 'Eduardo', 'Rodriquez', '2693 Commerce St.', 'McFarland', '6085558763'); 28 | INSERT IGNORE INTO owners VALUES (4, 'Harold', 'Davis', '563 Friendly St.', 'Windsor', '6085553198'); 29 | INSERT IGNORE INTO owners VALUES (5, 'Peter', 'McTavish', '2387 S. Fair Way', 'Madison', '6085552765'); 30 | INSERT IGNORE INTO owners VALUES (6, 'Jean', 'Coleman', '105 N. Lake St.', 'Monona', '6085552654'); 31 | INSERT IGNORE INTO owners VALUES (7, 'Jeff', 'Black', '1450 Oak Blvd.', 'Monona', '6085555387'); 32 | INSERT IGNORE INTO owners VALUES (8, 'Maria', 'Escobito', '345 Maple St.', 'Madison', '6085557683'); 33 | INSERT IGNORE INTO owners VALUES (9, 'David', 'Schroeder', '2749 Blackhawk Trail', 'Madison', '6085559435'); 34 | INSERT IGNORE INTO owners VALUES (10, 'Carlos', 'Estaban', '2335 Independence La.', 'Waunakee', '6085555487'); 35 | 36 | INSERT IGNORE INTO pets VALUES (1, 'Leo', '2000-09-07', 1, 1); 37 | INSERT IGNORE INTO pets VALUES (2, 'Basil', '2002-08-06', 6, 2); 38 | INSERT IGNORE INTO pets VALUES (3, 'Rosy', '2001-04-17', 2, 3); 39 | INSERT IGNORE INTO pets VALUES (4, 'Jewel', '2000-03-07', 2, 3); 40 | INSERT IGNORE INTO pets VALUES (5, 'Iggy', '2000-11-30', 3, 4); 41 | INSERT IGNORE INTO pets VALUES (6, 'George', '2000-01-20', 4, 5); 42 | INSERT IGNORE INTO pets VALUES (7, 'Samantha', '1995-09-04', 1, 6); 43 | INSERT IGNORE INTO pets VALUES (8, 'Max', '1995-09-04', 1, 6); 44 | INSERT IGNORE INTO pets VALUES (9, 'Lucky', '1999-08-06', 5, 7); 45 | INSERT IGNORE INTO pets VALUES (10, 'Mulligan', '1997-02-24', 2, 8); 46 | INSERT IGNORE INTO pets VALUES (11, 'Freddy', '2000-03-09', 5, 9); 47 | INSERT IGNORE INTO pets VALUES (12, 'Lucky', '2000-06-24', 2, 10); 48 | INSERT IGNORE INTO pets VALUES (13, 'Sly', '2002-06-08', 1, 10); 49 | 50 | INSERT IGNORE INTO visits VALUES (1, 7, '2010-03-04', 'rabies shot'); 51 | INSERT IGNORE INTO visits VALUES (2, 8, '2011-03-04', 'rabies shot'); 52 | INSERT IGNORE INTO visits VALUES (3, 8, '2009-06-04', 'neutered'); 53 | INSERT IGNORE INTO visits VALUES (4, 7, '2008-09-04', 'spayed'); 54 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/db/mysql/petclinic_db_setup_mysql.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | === Spring PetClinic sample application - MySQL Configuration === 3 | ================================================================================ 4 | 5 | @author Sam Brannen 6 | @author Costin Leau 7 | @author Dave Syer 8 | 9 | -------------------------------------------------------------------------------- 10 | 11 | 1) Download and install the MySQL database (e.g., MySQL Community Server 5.1.x), 12 | which can be found here: https://dev.mysql.com/downloads/. Or run the 13 | "docker-compose.yml" from the root of the project (if you have docker installed 14 | locally): 15 | 16 | $ docker-compose up 17 | ... 18 | mysql_1_eedb4818d817 | MySQL init process done. Ready for start up. 19 | ... 20 | 21 | 2) (Once only) create the PetClinic database and user by executing the "db/mysql/user.sql" 22 | scripts. You can connect to the database running in the docker container using 23 | `mysql -u root -h localhost --protocol tcp`, but you don't need to run the script there 24 | because the petclinic user is already set up if you use the provided `docker-compose.yaml`. 25 | 26 | 3) Run the app with `spring.profiles.active=mysql` (e.g. as a System property via the command 27 | line, but any way that sets that property in a Spring Boot app should work). 28 | 29 | N.B. the "petclinic" database has to exist for the app to work with the JDBC URL value 30 | as it is configured by default. This condition is taken care of automatically by the 31 | docker-compose configuration provided, or by the `user.sql` script if you run that as 32 | root. 33 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/db/mysql/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS vets ( 2 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 3 | first_name VARCHAR(30), 4 | last_name VARCHAR(30), 5 | INDEX(last_name) 6 | ) engine=InnoDB; 7 | 8 | CREATE TABLE IF NOT EXISTS specialties ( 9 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 10 | name VARCHAR(80), 11 | INDEX(name) 12 | ) engine=InnoDB; 13 | 14 | CREATE TABLE IF NOT EXISTS vet_specialties ( 15 | vet_id INT(4) UNSIGNED NOT NULL, 16 | specialty_id INT(4) UNSIGNED NOT NULL, 17 | FOREIGN KEY (vet_id) REFERENCES vets(id), 18 | FOREIGN KEY (specialty_id) REFERENCES specialties(id), 19 | UNIQUE (vet_id,specialty_id) 20 | ) engine=InnoDB; 21 | 22 | CREATE TABLE IF NOT EXISTS types ( 23 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 24 | name VARCHAR(80), 25 | INDEX(name) 26 | ) engine=InnoDB; 27 | 28 | CREATE TABLE IF NOT EXISTS owners ( 29 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 30 | first_name VARCHAR(30), 31 | last_name VARCHAR(30), 32 | address VARCHAR(255), 33 | city VARCHAR(80), 34 | telephone VARCHAR(20), 35 | INDEX(last_name) 36 | ) engine=InnoDB; 37 | 38 | CREATE TABLE IF NOT EXISTS pets ( 39 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 40 | name VARCHAR(30), 41 | birth_date DATE, 42 | type_id INT(4) UNSIGNED NOT NULL, 43 | owner_id INT(4) UNSIGNED NOT NULL, 44 | INDEX(name), 45 | FOREIGN KEY (owner_id) REFERENCES owners(id), 46 | FOREIGN KEY (type_id) REFERENCES types(id) 47 | ) engine=InnoDB; 48 | 49 | CREATE TABLE IF NOT EXISTS visits ( 50 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 51 | pet_id INT(4) UNSIGNED NOT NULL, 52 | visit_date DATE, 53 | description VARCHAR(255), 54 | FOREIGN KEY (pet_id) REFERENCES pets(id) 55 | ) engine=InnoDB; 56 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/db/mysql/user.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS petclinic; 2 | 3 | ALTER DATABASE petclinic 4 | DEFAULT CHARACTER SET utf8 5 | DEFAULT COLLATE utf8_general_ci; 6 | 7 | GRANT ALL PRIVILEGES ON petclinic.* TO 'petclinic@%' IDENTIFIED BY 'petclinic'; 8 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/messages/messages.properties: -------------------------------------------------------------------------------- 1 | welcome=Welcome 2 | required=is required 3 | notFound=has not been found 4 | duplicate=is already in use 5 | nonNumeric=must be all numeric 6 | duplicateFormSubmission=Duplicate form submission is not allowed 7 | typeMismatch.date=invalid date 8 | typeMismatch.birthDate=invalid date 9 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/messages/messages_de.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/messages/messages_de.properties -------------------------------------------------------------------------------- /petclinic/src/main/resources/messages/messages_en.properties: -------------------------------------------------------------------------------- 1 | # This file is intentionally empty. Message look-ups will fall back to the default "messages.properties" file. -------------------------------------------------------------------------------- /petclinic/src/main/resources/messages/messages_es.properties: -------------------------------------------------------------------------------- 1 | welcome=Bienvenido 2 | required=Es requerido 3 | notFound=No ha sido encontrado 4 | duplicate=Ya se encuentra en uso 5 | nonNumeric=Sólo debe contener numeros 6 | duplicateFormSubmission=No se permite el envío de formularios duplicados 7 | typeMismatch.date=Fecha invalida 8 | typeMismatch.birthDate=Fecha invalida 9 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/fonts/montserrat-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/fonts/montserrat-webfont.eot -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/fonts/montserrat-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/fonts/montserrat-webfont.ttf -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/fonts/montserrat-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/fonts/montserrat-webfont.woff -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/fonts/varela_round-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/fonts/varela_round-webfont.eot -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/fonts/varela_round-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/fonts/varela_round-webfont.ttf -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/fonts/varela_round-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/fonts/varela_round-webfont.woff -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/images/favicon.png -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/images/pets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/images/pets.png -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/images/platform-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/images/platform-bg.png -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/images/spring-logo-dataflow-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/images/spring-logo-dataflow-mobile.png -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/images/spring-logo-dataflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/images/spring-logo-dataflow.png -------------------------------------------------------------------------------- /petclinic/src/main/resources/static/resources/images/spring-pivotal-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/petclinic/src/main/resources/static/resources/images/spring-pivotal-logo.png -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Something happened...

8 |

Exception message

9 | 10 | 11 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/fragments/inputField.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
8 | 9 |
10 |
11 | 12 | 15 |
16 | 19 | 20 | 23 | Error 24 | 25 |
26 |
27 |
28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/fragments/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | PetClinic :: a Spring Framework demonstration 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 81 |
82 |
83 | 84 | 85 | 86 |
87 |
88 |
89 |
90 |
91 | Sponsored by Pivotal
93 |
94 |
95 |
96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/fragments/selectField.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
8 | 9 | 10 |
11 | 15 | 18 | 19 | 22 | Error 23 | 24 |
25 |
26 |
27 |
28 | 29 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/owners/createOrUpdateOwnerForm.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 |

Owner

7 |
8 |
9 | 11 | 13 | 15 | 17 | 19 |
20 |
21 |
22 | 26 |
27 |
28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/owners/findOwners.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 |

Find Owners

7 | 8 |
10 |
11 |
12 | 13 |
14 |
17 |

Error

18 |
19 |
20 |
21 |
22 |
23 |
24 | 26 |
27 |
28 | 29 |
30 | 31 |
32 | Add Owner 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/owners/ownerDetails.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 |

Owner Information

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
Name
Address
City
Telephone
30 | 31 | Edit 32 | Owner 33 | Add 34 | New Pet 35 | 36 |
37 |
38 |
39 |

Pets and Visits

40 | 41 | 42 | 43 | 44 | 55 | 77 | 78 | 79 |
45 |
46 |
Name
47 |
48 |
Birth Date
49 |
51 |
Type
52 |
53 |
54 |
56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 71 | 74 | 75 |
Visit DateDescription
Edit 70 | PetAdd 73 | Visit
76 |
80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/owners/ownersList.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Owners

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 28 | 29 | 30 |
NameAddressCityTelephonePets
22 | 23 | 25 | 26 | 27 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/pets/createOrUpdatePetForm.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 |

7 | New 8 | Pet 9 |

10 |
11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 |
19 | 21 | 23 | 25 |
26 |
27 |
28 | 32 |
33 |
34 |
35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/pets/createOrUpdateVisitForm.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 |

7 | New 8 | Visit 9 |

10 | 11 | Pet 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 28 | 29 |
NameBirth DateTypeOwner
30 | 31 |
32 |
33 | 35 | 37 |
38 | 39 |
40 |
41 | 42 | 43 |
44 |
45 |
46 | 47 |
48 | Previous Visits 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
DateDescription
59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/vets/vetList.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 |

Veterinarians

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 |
NameSpecialties
none
26 | 27 | 28 | -------------------------------------------------------------------------------- /petclinic/src/main/resources/templates/welcome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Welcome

8 |
9 |
10 | 11 |
12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /petclinic/src/main/wro/wro.properties: -------------------------------------------------------------------------------- 1 | #List of preProcessors 2 | preProcessors=lessCssImport 3 | #List of postProcessors 4 | postProcessors=less4j -------------------------------------------------------------------------------- /petclinic/src/main/wro/wro.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | classpath:META-INF/resources/webjars/bootstrap/3.3.6/less/bootstrap.less 4 | /petclinic.less 5 | 6 | 7 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/PetclinicIntegrationTests.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.junit.jupiter.api.Test; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.boot.test.context.SpringBootTest; 22 | import org.springframework.samples.petclinic.vet.VetRepository; 23 | 24 | @SpringBootTest 25 | class PetclinicIntegrationTests { 26 | 27 | @Autowired 28 | private VetRepository vets; 29 | 30 | @Test 31 | void testFindAll() throws Exception { 32 | vets.findAll(); 33 | vets.findAll(); // served from cache 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.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.model; 18 | 19 | import java.util.Locale; 20 | import java.util.Set; 21 | 22 | import javax.validation.ConstraintViolation; 23 | import javax.validation.Validator; 24 | 25 | import org.junit.jupiter.api.Test; 26 | import org.springframework.context.i18n.LocaleContextHolder; 27 | import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | 31 | /** 32 | * @author Michael Isvy Simple test to make sure that Bean Validation is working (useful 33 | * when upgrading to a new version of Hibernate Validator/ Bean Validation) 34 | */ 35 | class ValidatorTests { 36 | 37 | private Validator createValidator() { 38 | LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean(); 39 | localValidatorFactoryBean.afterPropertiesSet(); 40 | return localValidatorFactoryBean; 41 | } 42 | 43 | @Test 44 | void shouldNotValidateWhenFirstNameEmpty() { 45 | 46 | LocaleContextHolder.setLocale(Locale.ENGLISH); 47 | Person person = new Person(); 48 | person.setFirstName(""); 49 | person.setLastName("smith"); 50 | 51 | Validator validator = createValidator(); 52 | Set> constraintViolations = validator.validate(person); 53 | 54 | assertThat(constraintViolations).hasSize(1); 55 | ConstraintViolation violation = constraintViolations.iterator().next(); 56 | assertThat(violation.getPropertyPath().toString()).isEqualTo("firstName"); 57 | assertThat(violation.getMessage()).isEqualTo("must not be empty"); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/owner/PetControllerTests.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.owner; 18 | 19 | import static org.mockito.BDDMockito.given; 20 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 21 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 22 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 23 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 24 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 25 | 26 | import org.assertj.core.util.Lists; 27 | import org.junit.jupiter.api.BeforeEach; 28 | import org.junit.jupiter.api.Test; 29 | import org.springframework.beans.factory.annotation.Autowired; 30 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 31 | import org.springframework.boot.test.mock.mockito.MockBean; 32 | import org.springframework.context.annotation.ComponentScan; 33 | import org.springframework.context.annotation.FilterType; 34 | import org.springframework.test.web.servlet.MockMvc; 35 | 36 | /** 37 | * Test class for the {@link PetController} 38 | * 39 | * @author Colin But 40 | */ 41 | @WebMvcTest(value = PetController.class, 42 | includeFilters = @ComponentScan.Filter(value = PetTypeFormatter.class, type = FilterType.ASSIGNABLE_TYPE)) 43 | class PetControllerTests { 44 | 45 | private static final int TEST_OWNER_ID = 1; 46 | 47 | private static final int TEST_PET_ID = 1; 48 | 49 | @Autowired 50 | private MockMvc mockMvc; 51 | 52 | @MockBean 53 | private PetRepository pets; 54 | 55 | @MockBean 56 | private OwnerRepository owners; 57 | 58 | @BeforeEach 59 | void setup() { 60 | PetType cat = new PetType(); 61 | cat.setId(3); 62 | cat.setName("hamster"); 63 | given(this.pets.findPetTypes()).willReturn(Lists.newArrayList(cat)); 64 | given(this.owners.findById(TEST_OWNER_ID)).willReturn(new Owner()); 65 | given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet()); 66 | 67 | } 68 | 69 | @Test 70 | void testInitCreationForm() throws Exception { 71 | mockMvc.perform(get("/owners/{ownerId}/pets/new", TEST_OWNER_ID)).andExpect(status().isOk()) 72 | .andExpect(view().name("pets/createOrUpdatePetForm")).andExpect(model().attributeExists("pet")); 73 | } 74 | 75 | @Test 76 | void testProcessCreationFormSuccess() throws Exception { 77 | mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID).param("name", "Betty") 78 | .param("type", "hamster").param("birthDate", "2015-02-12")).andExpect(status().is3xxRedirection()) 79 | .andExpect(view().name("redirect:/owners/{ownerId}")); 80 | } 81 | 82 | @Test 83 | void testProcessCreationFormHasErrors() throws Exception { 84 | mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID).param("name", "Betty").param("birthDate", 85 | "2015-02-12")).andExpect(model().attributeHasNoErrors("owner")) 86 | .andExpect(model().attributeHasErrors("pet")).andExpect(model().attributeHasFieldErrors("pet", "type")) 87 | .andExpect(model().attributeHasFieldErrorCode("pet", "type", "required")).andExpect(status().isOk()) 88 | .andExpect(view().name("pets/createOrUpdatePetForm")); 89 | } 90 | 91 | @Test 92 | void testInitUpdateForm() throws Exception { 93 | mockMvc.perform(get("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID)) 94 | .andExpect(status().isOk()).andExpect(model().attributeExists("pet")) 95 | .andExpect(view().name("pets/createOrUpdatePetForm")); 96 | } 97 | 98 | @Test 99 | void testProcessUpdateFormSuccess() throws Exception { 100 | mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID).param("name", "Betty") 101 | .param("type", "hamster").param("birthDate", "2015-02-12")).andExpect(status().is3xxRedirection()) 102 | .andExpect(view().name("redirect:/owners/{ownerId}")); 103 | } 104 | 105 | @Test 106 | void testProcessUpdateFormHasErrors() throws Exception { 107 | mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID).param("name", "Betty") 108 | .param("birthDate", "2015/02/12")).andExpect(model().attributeHasNoErrors("owner")) 109 | .andExpect(model().attributeHasErrors("pet")).andExpect(status().isOk()) 110 | .andExpect(view().name("pets/createOrUpdatePetForm")); 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/owner/PetTypeFormatterTests.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.owner; 18 | 19 | import java.text.ParseException; 20 | import java.util.ArrayList; 21 | import java.util.Collection; 22 | import java.util.List; 23 | import java.util.Locale; 24 | 25 | import org.junit.jupiter.api.Assertions; 26 | import org.junit.jupiter.api.BeforeEach; 27 | import org.junit.jupiter.api.Test; 28 | import org.junit.jupiter.api.extension.ExtendWith; 29 | import org.mockito.Mock; 30 | import org.mockito.junit.jupiter.MockitoExtension; 31 | 32 | import static org.assertj.core.api.Assertions.assertThat; 33 | import static org.mockito.BDDMockito.given; 34 | 35 | /** 36 | * Test class for {@link PetTypeFormatter} 37 | * 38 | * @author Colin But 39 | */ 40 | @ExtendWith(MockitoExtension.class) 41 | class PetTypeFormatterTests { 42 | 43 | @Mock 44 | private PetRepository pets; 45 | 46 | private PetTypeFormatter petTypeFormatter; 47 | 48 | @BeforeEach 49 | void setup() { 50 | this.petTypeFormatter = new PetTypeFormatter(pets); 51 | } 52 | 53 | @Test 54 | void testPrint() { 55 | PetType petType = new PetType(); 56 | petType.setName("Hamster"); 57 | String petTypeName = this.petTypeFormatter.print(petType, Locale.ENGLISH); 58 | assertThat(petTypeName).isEqualTo("Hamster"); 59 | } 60 | 61 | @Test 62 | void shouldParse() throws ParseException { 63 | given(this.pets.findPetTypes()).willReturn(makePetTypes()); 64 | PetType petType = petTypeFormatter.parse("Bird", Locale.ENGLISH); 65 | assertThat(petType.getName()).isEqualTo("Bird"); 66 | } 67 | 68 | @Test 69 | void shouldThrowParseException() throws ParseException { 70 | given(this.pets.findPetTypes()).willReturn(makePetTypes()); 71 | Assertions.assertThrows(ParseException.class, () -> { 72 | petTypeFormatter.parse("Fish", Locale.ENGLISH); 73 | }); 74 | } 75 | 76 | /** 77 | * Helper method to produce some sample pet types just for test purpose 78 | * @return {@link Collection} of {@link PetType} 79 | */ 80 | private List makePetTypes() { 81 | List petTypes = new ArrayList<>(); 82 | petTypes.add(new PetType() { 83 | { 84 | setName("Dog"); 85 | } 86 | }); 87 | petTypes.add(new PetType() { 88 | { 89 | setName("Bird"); 90 | } 91 | }); 92 | return petTypes; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/owner/VisitControllerTests.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.owner; 18 | 19 | import static org.mockito.BDDMockito.given; 20 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 21 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 22 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 23 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 24 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 25 | 26 | import org.junit.jupiter.api.BeforeEach; 27 | import org.junit.jupiter.api.Test; 28 | import org.springframework.beans.factory.annotation.Autowired; 29 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 30 | import org.springframework.boot.test.mock.mockito.MockBean; 31 | import org.springframework.samples.petclinic.visit.VisitRepository; 32 | import org.springframework.test.web.servlet.MockMvc; 33 | 34 | /** 35 | * Test class for {@link VisitController} 36 | * 37 | * @author Colin But 38 | */ 39 | @WebMvcTest(VisitController.class) 40 | class VisitControllerTests { 41 | 42 | private static final int TEST_PET_ID = 1; 43 | 44 | @Autowired 45 | private MockMvc mockMvc; 46 | 47 | @MockBean 48 | private VisitRepository visits; 49 | 50 | @MockBean 51 | private PetRepository pets; 52 | 53 | @BeforeEach 54 | void init() { 55 | given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet()); 56 | } 57 | 58 | @Test 59 | void testInitNewVisitForm() throws Exception { 60 | mockMvc.perform(get("/owners/*/pets/{petId}/visits/new", TEST_PET_ID)).andExpect(status().isOk()) 61 | .andExpect(view().name("pets/createOrUpdateVisitForm")); 62 | } 63 | 64 | @Test 65 | void testProcessNewVisitFormSuccess() throws Exception { 66 | mockMvc.perform(post("/owners/*/pets/{petId}/visits/new", TEST_PET_ID).param("name", "George") 67 | .param("description", "Visit Description")).andExpect(status().is3xxRedirection()) 68 | .andExpect(view().name("redirect:/owners/{ownerId}")); 69 | } 70 | 71 | @Test 72 | void testProcessNewVisitFormHasErrors() throws Exception { 73 | mockMvc.perform(post("/owners/*/pets/{petId}/visits/new", TEST_PET_ID).param("name", "George")) 74 | .andExpect(model().attributeHasErrors("visit")).andExpect(status().isOk()) 75 | .andExpect(view().name("pets/createOrUpdateVisitForm")); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/service/EntityUtils.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.service; 18 | 19 | import java.util.Collection; 20 | 21 | import org.springframework.orm.ObjectRetrievalFailureException; 22 | import org.springframework.samples.petclinic.model.BaseEntity; 23 | 24 | /** 25 | * Utility methods for handling entities. Separate from the BaseEntity class mainly 26 | * because of dependency on the ORM-associated ObjectRetrievalFailureException. 27 | * 28 | * @author Juergen Hoeller 29 | * @author Sam Brannen 30 | * @see org.springframework.samples.petclinic.model.BaseEntity 31 | * @since 29.10.2003 32 | */ 33 | public abstract class EntityUtils { 34 | 35 | /** 36 | * Look up the entity of the given class with the given id in the given collection. 37 | * @param entities the collection to search 38 | * @param entityClass the entity class to look up 39 | * @param entityId the entity id to look up 40 | * @return the found entity 41 | * @throws ObjectRetrievalFailureException if the entity was not found 42 | */ 43 | public static T getById(Collection entities, Class entityClass, int entityId) 44 | throws ObjectRetrievalFailureException { 45 | for (T entity : entities) { 46 | if (entity.getId() == entityId && entityClass.isInstance(entity)) { 47 | return entity; 48 | } 49 | } 50 | throw new ObjectRetrievalFailureException(entityClass, entityId); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/system/CrashControllerTests.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 org.junit.jupiter.api.Disabled; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 23 | import org.springframework.test.web.servlet.MockMvc; 24 | 25 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 26 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; 27 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 28 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 29 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 30 | 31 | /** 32 | * Test class for {@link CrashController} 33 | * 34 | * @author Colin But 35 | */ 36 | // Waiting https://github.com/spring-projects/spring-boot/issues/5574 37 | @Disabled 38 | @WebMvcTest(controllers = CrashController.class) 39 | class CrashControllerTests { 40 | 41 | @Autowired 42 | private MockMvc mockMvc; 43 | 44 | @Test 45 | void testTriggerException() throws Exception { 46 | mockMvc.perform(get("/oups")).andExpect(view().name("exception")) 47 | .andExpect(model().attributeExists("exception")).andExpect(forwardedUrl("exception")) 48 | .andExpect(status().isOk()); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/vet/VetControllerTests.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.vet; 18 | 19 | import static org.mockito.BDDMockito.given; 20 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 21 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; 22 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 23 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 24 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 25 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 26 | 27 | import org.assertj.core.util.Lists; 28 | import org.junit.jupiter.api.BeforeEach; 29 | import org.junit.jupiter.api.Test; 30 | import org.springframework.beans.factory.annotation.Autowired; 31 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 32 | import org.springframework.boot.test.mock.mockito.MockBean; 33 | import org.springframework.http.MediaType; 34 | import org.springframework.test.web.servlet.MockMvc; 35 | import org.springframework.test.web.servlet.ResultActions; 36 | 37 | /** 38 | * Test class for the {@link VetController} 39 | */ 40 | @WebMvcTest(VetController.class) 41 | class VetControllerTests { 42 | 43 | @Autowired 44 | private MockMvc mockMvc; 45 | 46 | @MockBean 47 | private VetRepository vets; 48 | 49 | @BeforeEach 50 | void setup() { 51 | Vet james = new Vet(); 52 | james.setFirstName("James"); 53 | james.setLastName("Carter"); 54 | james.setId(1); 55 | Vet helen = new Vet(); 56 | helen.setFirstName("Helen"); 57 | helen.setLastName("Leary"); 58 | helen.setId(2); 59 | Specialty radiology = new Specialty(); 60 | radiology.setId(1); 61 | radiology.setName("radiology"); 62 | helen.addSpecialty(radiology); 63 | given(this.vets.findAll()).willReturn(Lists.newArrayList(james, helen)); 64 | } 65 | 66 | @Test 67 | void testShowVetListHtml() throws Exception { 68 | mockMvc.perform(get("/vets.html")).andExpect(status().isOk()).andExpect(model().attributeExists("vets")) 69 | .andExpect(view().name("vets/vetList")); 70 | } 71 | 72 | @Test 73 | void testShowResourcesVetList() throws Exception { 74 | ResultActions actions = mockMvc.perform(get("/vets").accept(MediaType.APPLICATION_JSON)) 75 | .andExpect(status().isOk()); 76 | actions.andExpect(content().contentType(MediaType.APPLICATION_JSON)) 77 | .andExpect(jsonPath("$.vetList[0].id").value(1)); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /petclinic/src/test/java/org/springframework/samples/petclinic/vet/VetTests.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.vet; 17 | 18 | import org.junit.jupiter.api.Test; 19 | import org.springframework.util.SerializationUtils; 20 | 21 | import static org.assertj.core.api.Assertions.assertThat; 22 | 23 | /** 24 | * @author Dave Syer 25 | */ 26 | class VetTests { 27 | 28 | @Test 29 | void testSerialization() { 30 | Vet vet = new Vet(); 31 | vet.setFirstName("Zaphod"); 32 | vet.setLastName("Beeblebrox"); 33 | vet.setId(123); 34 | Vet other = (Vet) SerializationUtils.deserialize(SerializationUtils.serialize(vet)); 35 | assertThat(other.getFirstName()).isEqualTo(vet.getFirstName()); 36 | assertThat(other.getLastName()).isEqualTo(vet.getLastName()); 37 | assertThat(other.getId()).isEqualTo(vet.getId()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Click==7.0 2 | jinja2=2.11.3 3 | livereload==2.6.1 4 | Markdown==3.1 5 | MarkupSafe==1.1.1 6 | material==0.1 7 | mkdocs==1.0.4 8 | mkdocs-material==4.2.0 9 | Pygments==2.7.4 10 | pymdown-extensions==6.0 11 | PyYAML==5.4 12 | six==1.12.0 13 | tornado==6.0.2 14 | -------------------------------------------------------------------------------- /site/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/assets/images/favicon.png -------------------------------------------------------------------------------- /site/assets/javascripts/lunr/min/lunr.da.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lunr languages, `Danish` language 3 | * https://github.com/MihaiValentin/lunr-languages 4 | * 5 | * Copyright 2014, Mihai Valentin 6 | * http://www.mozilla.org/MPL/ 7 | */ 8 | /*! 9 | * based on 10 | * Snowball JavaScript Library v0.3 11 | * http://code.google.com/p/urim/ 12 | * http://snowball.tartarus.org/ 13 | * 14 | * Copyright 2010, Oleg Mazko 15 | * http://www.mozilla.org/MPL/ 16 | */ 17 | 18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){var e,r=f.cursor+3;if(d=f.limit,0<=r&&r<=f.limit){for(a=r;;){if(e=f.cursor,f.in_grouping(w,97,248)){f.cursor=e;break}if(f.cursor=e,e>=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); -------------------------------------------------------------------------------- /site/assets/javascripts/lunr/min/lunr.ja.min.js: -------------------------------------------------------------------------------- 1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); -------------------------------------------------------------------------------- /site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js: -------------------------------------------------------------------------------- 1 | !function(r,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(r.lunr)}(this,function(){return function(r){r.stemmerSupport={Among:function(r,t,i,s){if(this.toCharArray=function(r){for(var t=r.length,i=new Array(t),s=0;s=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursors||e>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor>1),f=0,l=o0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); -------------------------------------------------------------------------------- /site/assets/javascripts/lunr/min/lunr.sv.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lunr languages, `Swedish` language 3 | * https://github.com/MihaiValentin/lunr-languages 4 | * 5 | * Copyright 2014, Mihai Valentin 6 | * http://www.mozilla.org/MPL/ 7 | */ 8 | /*! 9 | * based on 10 | * Snowball JavaScript Library v0.3 11 | * http://code.google.com/p/urim/ 12 | * http://snowball.tartarus.org/ 13 | * 14 | * Copyright 2010, Oleg Mazko 15 | * http://www.mozilla.org/MPL/ 16 | */ 17 | 18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); -------------------------------------------------------------------------------- /site/assets/javascripts/lunr/min/lunr.vi.min.js: -------------------------------------------------------------------------------- 1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}}); -------------------------------------------------------------------------------- /site/images/Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/images/Architecture.png -------------------------------------------------------------------------------- /site/images/Cloud9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/images/Cloud9.png -------------------------------------------------------------------------------- /site/images/Fargate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/images/Fargate.png -------------------------------------------------------------------------------- /site/images/c9attachrole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/images/c9attachrole.png -------------------------------------------------------------------------------- /site/images/c9disableiam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/images/c9disableiam.png -------------------------------------------------------------------------------- /site/images/c9instancerole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/images/c9instancerole.png -------------------------------------------------------------------------------- /site/images/createrole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/images/createrole.png -------------------------------------------------------------------------------- /site/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | None 4 | 2020-11-18 5 | daily 6 | 7 | None 8 | 2020-11-18 9 | daily 10 | 11 | None 12 | 2020-11-18 13 | daily 14 | 15 | None 16 | 2020-11-18 17 | daily 18 | 19 | None 20 | 2020-11-18 21 | daily 22 | 23 | None 24 | 2020-11-18 25 | daily 26 | 27 | -------------------------------------------------------------------------------- /site/sitemap.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-ecs-cicd-terraform/dece8217e51bdae5f5f5a39399edac46cdda3207/site/sitemap.xml.gz -------------------------------------------------------------------------------- /terraform/alb.tf: -------------------------------------------------------------------------------- 1 | 2 | # --------------------------------------------------------------------------------------------------------------------- 3 | # ALB 4 | # --------------------------------------------------------------------------------------------------------------------- 5 | 6 | resource "aws_alb" "alb" { 7 | name = "${var.stack}-alb" 8 | # subnets = "${aws_subnet.public.*.id}" 9 | subnets = aws_subnet.public.*.id 10 | # security_groups = ["${aws_security_group.alb-sg.id}"] 11 | security_groups = [aws_security_group.alb-sg.id] 12 | } 13 | 14 | # --------------------------------------------------------------------------------------------------------------------- 15 | # ALB TARGET GROUP 16 | # --------------------------------------------------------------------------------------------------------------------- 17 | 18 | resource "aws_alb_target_group" "trgp" { 19 | name = "${var.stack}-tgrp" 20 | port = 8080 21 | protocol = "HTTP" 22 | vpc_id = aws_vpc.main.id 23 | target_type = "ip" 24 | } 25 | 26 | # --------------------------------------------------------------------------------------------------------------------- 27 | # ALB LISTENER 28 | # --------------------------------------------------------------------------------------------------------------------- 29 | 30 | resource "aws_alb_listener" "alb-listener" { 31 | load_balancer_arn = aws_alb.alb.id 32 | port = "80" 33 | protocol = "HTTP" 34 | 35 | default_action { 36 | target_group_arn = aws_alb_target_group.trgp.id 37 | type = "forward" 38 | } 39 | } 40 | 41 | output "alb_address" { 42 | value = aws_alb.alb.dns_name 43 | } -------------------------------------------------------------------------------- /terraform/codebuild.tf: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------------------------------------- 2 | # Code Build 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | 5 | data "aws_caller_identity" "current" {} 6 | 7 | # Codebuild role 8 | 9 | resource "aws_iam_role" "codebuild_role" { 10 | assume_role_policy = < imagedefinitions.json 140 | artifacts: 141 | files: imagedefinitions.json 142 | BUILDSPEC 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /terraform/codecommit.tf: -------------------------------------------------------------------------------- 1 | 2 | # --------------------------------------------------------------------------------------------------------------------- 3 | # Code Commit 4 | # --------------------------------------------------------------------------------------------------------------------- 5 | 6 | # Code Commit repo 7 | 8 | resource "aws_codecommit_repository" "source_repo" { 9 | repository_name = var.source_repo_name 10 | description = "This is the app source repository" 11 | } 12 | 13 | 14 | # Trigger role and event rule to trigger pipeline 15 | 16 | resource "aws_iam_role" "trigger_role" { 17 | assume_role_policy = <