├── .editorconfig ├── .gitignore ├── .gitpod.yml ├── .idea ├── .gitignore ├── compiler.xml ├── encodings.xml ├── jarRepositories.xml ├── jpa-buddy.xml ├── misc.xml ├── runConfigurations │ └── PetClinicApplication.xml └── vcs.xml ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .travis.yml ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── mvnw ├── mvnw.cmd ├── pom.xml ├── push-to-pws └── button.yml ├── readme.md └── src ├── 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 │ │ ├── hsqldb │ │ │ ├── data.sql │ │ │ └── schema.sql │ │ └── mysql │ │ │ ├── data.sql │ │ │ ├── petclinic_db_setup_mysql.txt │ │ │ └── schema.sql │ ├── messages │ │ ├── messages.properties │ │ ├── messages_de.properties │ │ └── messages_en.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 /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = space 9 | 10 | [*.{java,xml}] 11 | indent_size = 4 12 | trim_trailing_whitespace = true 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/* 2 | .settings/* 3 | .classpath 4 | .project 5 | .factorypath 6 | .attach_pid* 7 | /target 8 | .sts4-cache/ 9 | _site/ 10 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: gitpod/workspace-full 2 | 3 | tasks: 4 | - init: ./mvnw clean install -U -DskipTests 5 | command: ./mvnw spring-boot:run 6 | name: Run PetClinic app 7 | 8 | ports: 9 | - port: 8080 10 | onOpen: open-preview 11 | 12 | vscode: 13 | extensions: 14 | - pivotal.vscode-spring-boot 15 | - vscjava.vscode-java-pack 16 | 17 | jetbrains: 18 | intellij: 19 | plugins: 20 | - com.haulmont.jpab 21 | prebuilds: 22 | version: both 23 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | -------------------------------------------------------------------------------- /.idea/jpa-buddy.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 | 15 | -------------------------------------------------------------------------------- /.idea/runConfigurations/PetClinicApplication.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present 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 | * http://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 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.4"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + " .jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: java 3 | jdk: oraclejdk8 4 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "java", 9 | "name": "Debug (Launch)-PetClinicApplication", 10 | "request": "launch", 11 | "cwd": "${workspaceFolder}", 12 | "console": "internalConsole", 13 | "stopOnEntry": false, 14 | "mainClass": "org.springframework.samples.petclinic.PetClinicApplication", 15 | "projectName": "spring-petclinic", 16 | "args": "" 17 | }, 18 | { 19 | "type": "java", 20 | "name": "Debug (Attach)", 21 | "request": "attach", 22 | "hostName": "localhost", 23 | "port": 0 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "interactive", 3 | "files.exclude": { 4 | "**/.classpath": true, 5 | "**/.project": true, 6 | "**/.settings": true, 7 | "**/.factorypath": true 8 | } 9 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "verify", 8 | "type": "shell", 9 | "command": "mvn -B verify", 10 | "group": "build" 11 | }, 12 | { 13 | "label": "test", 14 | "type": "shell", 15 | "command": "mvn -B test", 16 | "group": "test" 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | org.springframework.samples 7 | spring-petclinic 8 | 2.1.0.BUILD-SNAPSHOT 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 2.1.6.RELEASE 14 | 15 | petclinic 16 | 17 | 18 | 19 | 20 | 1.8 21 | UTF-8 22 | UTF-8 23 | 24 | 25 | 3.3.6 26 | 1.11.4 27 | 2.2.4 28 | 1.8.0 29 | 30 | 0.8.2 31 | 32 | 11 33 | 11 34 | 35 | 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-actuator 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-cache 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-data-jpa 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-web 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-thymeleaf 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-starter-test 62 | test 63 | 64 | 65 | 66 | 67 | org.hsqldb 68 | hsqldb 69 | runtime 70 | 71 | 72 | mysql 73 | mysql-connector-java 74 | runtime 75 | 76 | 77 | 78 | 79 | javax.cache 80 | cache-api 81 | 82 | 83 | org.ehcache 84 | ehcache 85 | 86 | 87 | 88 | 89 | org.webjars 90 | webjars-locator-core 91 | 92 | 93 | org.webjars 94 | jquery 95 | ${webjars-jquery.version} 96 | 97 | 98 | org.webjars 99 | jquery-ui 100 | ${webjars-jquery-ui.version} 101 | 102 | 103 | org.webjars 104 | bootstrap 105 | ${webjars-bootstrap.version} 106 | 107 | 108 | 109 | 110 | org.springframework.boot 111 | spring-boot-devtools 112 | true 113 | 114 | 115 | 116 | 117 | 118 | 119 | org.springframework.boot 120 | spring-boot-maven-plugin 121 | 122 | 123 | 125 | 126 | build-info 127 | 128 | 129 | 130 | ${project.build.sourceEncoding} 131 | ${project.reporting.outputEncoding} 132 | ${maven.compiler.source} 133 | ${maven.compiler.target} 134 | 135 | 136 | 137 | 138 | 139 | 140 | org.jacoco 141 | jacoco-maven-plugin 142 | ${jacoco.version} 143 | 144 | 145 | 146 | prepare-agent 147 | 148 | 149 | 150 | report 151 | prepare-package 152 | 153 | report 154 | 155 | 156 | 157 | 158 | 159 | 161 | 162 | pl.project13.maven 163 | git-commit-id-plugin 164 | 165 | 166 | 167 | revision 168 | 169 | 170 | 171 | 172 | true 173 | yyyy-MM-dd'T'HH:mm:ssZ 174 | true 175 | ${project.build.outputDirectory}/git.properties 176 | 177 | false 178 | 179 | 180 | 181 | 182 | ro.isdc.wro4j 183 | wro4j-maven-plugin 184 | ${wro4j.version} 185 | 186 | 187 | generate-resources 188 | 189 | run 190 | 191 | 192 | 193 | 194 | ro.isdc.wro.maven.plugin.manager.factory.ConfigurableWroManagerFactory 195 | ${project.build.directory}/classes/static/resources/css 196 | ${basedir}/src/main/wro/wro.xml 197 | ${basedir}/src/main/wro/wro.properties 198 | ${basedir}/src/main/less 199 | 200 | 201 | 202 | org.webjars 203 | bootstrap 204 | ${webjars-bootstrap.version} 205 | 206 | 207 | org.mockito 208 | mockito-core 209 | ${mockito.version} 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | Apache License, Version 2.0 220 | https://www.apache.org/licenses/LICENSE-2.0 221 | 222 | 223 | 224 | 225 | 226 | spring-snapshots 227 | Spring Snapshots 228 | https://repo.spring.io/snapshot 229 | 230 | true 231 | 232 | 233 | 234 | spring-milestones 235 | Spring Milestones 236 | https://repo.spring.io/milestone 237 | 238 | false 239 | 240 | 241 | 242 | 243 | 244 | 245 | spring-snapshots 246 | Spring Snapshots 247 | https://repo.spring.io/snapshot 248 | 249 | true 250 | 251 | 252 | 253 | spring-milestones 254 | Spring Milestones 255 | https://repo.spring.io/milestone 256 | 257 | false 258 | 259 | 260 | 261 | 262 | 263 | -------------------------------------------------------------------------------- /push-to-pws/button.yml: -------------------------------------------------------------------------------- 1 | repo: https://github.com/spring-projects/spring-petclinic.git 2 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Spring PetClinic Sample application [![setup automated](https://img.shields.io/badge/Gitpod-ready_to_code-orange?logo=gitpod)](https://gitpod.io/#https://github.com/gitpod-io/spring-petclinic) 2 | 3 | [Petclinic](https://github.com/spring-projects/spring-petclinic) is a [Spring Boot](https://spring.io/guides/gs/spring-boot/) application built using [Maven](https://spring.io/guides/gs/maven/). 4 | 5 | ## Table of Contents 6 | 7 | - [Run petclinic on Gitpod](#run-petclinic-on-gitpod) 8 | - [Get Started With Your Own Project](#get-started-with-your-own-project) 9 | - [Community support](#community-support) 10 | 11 | ## Run petclinic on Gitpod 12 | 13 | Start coding in a [ready-to-code, cloud development environment](https://www.gitpod.io) 14 | 15 | Setup Gitpod integration with Jetbrains Gateway using the instructions given in this [doc](https://www.gitpod.io/docs/ides-and-editors/intellij). 16 | 17 | Click the button below to start a new workspace on Gitpod which will automatically open the workspace in IntelliJ IDEA through JetBrains Gateway. 18 | 19 | 20 | 21 | Push 22 | 23 | 24 | 25 | Or you can run it from Maven directly using the Spring Boot Maven plugin. If you do this it will pick up changes that you make in the project immediately (changes to Java source files require a compile as well - most people use an IDE for this): 26 | 27 | ``` 28 | ./mvnw spring-boot:run 29 | ``` 30 | 31 | ## Get Started With Your Own Project 32 | 33 | To get started with Spring Boot on Gitpod, add a [`.gitpod.yml`](./.gitpod.yml) file which contains the configuration to improve the developer experience on Gitpod. To learn more, please see the [Getting Started](https://www.gitpod.io/docs/getting-started) documentation. 34 | 35 | ## Community Support 36 | 37 | For any help refer to [Gitpod documentation](https://gitpod.io/workspaces). If you have any additonal questions, you can use one of these channels: 38 | 39 | [![Discord](https://img.shields.io/discord/816244985187008514?color=7289da&logo=Discord&style=for-the-badge)](https://discord.com/channels/816244985187008514/903225840660279296) 40 | 41 | [![GitHub issues](https://img.shields.io/github/issues/gitpod-io/template-java-spring-boot-gradle?logo=Github&style=for-the-badge)](https://github.com/gitpod-io/spring-petclinic/issues) 42 | 43 | [![Twitter Follow](https://img.shields.io/twitter/follow/gitpod?label=Gitpod&logo=twitter&style=for-the-badge)](https://twitter.com/gitpod) 44 | -------------------------------------------------------------------------------- /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 29 | public class PetClinicApplication { 30 | 31 | public static void main(String[] args) { 32 | SpringApplication.run(PetClinicApplication.class, args); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /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 | @Id 35 | @GeneratedValue(strategy = GenerationType.IDENTITY) 36 | private Integer id; 37 | 38 | public Integer getId() { 39 | return id; 40 | } 41 | 42 | public void setId(Integer id) { 43 | this.id = id; 44 | } 45 | 46 | public boolean isNew() { 47 | return this.id == null; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /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 | /** 23 | * Simple JavaBean domain object adds a name property to BaseEntity. Used as a base class for objects 24 | * needing these properties. 25 | * 26 | * @author Ken Krebs 27 | * @author Juergen Hoeller 28 | */ 29 | @MappedSuperclass 30 | public class NamedEntity extends BaseEntity { 31 | 32 | @Column(name = "name") 33 | private String name; 34 | 35 | public String getName() { 36 | return this.name; 37 | } 38 | 39 | public void setName(String name) { 40 | this.name = name; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return this.getName(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 22 | -------------------------------------------------------------------------------- /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 | @Column(name = "address") 49 | @NotEmpty 50 | private String address; 51 | 52 | @Column(name = "city") 53 | @NotEmpty 54 | private String city; 55 | 56 | @Column(name = "telephone") 57 | @NotEmpty 58 | @Digits(fraction = 0, integer = 10) 59 | private String telephone; 60 | 61 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner") 62 | private Set pets; 63 | 64 | public String getAddress() { 65 | return this.address; 66 | } 67 | 68 | public void setAddress(String address) { 69 | this.address = address; 70 | } 71 | 72 | public String getCity() { 73 | return this.city; 74 | } 75 | 76 | public void setCity(String city) { 77 | this.city = city; 78 | } 79 | 80 | public String getTelephone() { 81 | return this.telephone; 82 | } 83 | 84 | public void setTelephone(String telephone) { 85 | this.telephone = telephone; 86 | } 87 | 88 | protected Set getPetsInternal() { 89 | if (this.pets == null) { 90 | this.pets = new HashSet<>(); 91 | } 92 | return this.pets; 93 | } 94 | 95 | protected void setPetsInternal(Set pets) { 96 | this.pets = pets; 97 | } 98 | 99 | public List getPets() { 100 | List sortedPets = new ArrayList<>(getPetsInternal()); 101 | PropertyComparator.sort(sortedPets, 102 | 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 | * 116 | * @param name to test 117 | * @return true if pet name is already in use 118 | */ 119 | public Pet getPet(String name) { 120 | return getPet(name, false); 121 | } 122 | 123 | /** 124 | * Return the Pet with the given name, or null if none found for this Owner. 125 | * 126 | * @param name to test 127 | * @return true if pet name is already in use 128 | */ 129 | public Pet getPet(String name, boolean ignoreNew) { 130 | name = name.toLowerCase(); 131 | for (Pet pet : getPetsInternal()) { 132 | if (!ignoreNew || !pet.isNew()) { 133 | String compName = pet.getName(); 134 | compName = compName.toLowerCase(); 135 | if (compName.equals(name)) { 136 | return pet; 137 | } 138 | } 139 | } 140 | return null; 141 | } 142 | 143 | @Override 144 | public String toString() { 145 | return new ToStringCreator(this) 146 | 147 | .append("id", this.getId()).append("new", this.isNew()) 148 | .append("lastName", this.getLastName()) 149 | .append("firstName", this.getFirstName()).append("address", this.address) 150 | .append("city", this.city).append("telephone", this.telephone).toString(); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /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.stereotype.Controller; 19 | import org.springframework.ui.Model; 20 | import org.springframework.validation.BindingResult; 21 | import org.springframework.web.bind.WebDataBinder; 22 | import org.springframework.web.bind.annotation.GetMapping; 23 | import org.springframework.web.bind.annotation.InitBinder; 24 | import org.springframework.web.bind.annotation.PathVariable; 25 | import org.springframework.web.bind.annotation.PostMapping; 26 | import org.springframework.web.servlet.ModelAndView; 27 | 28 | import javax.validation.Valid; 29 | import java.util.Collection; 30 | import java.util.Map; 31 | 32 | /** 33 | * @author Juergen Hoeller 34 | * @author Ken Krebs 35 | * @author Arjen Poutsma 36 | * @author Michael Isvy 37 | */ 38 | @Controller 39 | class OwnerController { 40 | 41 | private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm"; 42 | private final OwnerRepository owners; 43 | 44 | 45 | public OwnerController(OwnerRepository clinicService) { 46 | this.owners = clinicService; 47 | } 48 | 49 | @InitBinder 50 | public void setAllowedFields(WebDataBinder dataBinder) { 51 | dataBinder.setDisallowedFields("id"); 52 | } 53 | 54 | @GetMapping("/owners/new") 55 | public String initCreationForm(Map model) { 56 | Owner owner = new Owner(); 57 | model.put("owner", owner); 58 | return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; 59 | } 60 | 61 | @PostMapping("/owners/new") 62 | public String processCreationForm(@Valid Owner owner, BindingResult result) { 63 | if (result.hasErrors()) { 64 | return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; 65 | } else { 66 | this.owners.save(owner); 67 | return "redirect:/owners/" + owner.getId(); 68 | } 69 | } 70 | 71 | @GetMapping("/owners/find") 72 | public String initFindForm(Map model) { 73 | model.put("owner", new Owner()); 74 | return "owners/findOwners"; 75 | } 76 | 77 | @GetMapping("/owners") 78 | public String processFindForm(Owner owner, BindingResult result, Map model) { 79 | 80 | // allow parameterless GET request for /owners to return all records 81 | if (owner.getLastName() == null) { 82 | owner.setLastName(""); // empty string signifies broadest possible search 83 | } 84 | 85 | // find owners by last name 86 | Collection results = this.owners.findByLastName(owner.getLastName()); 87 | if (results.isEmpty()) { 88 | // no owners found 89 | result.rejectValue("lastName", "notFound", "not found"); 90 | return "owners/findOwners"; 91 | } else if (results.size() == 1) { 92 | // 1 owner found 93 | owner = results.iterator().next(); 94 | return "redirect:/owners/" + owner.getId(); 95 | } else { 96 | // multiple owners found 97 | model.put("selections", results); 98 | return "owners/ownersList"; 99 | } 100 | } 101 | 102 | @GetMapping("/owners/{ownerId}/edit") 103 | public String initUpdateOwnerForm(@PathVariable("ownerId") int ownerId, Model model) { 104 | Owner owner = this.owners.findById(ownerId); 105 | model.addAttribute(owner); 106 | return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; 107 | } 108 | 109 | @PostMapping("/owners/{ownerId}/edit") 110 | public String processUpdateOwnerForm(@Valid Owner owner, BindingResult result, @PathVariable("ownerId") int ownerId) { 111 | if (result.hasErrors()) { 112 | return VIEWS_OWNER_CREATE_OR_UPDATE_FORM; 113 | } else { 114 | owner.setId(ownerId); 115 | this.owners.save(owner); 116 | return "redirect:/owners/{ownerId}"; 117 | } 118 | } 119 | 120 | /** 121 | * Custom handler for displaying an owner. 122 | * 123 | * @param ownerId the ID of the owner to display 124 | * @return a ModelMap with the model attributes for the view 125 | */ 126 | @GetMapping("/owners/{ownerId}") 127 | public ModelAndView showOwner(@PathVariable("ownerId") int ownerId) { 128 | ModelAndView mav = new ModelAndView("owners/ownerDetails"); 129 | mav.addObject(this.owners.findById(ownerId)); 130 | return mav; 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /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 with Spring Data naming 27 | * conventions so this interface can easily be extended for Spring Data. 28 | * See: 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 OwnerRepository extends Repository { 36 | 37 | /** 38 | * Retrieve {@link Owner}s from the data store by last name, returning all owners 39 | * whose last name starts with the given name. 40 | * @param lastName Value to search for 41 | * @return a Collection of matching {@link Owner}s (or an empty Collection if none 42 | * found) 43 | */ 44 | @Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName%") 45 | @Transactional(readOnly = true) 46 | Collection findByLastName(@Param("lastName") String lastName); 47 | 48 | /** 49 | * Retrieve an {@link Owner} from the data store by id. 50 | * @param id the id to search for 51 | * @return the {@link Owner} if found 52 | */ 53 | @Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id") 54 | @Transactional(readOnly = true) 55 | Owner findById(@Param("id") Integer id); 56 | 57 | /** 58 | * Save an {@link Owner} to the data store, either inserting or updating it. 59 | * @param owner the {@link Owner} to save 60 | */ 61 | void save(Owner owner); 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /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.Collections; 21 | import java.util.HashSet; 22 | import java.util.LinkedHashSet; 23 | import java.util.List; 24 | import java.util.Set; 25 | 26 | import javax.persistence.CascadeType; 27 | import javax.persistence.Column; 28 | import javax.persistence.Entity; 29 | import javax.persistence.FetchType; 30 | import javax.persistence.JoinColumn; 31 | import javax.persistence.ManyToOne; 32 | import javax.persistence.OneToMany; 33 | import javax.persistence.Table; 34 | 35 | import org.springframework.beans.support.MutableSortDefinition; 36 | import org.springframework.beans.support.PropertyComparator; 37 | import org.springframework.format.annotation.DateTimeFormat; 38 | import org.springframework.samples.petclinic.model.NamedEntity; 39 | import org.springframework.samples.petclinic.visit.Visit; 40 | 41 | /** 42 | * Simple business object representing a pet. 43 | * 44 | * @author Ken Krebs 45 | * @author Juergen Hoeller 46 | * @author Sam Brannen 47 | */ 48 | @Entity 49 | @Table(name = "pets") 50 | public class Pet extends NamedEntity { 51 | 52 | @Column(name = "birth_date") 53 | @DateTimeFormat(pattern = "yyyy-MM-dd") 54 | private LocalDate birthDate; 55 | 56 | @ManyToOne 57 | @JoinColumn(name = "type_id") 58 | private PetType type; 59 | 60 | @ManyToOne 61 | @JoinColumn(name = "owner_id") 62 | private Owner owner; 63 | 64 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "petId", fetch = FetchType.EAGER) 65 | private Set visits = new LinkedHashSet<>(); 66 | 67 | public void setBirthDate(LocalDate birthDate) { 68 | this.birthDate = birthDate; 69 | } 70 | 71 | public LocalDate getBirthDate() { 72 | return this.birthDate; 73 | } 74 | 75 | public PetType getType() { 76 | return this.type; 77 | } 78 | 79 | public void setType(PetType type) { 80 | this.type = type; 81 | } 82 | 83 | public Owner getOwner() { 84 | return this.owner; 85 | } 86 | 87 | protected void setOwner(Owner owner) { 88 | this.owner = owner; 89 | } 90 | 91 | protected Set getVisitsInternal() { 92 | if (this.visits == null) { 93 | this.visits = new HashSet<>(); 94 | } 95 | return this.visits; 96 | } 97 | 98 | protected void setVisitsInternal(Set visits) { 99 | this.visits = visits; 100 | } 101 | 102 | public List getVisits() { 103 | List sortedVisits = new ArrayList<>(getVisitsInternal()); 104 | PropertyComparator.sort(sortedVisits, 105 | new MutableSortDefinition("date", false, false)); 106 | return Collections.unmodifiableList(sortedVisits); 107 | } 108 | 109 | public void addVisit(Visit visit) { 110 | getVisitsInternal().add(visit); 111 | visit.setPetId(this.getId()); 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /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 | private final PetRepository pets; 39 | private final OwnerRepository owners; 40 | 41 | public PetController(PetRepository pets, OwnerRepository owners) { 42 | this.pets = pets; 43 | this.owners = owners; 44 | } 45 | 46 | @ModelAttribute("types") 47 | public Collection populatePetTypes() { 48 | return this.pets.findPetTypes(); 49 | } 50 | 51 | @ModelAttribute("owner") 52 | public Owner findOwner(@PathVariable("ownerId") int ownerId) { 53 | return this.owners.findById(ownerId); 54 | } 55 | 56 | @InitBinder("owner") 57 | public void initOwnerBinder(WebDataBinder dataBinder) { 58 | dataBinder.setDisallowedFields("id"); 59 | } 60 | 61 | @InitBinder("pet") 62 | public void initPetBinder(WebDataBinder dataBinder) { 63 | dataBinder.setValidator(new PetValidator()); 64 | } 65 | 66 | @GetMapping("/pets/new") 67 | public String initCreationForm(Owner owner, ModelMap model) { 68 | Pet pet = new Pet(); 69 | owner.addPet(pet); 70 | model.put("pet", pet); 71 | return VIEWS_PETS_CREATE_OR_UPDATE_FORM; 72 | } 73 | 74 | @PostMapping("/pets/new") 75 | public String processCreationForm(Owner owner, @Valid Pet pet, BindingResult result, ModelMap model) { 76 | if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null){ 77 | result.rejectValue("name", "duplicate", "already exists"); 78 | } 79 | owner.addPet(pet); 80 | if (result.hasErrors()) { 81 | model.put("pet", pet); 82 | return VIEWS_PETS_CREATE_OR_UPDATE_FORM; 83 | } else { 84 | this.pets.save(pet); 85 | return "redirect:/owners/{ownerId}"; 86 | } 87 | } 88 | 89 | @GetMapping("/pets/{petId}/edit") 90 | public String initUpdateForm(@PathVariable("petId") int petId, ModelMap model) { 91 | Pet pet = this.pets.findById(petId); 92 | model.put("pet", pet); 93 | return VIEWS_PETS_CREATE_OR_UPDATE_FORM; 94 | } 95 | 96 | @PostMapping("/pets/{petId}/edit") 97 | public String processUpdateForm(@Valid Pet pet, BindingResult result, Owner owner, ModelMap model) { 98 | if (result.hasErrors()) { 99 | pet.setOwner(owner); 100 | model.put("pet", pet); 101 | return VIEWS_PETS_CREATE_OR_UPDATE_FORM; 102 | } else { 103 | owner.addPet(pet); 104 | this.pets.save(pet); 105 | return "redirect:/owners/{ownerId}"; 106 | } 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /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 with Spring Data naming 26 | * conventions so this interface can easily be extended for Spring Data. 27 | * See: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation 28 | * 29 | * @author Ken Krebs 30 | * @author Juergen Hoeller 31 | * @author Sam Brannen 32 | * @author Michael Isvy 33 | */ 34 | public interface PetRepository extends Repository { 35 | 36 | /** 37 | * Retrieve all {@link PetType}s from the data store. 38 | * @return a Collection of {@link PetType}s. 39 | */ 40 | @Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name") 41 | @Transactional(readOnly = true) 42 | List findPetTypes(); 43 | 44 | /** 45 | * Retrieve a {@link Pet} from the data store by id. 46 | * @param id the id to search for 47 | * @return the {@link Pet} if found 48 | */ 49 | @Transactional(readOnly = true) 50 | Pet findById(Integer id); 51 | 52 | /** 53 | * Save a {@link Pet} to the data store, either inserting or updating it. 54 | * @param pet the {@link Pet} to save 55 | */ 56 | void save(Pet pet); 57 | 58 | } 59 | 60 | -------------------------------------------------------------------------------- /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 25 | * Can be Cat, Dog, Hamster... 26 | */ 27 | @Entity 28 | @Table(name = "types") 29 | public class PetType extends NamedEntity { 30 | 31 | } 32 | -------------------------------------------------------------------------------- /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 from Spring 3.0, Formatters have 28 | * come as an improvement in comparison to legacy PropertyEditors. See the following links for more details: - The 29 | * Spring ref doc: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#format 30 | * 31 | * @author Mark Fisher 32 | * @author Juergen Hoeller 33 | * @author Michael Isvy 34 | */ 35 | @Component 36 | public class PetTypeFormatter implements Formatter { 37 | 38 | private final PetRepository pets; 39 | 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 | -------------------------------------------------------------------------------- /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 validation rule in Java. 26 | *

27 | * 28 | * @author Ken Krebs 29 | * @author Juergen Hoeller 30 | */ 31 | public class PetValidator implements Validator { 32 | 33 | private static final String REQUIRED = "required"; 34 | 35 | @Override 36 | public void validate(Object obj, Errors errors) { 37 | Pet pet = (Pet) obj; 38 | String name = pet.getName(); 39 | // name validation 40 | if (!StringUtils.hasLength(name)) { 41 | errors.rejectValue("name", REQUIRED, REQUIRED); 42 | } 43 | 44 | // type validation 45 | if (pet.isNew() && pet.getType() == null) { 46 | errors.rejectValue("type", REQUIRED, REQUIRED); 47 | } 48 | 49 | // birth date validation 50 | if (pet.getBirthDate() == null) { 51 | errors.rejectValue("birthDate", REQUIRED, REQUIRED); 52 | } 53 | } 54 | 55 | /** 56 | * This Validator validates *just* Pet instances 57 | */ 58 | @Override 59 | public boolean supports(Class clazz) { 60 | return Pet.class.isAssignableFrom(clazz); 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /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 org.springframework.samples.petclinic.visit.Visit; 19 | import org.springframework.samples.petclinic.visit.VisitRepository; 20 | import org.springframework.stereotype.Controller; 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.Map; 27 | 28 | /** 29 | * @author Juergen Hoeller 30 | * @author Ken Krebs 31 | * @author Arjen Poutsma 32 | * @author Michael Isvy 33 | * @author Dave Syer 34 | */ 35 | @Controller 36 | class VisitController { 37 | 38 | private final VisitRepository visits; 39 | private final PetRepository pets; 40 | 41 | 42 | public VisitController(VisitRepository visits, PetRepository pets) { 43 | this.visits = visits; 44 | this.pets = pets; 45 | } 46 | 47 | @InitBinder 48 | public void setAllowedFields(WebDataBinder dataBinder) { 49 | dataBinder.setDisallowedFields("id"); 50 | } 51 | 52 | /** 53 | * Called before each and every @RequestMapping annotated method. 54 | * 2 goals: 55 | * - Make sure we always have fresh data 56 | * - Since we do not use the session scope, make sure that Pet object always has an id 57 | * (Even though id is not part of the form fields) 58 | * 59 | * @param petId 60 | * @return Pet 61 | */ 62 | @ModelAttribute("visit") 63 | public Visit loadPetWithVisit(@PathVariable("petId") int petId, Map model) { 64 | Pet pet = this.pets.findById(petId); 65 | model.put("pet", pet); 66 | Visit visit = new Visit(); 67 | pet.addVisit(visit); 68 | return visit; 69 | } 70 | 71 | // Spring MVC calls method loadPetWithVisit(...) before initNewVisitForm is called 72 | @GetMapping("/owners/*/pets/{petId}/visits/new") 73 | public String initNewVisitForm(@PathVariable("petId") int petId, Map model) { 74 | return "pets/createOrUpdateVisitForm"; 75 | } 76 | 77 | // Spring MVC calls method loadPetWithVisit(...) before processNewVisitForm is called 78 | @PostMapping("/owners/{ownerId}/pets/{petId}/visits/new") 79 | public String processNewVisitForm(@Valid Visit visit, BindingResult result) { 80 | if (result.hasErrors()) { 81 | return "pets/createOrUpdateVisitForm"; 82 | } else { 83 | this.visits.save(visit); 84 | return "redirect:/owners/{ownerId}"; 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /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 org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer; 20 | import org.springframework.cache.annotation.EnableCaching; 21 | import org.springframework.context.annotation.Bean; 22 | import org.springframework.context.annotation.Configuration; 23 | 24 | import javax.cache.configuration.MutableConfiguration; 25 | 26 | /** 27 | * Cache configuration intended for caches providing the JCache API. This configuration creates the used cache for the 28 | * application and enables statistics that become accessible via JMX. 29 | */ 30 | @Configuration 31 | @EnableCaching 32 | class CacheConfiguration { 33 | 34 | @Bean 35 | public JCacheManagerCustomizer petclinicCacheConfigurationCustomizer() { 36 | return cm -> { 37 | cm.createCache("vets", cacheConfiguration()); 38 | }; 39 | } 40 | 41 | /** 42 | * Create a simple configuration that enable statistics via the JCache programmatic configuration API. 43 | *

44 | * Within the configuration object that is provided by the JCache API standard, there is only a very limited set of 45 | * configuration options. The really relevant configuration options (like the size limit) must be set via a 46 | * configuration mechanism that is provided by the selected JCache implementation. 47 | */ 48 | private javax.cache.configuration.Configuration cacheConfiguration() { 49 | return new MutableConfiguration<>().setStatisticsEnabled(true); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /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("Expected: controller used to showcase what " 34 | + "happens when an exception is thrown"); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /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 | 20 | import org.springframework.stereotype.Controller; 21 | import org.springframework.web.bind.annotation.GetMapping; 22 | 23 | @Controller 24 | class WelcomeController { 25 | 26 | @GetMapping("/") 27 | public String welcome() { 28 | return "welcome"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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"), inverseJoinColumns = @JoinColumn(name = "specialty_id")) 50 | private Set specialties; 51 | 52 | protected Set getSpecialtiesInternal() { 53 | if (this.specialties == null) { 54 | this.specialties = new HashSet<>(); 55 | } 56 | return this.specialties; 57 | } 58 | 59 | protected void setSpecialtiesInternal(Set specialties) { 60 | this.specialties = specialties; 61 | } 62 | 63 | @XmlElement 64 | public List getSpecialties() { 65 | List sortedSpecs = new ArrayList<>(getSpecialtiesInternal()); 66 | PropertyComparator.sort(sortedSpecs, 67 | 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 with Spring Data naming 27 | * conventions so this interface can easily be extended for Spring Data. 28 | * See: 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 VetRepository extends Repository { 36 | 37 | /** 38 | * Retrieve all Vets from the data store. 39 | * 40 | * @return a Collection of Vets 41 | */ 42 | @Transactional(readOnly = true) 43 | @Cacheable("vets") 44 | Collection findAll() throws DataAccessException; 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /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 the 'vets' {@link 26 | * 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 with Spring Data naming 26 | * conventions so this interface can easily be extended for Spring Data. 27 | * See: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation 28 | * 29 | * @author Ken Krebs 30 | * @author Juergen Hoeller 31 | * @author Sam Brannen 32 | * @author Michael Isvy 33 | */ 34 | public interface VisitRepository extends Repository { 35 | 36 | /** 37 | * Save a Visit to the data store, either inserting or updating it. 38 | * 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/main/less/petclinic.less: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 the original author or authors. 3 | * 4 | * You may obtain a copy of the License at 5 | * 6 | * https://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | @icon-font-path: "../../webjars/bootstrap/fonts/"; 15 | 16 | @spring-green: #6db33f; 17 | @spring-dark-green: #5fa134; 18 | @spring-brown: #34302D; 19 | @spring-grey: #838789; 20 | @spring-light-grey: #f1f1f1; 21 | 22 | @body-bg: @spring-light-grey; 23 | @text-color: @spring-brown; 24 | @link-color: @spring-dark-green; 25 | @link-hover-color: @spring-dark-green; 26 | 27 | @navbar-default-link-color: @spring-light-grey; 28 | @navbar-default-link-active-color: @spring-light-grey; 29 | @navbar-default-link-hover-color: @spring-light-grey; 30 | @navbar-default-link-hover-bg: @spring-green; 31 | @navbar-default-toggle-icon-bar-bg: @spring-light-grey; 32 | @navbar-default-toggle-hover-bg: transparent; 33 | @navbar-default-link-active-bg: @spring-green; 34 | 35 | @border-radius-base: 0; 36 | @border-radius-large: 0; 37 | @border-radius-small: 0; 38 | 39 | @btn-default-color: @spring-light-grey; 40 | @btn-default-bg: @spring-brown; 41 | @btn-default-border: @spring-green; 42 | 43 | @nav-tabs-active-link-hover-color: @spring-light-grey; 44 | @nav-tabs-active-link-hover-bg: @spring-brown; 45 | @nav-tabs-active-link-hover-border-color: @spring-brown; 46 | @nav-tabs-border-color: @spring-brown; 47 | 48 | @pagination-active-bg: @spring-brown; 49 | @pagination-active-border: @spring-green; 50 | @table-border-color: @spring-brown; 51 | 52 | .table > thead > tr > th { 53 | background-color: lighten(@spring-brown, 3%); 54 | color: @spring-light-grey; 55 | } 56 | 57 | .table-filter { 58 | background-color: @spring-brown; 59 | padding: 9px 12px; 60 | } 61 | 62 | .nav > li > a { 63 | color: @spring-grey; 64 | } 65 | 66 | .btn-default { 67 | border-width: 2px; 68 | transition: border 0.15s; 69 | -webkit-transition: border 0.15s; 70 | -moz-transition: border 0.15s; 71 | -o-transition: border 0.15s; 72 | -ms-transition: border 0.15s; 73 | 74 | &:hover, 75 | &:focus, 76 | &:active, 77 | &.active, 78 | .open .dropdown-toggle& { 79 | background-color: @spring-brown; 80 | border-color: @spring-brown; 81 | } 82 | } 83 | 84 | 85 | .container .text-muted { 86 | margin: 20px 0; 87 | } 88 | 89 | code { 90 | font-size: 80%; 91 | } 92 | 93 | .xd-container { 94 | margin-top: 40px; 95 | margin-bottom: 100px; 96 | padding-left: 5px; 97 | padding-right: 5px; 98 | } 99 | 100 | h1 { 101 | margin-bottom: 15px 102 | } 103 | 104 | .index-page--subtitle { 105 | font-size: 16px; 106 | line-height: 24px; 107 | margin: 0 0 30px; 108 | } 109 | 110 | .form-horizontal button.btn-inverse { 111 | margin-left: 32px; 112 | } 113 | 114 | #job-params-modal .modal-dialog { 115 | width: 90%; 116 | margin-left:auto; 117 | margin-right:auto; 118 | } 119 | 120 | [ng-cloak].splash { 121 | display: block !important; 122 | } 123 | [ng-cloak] { 124 | display: none; 125 | } 126 | 127 | .splash { 128 | background: @spring-green; 129 | color: @spring-brown; 130 | display: none; 131 | } 132 | 133 | .error-page { 134 | margin-top: 100px; 135 | text-align: center; 136 | } 137 | 138 | .error-page .error-title { 139 | font-size: 24px; 140 | line-height: 24px; 141 | margin: 30px 0 0; 142 | } 143 | 144 | table td { 145 | vertical-align: middle; 146 | } 147 | 148 | table td .progress { 149 | margin-bottom: 0; 150 | } 151 | 152 | table td.action-column { 153 | width: 1px; 154 | } 155 | 156 | .help-block { 157 | color: lighten(@text-color, 50%); // lighten the text some for contrast 158 | } 159 | 160 | .xd-containers { 161 | font-size: 15px; 162 | } 163 | 164 | .cluster-view > table td { 165 | vertical-align: top; 166 | } 167 | 168 | .cluster-view .label, .cluster-view .column-block { 169 | display: block; 170 | } 171 | 172 | .cluster-view .input-group-addon { 173 | width: 0%; 174 | } 175 | 176 | .cluster-view { 177 | margin-bottom: 0; 178 | } 179 | 180 | .deployment-status-deployed { 181 | .label-success; 182 | } 183 | 184 | .deployment-status-incomplete { 185 | .label-warning; 186 | } 187 | 188 | .deployment-status-failed { 189 | .label-danger; 190 | } 191 | 192 | .deployment-status-deploying { 193 | .label-info 194 | } 195 | .deployment-status-na { 196 | } 197 | 198 | .container-details-table th { 199 | background-color: lighten(@spring-brown, 3%); 200 | color: @spring-light-grey; 201 | } 202 | 203 | .status-help-content-table td { 204 | color: @spring-brown; 205 | } 206 | 207 | .alert-success { 208 | .alert-variant(fade(@alert-success-bg, 70%); @alert-success-border; @alert-success-text); 209 | } 210 | .alert-info { 211 | .alert-variant(fade(@alert-info-bg, 70%); @alert-info-border; @alert-info-text); 212 | } 213 | .alert-warning { 214 | .alert-variant(fade(@alert-warning-bg, 70%); @alert-warning-border; @alert-warning-text); 215 | } 216 | .alert-danger { 217 | .alert-variant(fade(@alert-danger-bg, 70%); @alert-danger-border; @alert-danger-text); 218 | } 219 | 220 | .myspinner { 221 | animation-name: spinner; 222 | animation-duration: 2s; 223 | animation-iteration-count: infinite; 224 | animation-timing-function: linear; 225 | 226 | -webkit-transform-origin: 49% 50%; 227 | -webkit-animation-name: spinner; 228 | -webkit-animation-duration: 2s; 229 | -webkit-animation-iteration-count: infinite; 230 | -webkit-animation-timing-function: linear; 231 | } 232 | 233 | hr { 234 | border-top: 1px dotted @spring-brown; 235 | } 236 | 237 | @import "typography.less"; 238 | @import "header.less"; 239 | @import "responsive.less"; 240 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/main/resources/application-mysql.properties: -------------------------------------------------------------------------------- 1 | # database init, supports mysql too 2 | database=mysql 3 | spring.datasource.url=jdbc:mysql://localhost/petclinic 4 | spring.datasource.username=root 5 | spring.datasource.password=petclinic 6 | # Uncomment this the first time the app runs 7 | # spring.datasource.initialization-mode=always 8 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # database init, supports mysql too 2 | database=hsqldb 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 | 12 | # Internationalization 13 | spring.messages.basename=messages/messages 14 | 15 | # Actuator / Management 16 | management.endpoints.web.base-path=/manage 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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) Create the PetClinic database and user by executing the "db/mysql/{schema,data}.sql" 22 | scripts (or set "spring.datasource.initialize=always" the first time you run the app). 23 | 24 | 3) Run the app with `spring.profiles.active=mysql` (e.g. as a System property via the command 25 | line, but any way that sets that property in a Spring Boot app should work). 26 | 27 | N.B. the "petclinic" database has to exist for the app to work with the JDBC URL value 28 | as it is configured by default. This condition is taken care of by the docker-compose 29 | configuration provided, or by the `schema.sql` if you can run that as root. -------------------------------------------------------------------------------- /src/main/resources/db/mysql/schema.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 pc@localhost IDENTIFIED BY 'pc'; 8 | 9 | USE petclinic; 10 | 11 | CREATE TABLE IF NOT EXISTS vets ( 12 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 13 | first_name VARCHAR(30), 14 | last_name VARCHAR(30), 15 | INDEX(last_name) 16 | ) engine=InnoDB; 17 | 18 | CREATE TABLE IF NOT EXISTS specialties ( 19 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 20 | name VARCHAR(80), 21 | INDEX(name) 22 | ) engine=InnoDB; 23 | 24 | CREATE TABLE IF NOT EXISTS vet_specialties ( 25 | vet_id INT(4) UNSIGNED NOT NULL, 26 | specialty_id INT(4) UNSIGNED NOT NULL, 27 | FOREIGN KEY (vet_id) REFERENCES vets(id), 28 | FOREIGN KEY (specialty_id) REFERENCES specialties(id), 29 | UNIQUE (vet_id,specialty_id) 30 | ) engine=InnoDB; 31 | 32 | CREATE TABLE IF NOT EXISTS types ( 33 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 34 | name VARCHAR(80), 35 | INDEX(name) 36 | ) engine=InnoDB; 37 | 38 | CREATE TABLE IF NOT EXISTS owners ( 39 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 40 | first_name VARCHAR(30), 41 | last_name VARCHAR(30), 42 | address VARCHAR(255), 43 | city VARCHAR(80), 44 | telephone VARCHAR(20), 45 | INDEX(last_name) 46 | ) engine=InnoDB; 47 | 48 | CREATE TABLE IF NOT EXISTS pets ( 49 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 50 | name VARCHAR(30), 51 | birth_date DATE, 52 | type_id INT(4) UNSIGNED NOT NULL, 53 | owner_id INT(4) UNSIGNED NOT NULL, 54 | INDEX(name), 55 | FOREIGN KEY (owner_id) REFERENCES owners(id), 56 | FOREIGN KEY (type_id) REFERENCES types(id) 57 | ) engine=InnoDB; 58 | 59 | CREATE TABLE IF NOT EXISTS visits ( 60 | id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 61 | pet_id INT(4) UNSIGNED NOT NULL, 62 | visit_date DATE, 63 | description VARCHAR(255), 64 | FOREIGN KEY (pet_id) REFERENCES pets(id) 65 | ) engine=InnoDB; 66 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/main/resources/messages/messages_de.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/messages/messages_de.properties -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /src/main/resources/static/resources/fonts/montserrat-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/fonts/montserrat-webfont.eot -------------------------------------------------------------------------------- /src/main/resources/static/resources/fonts/montserrat-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/fonts/montserrat-webfont.ttf -------------------------------------------------------------------------------- /src/main/resources/static/resources/fonts/montserrat-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/fonts/montserrat-webfont.woff -------------------------------------------------------------------------------- /src/main/resources/static/resources/fonts/varela_round-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/fonts/varela_round-webfont.eot -------------------------------------------------------------------------------- /src/main/resources/static/resources/fonts/varela_round-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/fonts/varela_round-webfont.ttf -------------------------------------------------------------------------------- /src/main/resources/static/resources/fonts/varela_round-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/fonts/varela_round-webfont.woff -------------------------------------------------------------------------------- /src/main/resources/static/resources/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/images/favicon.png -------------------------------------------------------------------------------- /src/main/resources/static/resources/images/pets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/images/pets.png -------------------------------------------------------------------------------- /src/main/resources/static/resources/images/platform-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/images/platform-bg.png -------------------------------------------------------------------------------- /src/main/resources/static/resources/images/spring-logo-dataflow-mobile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/images/spring-logo-dataflow-mobile.png -------------------------------------------------------------------------------- /src/main/resources/static/resources/images/spring-logo-dataflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/images/spring-logo-dataflow.png -------------------------------------------------------------------------------- /src/main/resources/static/resources/images/spring-pivotal-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gitpod-samples/spring-petclinic/b84fc2ca666c336a0468c65ac636d0a41499d68e/src/main/resources/static/resources/images/spring-pivotal-logo.png -------------------------------------------------------------------------------- /src/main/resources/templates/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Something happened...

8 |

Exception message

9 | 10 | 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 71 |
72 |
73 | 74 | 75 | 76 |
77 |
78 |
79 |
80 |
81 | Sponsored by Pivotal
83 |
84 |
85 |
86 |
87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/main/resources/templates/welcome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Welcome

8 |
9 |
10 | 11 |
12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/wro/wro.properties: -------------------------------------------------------------------------------- 1 | #List of preProcessors 2 | preProcessors=lessCssImport 3 | #List of postProcessors 4 | postProcessors=less4j -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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.Test; 20 | import org.junit.runner.RunWith; 21 | 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.boot.test.context.SpringBootTest; 24 | import org.springframework.samples.petclinic.vet.VetRepository; 25 | import org.springframework.test.context.junit4.SpringRunner; 26 | 27 | @RunWith(SpringRunner.class) 28 | @SpringBootTest 29 | public class PetclinicIntegrationTests { 30 | 31 | @Autowired 32 | private VetRepository vets; 33 | 34 | @Test 35 | public void testFindAll() throws Exception { 36 | vets.findAll(); 37 | vets.findAll(); // served from cache 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /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.Test; 26 | 27 | import org.springframework.context.i18n.LocaleContextHolder; 28 | import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; 29 | 30 | import static org.assertj.core.api.Assertions.assertThat; 31 | 32 | /** 33 | * @author Michael Isvy Simple test to make sure that Bean Validation is working (useful 34 | * when upgrading to a new version of Hibernate Validator/ Bean Validation) 35 | */ 36 | public class ValidatorTests { 37 | 38 | private Validator createValidator() { 39 | LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean(); 40 | localValidatorFactoryBean.afterPropertiesSet(); 41 | return localValidatorFactoryBean; 42 | } 43 | 44 | @Test 45 | public void shouldNotValidateWhenFirstNameEmpty() { 46 | 47 | LocaleContextHolder.setLocale(Locale.ENGLISH); 48 | Person person = new Person(); 49 | person.setFirstName(""); 50 | person.setLastName("smith"); 51 | 52 | Validator validator = createValidator(); 53 | Set> constraintViolations = validator 54 | .validate(person); 55 | 56 | assertThat(constraintViolations).hasSize(1); 57 | ConstraintViolation violation = constraintViolations.iterator().next(); 58 | assertThat(violation.getPropertyPath().toString()).isEqualTo("firstName"); 59 | assertThat(violation.getMessage()).isEqualTo("must not be empty"); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/petclinic/owner/OwnerControllerTests.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.hamcrest.Matchers.hasProperty; 20 | import static org.hamcrest.Matchers.is; 21 | import static org.mockito.BDDMockito.given; 22 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 23 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 24 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 25 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 26 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 27 | 28 | import org.assertj.core.util.Lists; 29 | import org.junit.Before; 30 | import org.junit.Test; 31 | import org.junit.runner.RunWith; 32 | import org.springframework.beans.factory.annotation.Autowired; 33 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 34 | import org.springframework.boot.test.mock.mockito.MockBean; 35 | import org.springframework.samples.petclinic.owner.Owner; 36 | import org.springframework.samples.petclinic.owner.OwnerController; 37 | import org.springframework.samples.petclinic.owner.OwnerRepository; 38 | import org.springframework.test.context.junit4.SpringRunner; 39 | import org.springframework.test.web.servlet.MockMvc; 40 | 41 | /** 42 | * Test class for {@link OwnerController} 43 | * 44 | * @author Colin But 45 | */ 46 | @RunWith(SpringRunner.class) 47 | @WebMvcTest(OwnerController.class) 48 | public class OwnerControllerTests { 49 | 50 | private static final int TEST_OWNER_ID = 1; 51 | 52 | @Autowired 53 | private MockMvc mockMvc; 54 | 55 | @MockBean 56 | private OwnerRepository owners; 57 | 58 | private Owner george; 59 | 60 | @Before 61 | public void setup() { 62 | george = new Owner(); 63 | george.setId(TEST_OWNER_ID); 64 | george.setFirstName("George"); 65 | george.setLastName("Franklin"); 66 | george.setAddress("110 W. Liberty St."); 67 | george.setCity("Madison"); 68 | george.setTelephone("6085551023"); 69 | given(this.owners.findById(TEST_OWNER_ID)).willReturn(george); 70 | } 71 | 72 | @Test 73 | public void testInitCreationForm() throws Exception { 74 | mockMvc.perform(get("/owners/new")) 75 | .andExpect(status().isOk()) 76 | .andExpect(model().attributeExists("owner")) 77 | .andExpect(view().name("owners/createOrUpdateOwnerForm")); 78 | } 79 | 80 | @Test 81 | public void testProcessCreationFormSuccess() throws Exception { 82 | mockMvc.perform(post("/owners/new") 83 | .param("firstName", "Joe") 84 | .param("lastName", "Bloggs") 85 | .param("address", "123 Caramel Street") 86 | .param("city", "London") 87 | .param("telephone", "01316761638") 88 | ) 89 | .andExpect(status().is3xxRedirection()); 90 | } 91 | 92 | @Test 93 | public void testProcessCreationFormHasErrors() throws Exception { 94 | mockMvc.perform(post("/owners/new") 95 | .param("firstName", "Joe") 96 | .param("lastName", "Bloggs") 97 | .param("city", "London") 98 | ) 99 | .andExpect(status().isOk()) 100 | .andExpect(model().attributeHasErrors("owner")) 101 | .andExpect(model().attributeHasFieldErrors("owner", "address")) 102 | .andExpect(model().attributeHasFieldErrors("owner", "telephone")) 103 | .andExpect(view().name("owners/createOrUpdateOwnerForm")); 104 | } 105 | 106 | @Test 107 | public void testInitFindForm() throws Exception { 108 | mockMvc.perform(get("/owners/find")) 109 | .andExpect(status().isOk()) 110 | .andExpect(model().attributeExists("owner")) 111 | .andExpect(view().name("owners/findOwners")); 112 | } 113 | 114 | @Test 115 | public void testProcessFindFormSuccess() throws Exception { 116 | given(this.owners.findByLastName("")).willReturn(Lists.newArrayList(george, new Owner())); 117 | mockMvc.perform(get("/owners")) 118 | .andExpect(status().isOk()) 119 | .andExpect(view().name("owners/ownersList")); 120 | } 121 | 122 | @Test 123 | public void testProcessFindFormByLastName() throws Exception { 124 | given(this.owners.findByLastName(george.getLastName())).willReturn(Lists.newArrayList(george)); 125 | mockMvc.perform(get("/owners") 126 | .param("lastName", "Franklin") 127 | ) 128 | .andExpect(status().is3xxRedirection()) 129 | .andExpect(view().name("redirect:/owners/" + TEST_OWNER_ID)); 130 | } 131 | 132 | @Test 133 | public void testProcessFindFormNoOwnersFound() throws Exception { 134 | mockMvc.perform(get("/owners") 135 | .param("lastName", "Unknown Surname") 136 | ) 137 | .andExpect(status().isOk()) 138 | .andExpect(model().attributeHasFieldErrors("owner", "lastName")) 139 | .andExpect(model().attributeHasFieldErrorCode("owner", "lastName", "notFound")) 140 | .andExpect(view().name("owners/findOwners")); 141 | } 142 | 143 | @Test 144 | public void testInitUpdateOwnerForm() throws Exception { 145 | mockMvc.perform(get("/owners/{ownerId}/edit", TEST_OWNER_ID)) 146 | .andExpect(status().isOk()) 147 | .andExpect(model().attributeExists("owner")) 148 | .andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin")))) 149 | .andExpect(model().attribute("owner", hasProperty("firstName", is("George")))) 150 | .andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St.")))) 151 | .andExpect(model().attribute("owner", hasProperty("city", is("Madison")))) 152 | .andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023")))) 153 | .andExpect(view().name("owners/createOrUpdateOwnerForm")); 154 | } 155 | 156 | @Test 157 | public void testProcessUpdateOwnerFormSuccess() throws Exception { 158 | mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID) 159 | .param("firstName", "Joe") 160 | .param("lastName", "Bloggs") 161 | .param("address", "123 Caramel Street") 162 | .param("city", "London") 163 | .param("telephone", "01616291589") 164 | ) 165 | .andExpect(status().is3xxRedirection()) 166 | .andExpect(view().name("redirect:/owners/{ownerId}")); 167 | } 168 | 169 | @Test 170 | public void testProcessUpdateOwnerFormHasErrors() throws Exception { 171 | mockMvc.perform(post("/owners/{ownerId}/edit", TEST_OWNER_ID) 172 | .param("firstName", "Joe") 173 | .param("lastName", "Bloggs") 174 | .param("city", "London") 175 | ) 176 | .andExpect(status().isOk()) 177 | .andExpect(model().attributeHasErrors("owner")) 178 | .andExpect(model().attributeHasFieldErrors("owner", "address")) 179 | .andExpect(model().attributeHasFieldErrors("owner", "telephone")) 180 | .andExpect(view().name("owners/createOrUpdateOwnerForm")); 181 | } 182 | 183 | @Test 184 | public void testShowOwner() throws Exception { 185 | mockMvc.perform(get("/owners/{ownerId}", TEST_OWNER_ID)) 186 | .andExpect(status().isOk()) 187 | .andExpect(model().attribute("owner", hasProperty("lastName", is("Franklin")))) 188 | .andExpect(model().attribute("owner", hasProperty("firstName", is("George")))) 189 | .andExpect(model().attribute("owner", hasProperty("address", is("110 W. Liberty St.")))) 190 | .andExpect(model().attribute("owner", hasProperty("city", is("Madison")))) 191 | .andExpect(model().attribute("owner", hasProperty("telephone", is("6085551023")))) 192 | .andExpect(view().name("owners/ownerDetails")); 193 | } 194 | 195 | } 196 | -------------------------------------------------------------------------------- /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.Before; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 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.context.annotation.ComponentScan; 34 | import org.springframework.context.annotation.FilterType; 35 | import org.springframework.samples.petclinic.owner.Owner; 36 | import org.springframework.samples.petclinic.owner.OwnerRepository; 37 | import org.springframework.samples.petclinic.owner.Pet; 38 | import org.springframework.samples.petclinic.owner.PetController; 39 | import org.springframework.samples.petclinic.owner.PetRepository; 40 | import org.springframework.samples.petclinic.owner.PetType; 41 | import org.springframework.samples.petclinic.owner.PetTypeFormatter; 42 | import org.springframework.test.context.junit4.SpringRunner; 43 | import org.springframework.test.web.servlet.MockMvc; 44 | 45 | /** 46 | * Test class for the {@link PetController} 47 | * 48 | * @author Colin But 49 | */ 50 | @RunWith(SpringRunner.class) 51 | @WebMvcTest(value = PetController.class, 52 | includeFilters = @ComponentScan.Filter( 53 | value = PetTypeFormatter.class, 54 | type = FilterType.ASSIGNABLE_TYPE)) 55 | public class PetControllerTests { 56 | 57 | private static final int TEST_OWNER_ID = 1; 58 | private static final int TEST_PET_ID = 1; 59 | 60 | 61 | @Autowired 62 | private MockMvc mockMvc; 63 | 64 | @MockBean 65 | private PetRepository pets; 66 | 67 | @MockBean 68 | private OwnerRepository owners; 69 | 70 | @Before 71 | public void setup() { 72 | PetType cat = new PetType(); 73 | cat.setId(3); 74 | cat.setName("hamster"); 75 | given(this.pets.findPetTypes()).willReturn(Lists.newArrayList(cat)); 76 | given(this.owners.findById(TEST_OWNER_ID)).willReturn(new Owner()); 77 | given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet()); 78 | 79 | } 80 | 81 | @Test 82 | public void testInitCreationForm() throws Exception { 83 | mockMvc.perform(get("/owners/{ownerId}/pets/new", TEST_OWNER_ID)) 84 | .andExpect(status().isOk()) 85 | .andExpect(view().name("pets/createOrUpdatePetForm")) 86 | .andExpect(model().attributeExists("pet")); 87 | } 88 | 89 | @Test 90 | public void testProcessCreationFormSuccess() throws Exception { 91 | mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID) 92 | .param("name", "Betty") 93 | .param("type", "hamster") 94 | .param("birthDate", "2015-02-12") 95 | ) 96 | .andExpect(status().is3xxRedirection()) 97 | .andExpect(view().name("redirect:/owners/{ownerId}")); 98 | } 99 | 100 | @Test 101 | public void testProcessCreationFormHasErrors() throws Exception { 102 | mockMvc.perform(post("/owners/{ownerId}/pets/new", TEST_OWNER_ID) 103 | .param("name", "Betty") 104 | .param("birthDate", "2015-02-12") 105 | ) 106 | .andExpect(model().attributeHasNoErrors("owner")) 107 | .andExpect(model().attributeHasErrors("pet")) 108 | .andExpect(model().attributeHasFieldErrors("pet", "type")) 109 | .andExpect(model().attributeHasFieldErrorCode("pet", "type", "required")) 110 | .andExpect(status().isOk()) 111 | .andExpect(view().name("pets/createOrUpdatePetForm")); 112 | } 113 | 114 | @Test 115 | public void testInitUpdateForm() throws Exception { 116 | mockMvc.perform(get("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID)) 117 | .andExpect(status().isOk()) 118 | .andExpect(model().attributeExists("pet")) 119 | .andExpect(view().name("pets/createOrUpdatePetForm")); 120 | } 121 | 122 | @Test 123 | public void testProcessUpdateFormSuccess() throws Exception { 124 | mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID) 125 | .param("name", "Betty") 126 | .param("type", "hamster") 127 | .param("birthDate", "2015-02-12") 128 | ) 129 | .andExpect(status().is3xxRedirection()) 130 | .andExpect(view().name("redirect:/owners/{ownerId}")); 131 | } 132 | 133 | @Test 134 | public void testProcessUpdateFormHasErrors() throws Exception { 135 | mockMvc.perform(post("/owners/{ownerId}/pets/{petId}/edit", TEST_OWNER_ID, TEST_PET_ID) 136 | .param("name", "Betty") 137 | .param("birthDate", "2015/02/12") 138 | ) 139 | .andExpect(model().attributeHasNoErrors("owner")) 140 | .andExpect(model().attributeHasErrors("pet")) 141 | .andExpect(status().isOk()) 142 | .andExpect(view().name("pets/createOrUpdatePetForm")); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /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.Before; 26 | import org.junit.Test; 27 | import org.junit.runner.RunWith; 28 | import org.mockito.Mock; 29 | import org.mockito.junit.MockitoJUnitRunner; 30 | 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | import static org.mockito.BDDMockito.given; 33 | 34 | /** 35 | * Test class for {@link PetTypeFormatter} 36 | * 37 | * @author Colin But 38 | */ 39 | @RunWith(MockitoJUnitRunner.class) 40 | public class PetTypeFormatterTests { 41 | 42 | @Mock 43 | private PetRepository pets; 44 | 45 | private PetTypeFormatter petTypeFormatter; 46 | 47 | @Before 48 | public void setup() { 49 | this.petTypeFormatter = new PetTypeFormatter(pets); 50 | } 51 | 52 | @Test 53 | public void testPrint() { 54 | PetType petType = new PetType(); 55 | petType.setName("Hamster"); 56 | String petTypeName = this.petTypeFormatter.print(petType, Locale.ENGLISH); 57 | assertThat(petTypeName).isEqualTo("Hamster"); 58 | } 59 | 60 | @Test 61 | public void shouldParse() throws ParseException { 62 | given(this.pets.findPetTypes()).willReturn(makePetTypes()); 63 | PetType petType = petTypeFormatter.parse("Bird", Locale.ENGLISH); 64 | assertThat(petType.getName()).isEqualTo("Bird"); 65 | } 66 | 67 | @Test(expected = ParseException.class) 68 | public void shouldThrowParseException() throws ParseException { 69 | given(this.pets.findPetTypes()).willReturn(makePetTypes()); 70 | petTypeFormatter.parse("Fish", Locale.ENGLISH); 71 | } 72 | 73 | /** 74 | * Helper method to produce some sample pet types just for test purpose 75 | * 76 | * @return {@link Collection} of {@link PetType} 77 | */ 78 | private List makePetTypes() { 79 | List petTypes = new ArrayList<>(); 80 | petTypes.add(new PetType() { 81 | { 82 | setName("Dog"); 83 | } 84 | }); 85 | petTypes.add(new PetType() { 86 | { 87 | setName("Bird"); 88 | } 89 | }); 90 | return petTypes; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /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.Before; 27 | import org.junit.Test; 28 | import org.junit.runner.RunWith; 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.samples.petclinic.owner.Pet; 33 | import org.springframework.samples.petclinic.owner.PetRepository; 34 | import org.springframework.samples.petclinic.owner.VisitController; 35 | import org.springframework.samples.petclinic.visit.VisitRepository; 36 | import org.springframework.test.context.junit4.SpringRunner; 37 | import org.springframework.test.web.servlet.MockMvc; 38 | 39 | /** 40 | * Test class for {@link VisitController} 41 | * 42 | * @author Colin But 43 | */ 44 | @RunWith(SpringRunner.class) 45 | @WebMvcTest(VisitController.class) 46 | public class VisitControllerTests { 47 | 48 | private static final int TEST_PET_ID = 1; 49 | 50 | @Autowired 51 | private MockMvc mockMvc; 52 | 53 | @MockBean 54 | private VisitRepository visits; 55 | 56 | @MockBean 57 | private PetRepository pets; 58 | 59 | @Before 60 | public void init() { 61 | given(this.pets.findById(TEST_PET_ID)).willReturn(new Pet()); 62 | } 63 | 64 | @Test 65 | public void testInitNewVisitForm() throws Exception { 66 | mockMvc.perform(get("/owners/*/pets/{petId}/visits/new", TEST_PET_ID)) 67 | .andExpect(status().isOk()) 68 | .andExpect(view().name("pets/createOrUpdateVisitForm")); 69 | } 70 | 71 | @Test 72 | public void testProcessNewVisitFormSuccess() throws Exception { 73 | mockMvc.perform(post("/owners/*/pets/{petId}/visits/new", TEST_PET_ID) 74 | .param("name", "George") 75 | .param("description", "Visit Description") 76 | ) 77 | .andExpect(status().is3xxRedirection()) 78 | .andExpect(view().name("redirect:/owners/{ownerId}")); 79 | } 80 | 81 | @Test 82 | public void testProcessNewVisitFormHasErrors() throws Exception { 83 | mockMvc.perform(post("/owners/*/pets/{petId}/visits/new", TEST_PET_ID) 84 | .param("name", "George") 85 | ) 86 | .andExpect(model().attributeHasErrors("visit")) 87 | .andExpect(status().isOk()) 88 | .andExpect(view().name("pets/createOrUpdateVisitForm")); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/test/java/org/springframework/samples/petclinic/service/ClinicServiceTests.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 static org.assertj.core.api.Assertions.assertThat; 20 | 21 | import java.time.LocalDate; 22 | import java.util.Collection; 23 | 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 28 | import org.springframework.context.annotation.ComponentScan; 29 | import org.springframework.samples.petclinic.owner.Owner; 30 | import org.springframework.samples.petclinic.owner.OwnerRepository; 31 | import org.springframework.samples.petclinic.owner.Pet; 32 | import org.springframework.samples.petclinic.owner.PetRepository; 33 | import org.springframework.samples.petclinic.owner.PetType; 34 | import org.springframework.samples.petclinic.vet.Vet; 35 | import org.springframework.samples.petclinic.vet.VetRepository; 36 | import org.springframework.samples.petclinic.visit.Visit; 37 | import org.springframework.samples.petclinic.visit.VisitRepository; 38 | import org.springframework.stereotype.Service; 39 | import org.springframework.test.context.junit4.SpringRunner; 40 | import org.springframework.transaction.annotation.Transactional; 41 | 42 | /** 43 | * Integration test of the Service and the Repository layer. 44 | *

45 | * ClinicServiceSpringDataJpaTests subclasses benefit from the following services provided by the Spring 46 | * TestContext Framework:

  • Spring IoC container caching which spares us unnecessary set up 47 | * time between test execution.
  • Dependency Injection of test fixture instances, meaning that 48 | * we don't need to perform application context lookups. See the use of {@link Autowired @Autowired} on the {@link 49 | * ClinicServiceTests#clinicService clinicService} instance variable, which uses autowiring by 50 | * type.
  • Transaction management, meaning each test method is executed in its own transaction, 51 | * which is automatically rolled back by default. Thus, even if tests insert or otherwise change database state, there 52 | * is no need for a teardown or cleanup script.
  • An {@link org.springframework.context.ApplicationContext 53 | * ApplicationContext} is also inherited and can be used for explicit bean lookup if necessary.
54 | * 55 | * @author Ken Krebs 56 | * @author Rod Johnson 57 | * @author Juergen Hoeller 58 | * @author Sam Brannen 59 | * @author Michael Isvy 60 | * @author Dave Syer 61 | */ 62 | 63 | @RunWith(SpringRunner.class) 64 | @DataJpaTest(includeFilters = @ComponentScan.Filter(Service.class)) 65 | public class ClinicServiceTests { 66 | 67 | @Autowired 68 | protected OwnerRepository owners; 69 | 70 | @Autowired 71 | protected PetRepository pets; 72 | 73 | @Autowired 74 | protected VisitRepository visits; 75 | 76 | @Autowired 77 | protected VetRepository vets; 78 | 79 | @Test 80 | public void shouldFindOwnersByLastName() { 81 | Collection owners = this.owners.findByLastName("Davis"); 82 | assertThat(owners).hasSize(2); 83 | 84 | owners = this.owners.findByLastName("Daviss"); 85 | assertThat(owners).isEmpty(); 86 | } 87 | 88 | @Test 89 | public void shouldFindSingleOwnerWithPet() { 90 | Owner owner = this.owners.findById(1); 91 | assertThat(owner.getLastName()).startsWith("Franklin"); 92 | assertThat(owner.getPets()).hasSize(1); 93 | assertThat(owner.getPets().get(0).getType()).isNotNull(); 94 | assertThat(owner.getPets().get(0).getType().getName()).isEqualTo("cat"); 95 | } 96 | 97 | @Test 98 | @Transactional 99 | public void shouldInsertOwner() { 100 | Collection owners = this.owners.findByLastName("Schultz"); 101 | int found = owners.size(); 102 | 103 | Owner owner = new Owner(); 104 | owner.setFirstName("Sam"); 105 | owner.setLastName("Schultz"); 106 | owner.setAddress("4, Evans Street"); 107 | owner.setCity("Wollongong"); 108 | owner.setTelephone("4444444444"); 109 | this.owners.save(owner); 110 | assertThat(owner.getId().longValue()).isNotEqualTo(0); 111 | 112 | owners = this.owners.findByLastName("Schultz"); 113 | assertThat(owners.size()).isEqualTo(found + 1); 114 | } 115 | 116 | @Test 117 | @Transactional 118 | public void shouldUpdateOwner() { 119 | Owner owner = this.owners.findById(1); 120 | String oldLastName = owner.getLastName(); 121 | String newLastName = oldLastName + "X"; 122 | 123 | owner.setLastName(newLastName); 124 | this.owners.save(owner); 125 | 126 | // retrieving new name from database 127 | owner = this.owners.findById(1); 128 | assertThat(owner.getLastName()).isEqualTo(newLastName); 129 | } 130 | 131 | @Test 132 | public void shouldFindPetWithCorrectId() { 133 | Pet pet7 = this.pets.findById(7); 134 | assertThat(pet7.getName()).startsWith("Samantha"); 135 | assertThat(pet7.getOwner().getFirstName()).isEqualTo("Jean"); 136 | 137 | } 138 | 139 | @Test 140 | public void shouldFindAllPetTypes() { 141 | Collection petTypes = this.pets.findPetTypes(); 142 | 143 | PetType petType1 = EntityUtils.getById(petTypes, PetType.class, 1); 144 | assertThat(petType1.getName()).isEqualTo("cat"); 145 | PetType petType4 = EntityUtils.getById(petTypes, PetType.class, 4); 146 | assertThat(petType4.getName()).isEqualTo("snake"); 147 | } 148 | 149 | @Test 150 | @Transactional 151 | public void shouldInsertPetIntoDatabaseAndGenerateId() { 152 | Owner owner6 = this.owners.findById(6); 153 | int found = owner6.getPets().size(); 154 | 155 | Pet pet = new Pet(); 156 | pet.setName("bowser"); 157 | Collection types = this.pets.findPetTypes(); 158 | pet.setType(EntityUtils.getById(types, PetType.class, 2)); 159 | pet.setBirthDate(LocalDate.now()); 160 | owner6.addPet(pet); 161 | assertThat(owner6.getPets().size()).isEqualTo(found + 1); 162 | 163 | this.pets.save(pet); 164 | this.owners.save(owner6); 165 | 166 | owner6 = this.owners.findById(6); 167 | assertThat(owner6.getPets().size()).isEqualTo(found + 1); 168 | // checks that id has been generated 169 | assertThat(pet.getId()).isNotNull(); 170 | } 171 | 172 | @Test 173 | @Transactional 174 | public void shouldUpdatePetName() throws Exception { 175 | Pet pet7 = this.pets.findById(7); 176 | String oldName = pet7.getName(); 177 | 178 | String newName = oldName + "X"; 179 | pet7.setName(newName); 180 | this.pets.save(pet7); 181 | 182 | pet7 = this.pets.findById(7); 183 | assertThat(pet7.getName()).isEqualTo(newName); 184 | } 185 | 186 | @Test 187 | public void shouldFindVets() { 188 | Collection vets = this.vets.findAll(); 189 | 190 | Vet vet = EntityUtils.getById(vets, Vet.class, 3); 191 | assertThat(vet.getLastName()).isEqualTo("Douglas"); 192 | assertThat(vet.getNrOfSpecialties()).isEqualTo(2); 193 | assertThat(vet.getSpecialties().get(0).getName()).isEqualTo("dentistry"); 194 | assertThat(vet.getSpecialties().get(1).getName()).isEqualTo("surgery"); 195 | } 196 | 197 | @Test 198 | @Transactional 199 | public void shouldAddNewVisitForPet() { 200 | Pet pet7 = this.pets.findById(7); 201 | int found = pet7.getVisits().size(); 202 | Visit visit = new Visit(); 203 | pet7.addVisit(visit); 204 | visit.setDescription("test"); 205 | this.visits.save(visit); 206 | this.pets.save(pet7); 207 | 208 | pet7 = this.pets.findById(7); 209 | assertThat(pet7.getVisits().size()).isEqualTo(found + 1); 210 | assertThat(visit.getId()).isNotNull(); 211 | } 212 | 213 | @Test 214 | public void shouldFindVisitsByPetId() throws Exception { 215 | Collection visits = this.visits.findByPetId(7); 216 | assertThat(visits).hasSize(2); 217 | Visit[] visitArr = visits.toArray(new Visit[visits.size()]); 218 | assertThat(visitArr[0].getDate()).isNotNull(); 219 | assertThat(visitArr[0].getPetId()).isEqualTo(7); 220 | } 221 | 222 | } 223 | -------------------------------------------------------------------------------- /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 because of dependency on the 26 | * 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 | * 38 | * @param entities the collection to search 39 | * @param entityClass the entity class to look up 40 | * @param entityId the entity id to look up 41 | * @return the found entity 42 | * @throws ObjectRetrievalFailureException if the entity was not found 43 | */ 44 | public static T getById(Collection entities, Class entityClass, int entityId) 45 | throws ObjectRetrievalFailureException { 46 | for (T entity : entities) { 47 | if (entity.getId() == entityId && entityClass.isInstance(entity)) { 48 | return entity; 49 | } 50 | } 51 | throw new ObjectRetrievalFailureException(entityClass, entityId); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /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.Ignore; 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 25 | import org.springframework.test.context.junit4.SpringRunner; 26 | import org.springframework.test.web.servlet.MockMvc; 27 | 28 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 29 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; 30 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; 31 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 32 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; 33 | 34 | /** 35 | * Test class for {@link CrashController} 36 | * 37 | * @author Colin But 38 | */ 39 | @RunWith(SpringRunner.class) 40 | // Waiting https://github.com/spring-projects/spring-boot/issues/5574 41 | @Ignore 42 | @WebMvcTest(controllers = CrashController.class) 43 | public class CrashControllerTests { 44 | 45 | @Autowired 46 | private MockMvc mockMvc; 47 | 48 | @Test 49 | public void testTriggerException() throws Exception { 50 | mockMvc.perform(get("/oups")).andExpect(view().name("exception")) 51 | .andExpect(model().attributeExists("exception")) 52 | .andExpect(forwardedUrl("exception")).andExpect(status().isOk()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /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.Before; 29 | import org.junit.Test; 30 | import org.junit.runner.RunWith; 31 | import org.springframework.beans.factory.annotation.Autowired; 32 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 33 | import org.springframework.boot.test.mock.mockito.MockBean; 34 | import org.springframework.http.MediaType; 35 | import org.springframework.test.context.junit4.SpringRunner; 36 | import org.springframework.test.web.servlet.MockMvc; 37 | import org.springframework.test.web.servlet.ResultActions; 38 | 39 | /** 40 | * Test class for the {@link VetController} 41 | */ 42 | @RunWith(SpringRunner.class) 43 | @WebMvcTest(VetController.class) 44 | public class VetControllerTests { 45 | 46 | @Autowired 47 | private MockMvc mockMvc; 48 | 49 | @MockBean 50 | private VetRepository vets; 51 | 52 | @Before 53 | public void setup() { 54 | Vet james = new Vet(); 55 | james.setFirstName("James"); 56 | james.setLastName("Carter"); 57 | james.setId(1); 58 | Vet helen = new Vet(); 59 | helen.setFirstName("Helen"); 60 | helen.setLastName("Leary"); 61 | helen.setId(2); 62 | Specialty radiology = new Specialty(); 63 | radiology.setId(1); 64 | radiology.setName("radiology"); 65 | helen.addSpecialty(radiology); 66 | given(this.vets.findAll()).willReturn(Lists.newArrayList(james, helen)); 67 | } 68 | 69 | @Test 70 | public void testShowVetListHtml() throws Exception { 71 | mockMvc.perform(get("/vets.html")) 72 | .andExpect(status().isOk()) 73 | .andExpect(model().attributeExists("vets")) 74 | .andExpect(view().name("vets/vetList")); 75 | } 76 | 77 | @Test 78 | public void testShowResourcesVetList() throws Exception { 79 | ResultActions actions = mockMvc.perform(get("/vets") 80 | .accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk()); 81 | actions.andExpect(content().contentType("application/json;charset=UTF-8")) 82 | .andExpect(jsonPath("$.vetList[0].id").value(1)); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /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.Test; 19 | 20 | import org.springframework.util.SerializationUtils; 21 | 22 | import static org.assertj.core.api.Assertions.assertThat; 23 | 24 | /** 25 | * @author Dave Syer 26 | * 27 | */ 28 | public class VetTests { 29 | 30 | @Test 31 | public void testSerialization() { 32 | Vet vet = new Vet(); 33 | vet.setFirstName("Zaphod"); 34 | vet.setLastName("Beeblebrox"); 35 | vet.setId(123); 36 | Vet other = (Vet) SerializationUtils 37 | .deserialize(SerializationUtils.serialize(vet)); 38 | assertThat(other.getFirstName()).isEqualTo(vet.getFirstName()); 39 | assertThat(other.getLastName()).isEqualTo(vet.getLastName()); 40 | assertThat(other.getId()).isEqualTo(vet.getId()); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/test/jmeter/petclinic_test_plan.jmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | false 7 | false 8 | 9 | 10 | 11 | PETCLINIC_HOST 12 | localhost 13 | = 14 | 15 | 16 | PETCLINIC_PORT 17 | 8080 18 | = 19 | 20 | 21 | CONTEXT_WEB 22 | 23 | = 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | continue 32 | 33 | false 34 | 10 35 | 36 | 500 37 | 10 38 | 1361531541000 39 | 1361531541000 40 | false 41 | 42 | 43 | true 44 | Original : 500 - 10 - 10 45 | 46 | 47 | 48 | 300 49 | 50 | 51 | 52 | 53 | 54 | 55 | ${PETCLINIC_HOST} 56 | ${PETCLINIC_PORT} 57 | 58 | 59 | 60 | 61 | 62 | 4 63 | 64 | 65 | 66 | 67 | true 68 | 69 | 70 | 71 | 1 72 | 10 73 | 1 74 | count 75 | 76 | false 77 | 78 | 79 | 80 | 1 81 | 13 82 | 1 83 | petCount 84 | 85 | false 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | ${CONTEXT_WEB}/ 99 | GET 100 | true 101 | false 102 | true 103 | false 104 | false 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | ${CONTEXT_WEB}/resources/css/petclinic.css 119 | GET 120 | true 121 | false 122 | true 123 | false 124 | false 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | ${CONTEXT_WEB}/webjars/jquery/jquery.min.js 139 | GET 140 | true 141 | false 142 | true 143 | false 144 | false 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | ${CONTEXT_WEB}/vets.html 159 | GET 160 | true 161 | false 162 | true 163 | false 164 | false 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | ${CONTEXT_WEB}/owners/find 179 | GET 180 | true 181 | false 182 | true 183 | false 184 | false 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | ${CONTEXT_WEB}/owners?lastName= 199 | GET 200 | true 201 | false 202 | true 203 | false 204 | false 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | ${CONTEXT_WEB}/owners/${count} 219 | GET 220 | true 221 | false 222 | true 223 | false 224 | false 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | ${CONTEXT_WEB}/owners/${count}/edit 239 | GET 240 | true 241 | false 242 | true 243 | false 244 | false 245 | 246 | 247 | 248 | 249 | true 250 | 251 | 252 | 253 | false 254 | firstName=Test&lastName=${count}&address=1234+Test+St.&city=TestCity&telephone=612345678 255 | = 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | ${CONTEXT_WEB}/owners/${count}/edit 266 | POST 267 | true 268 | false 269 | true 270 | false 271 | false 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | ${CONTEXT_WEB}/owners/${count}/pets/${petCount}/visits/new 286 | GET 287 | true 288 | false 289 | true 290 | false 291 | false 292 | 293 | 294 | 295 | 296 | true 297 | 298 | 299 | 300 | false 301 | date=2013%2F02%2F22&description=visit 302 | = 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | ${CONTEXT_WEB}/owners/${count}/pets/${petCount}/visits/new 313 | POST 314 | true 315 | false 316 | true 317 | false 318 | false 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | ${CONTEXT_WEB}/owners/${count} 333 | GET 334 | true 335 | false 336 | true 337 | false 338 | false 339 | 340 | 341 | 342 | 343 | false 344 | 345 | saveConfig 346 | 347 | 348 | true 349 | true 350 | true 351 | 352 | true 353 | true 354 | true 355 | true 356 | false 357 | true 358 | true 359 | false 360 | false 361 | false 362 | false 363 | false 364 | false 365 | false 366 | false 367 | 0 368 | true 369 | true 370 | 371 | 372 | 373 | 374 | 375 | 376 | false 377 | 378 | saveConfig 379 | 380 | 381 | true 382 | true 383 | true 384 | 385 | true 386 | true 387 | true 388 | true 389 | false 390 | true 391 | true 392 | false 393 | false 394 | false 395 | false 396 | false 397 | false 398 | false 399 | false 400 | 0 401 | true 402 | true 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | --------------------------------------------------------------------------------