├── .gitignore ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main ├── java │ └── sample │ │ └── petclinic │ │ ├── Application.java │ │ ├── CustomErrorController.java │ │ ├── ServletInitializer.java │ │ ├── model │ │ ├── BaseEntity.java │ │ ├── NamedEntity.java │ │ ├── Owner.java │ │ ├── Person.java │ │ ├── Pet.java │ │ ├── PetType.java │ │ ├── Specialty.java │ │ ├── Vet.java │ │ ├── VetAddress.java │ │ ├── Visit.java │ │ └── package-info.java │ │ └── repository │ │ ├── OwnerRepository.java │ │ ├── PetRepository.java │ │ ├── PetTypeRepository.java │ │ ├── SpecialtyRepository.java │ │ ├── VetAddressRepository.java │ │ ├── VetRepository.java │ │ └── VisitRepository.java └── resources │ ├── application.properties │ ├── data-hsqldb.sql │ └── schema-hsqldb.sql └── test ├── java └── sample │ └── petclinic │ ├── BaseIntegrationTest.java │ ├── OwnersGetTests.java │ ├── PetsGetTest.java │ └── VetsGetTest.java └── resources └── application.properties /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .gradle 3 | .idea 4 | *.ids 5 | *.iml 6 | *.ipr 7 | *.iws -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Spring Boot PetClinic API 2 | ========================= 3 | 4 | Spring Boot project with the use of Spring Data REST to expose a business model of Spring's PetClinic application over REST. See the walkthrough here: http://blog.codeleak.pl/2014/10/exposing-spring-data-repositories-over-rest.html 5 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '1.5.6.RELEASE' 4 | } 5 | repositories { 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 10 | } 11 | } 12 | 13 | apply plugin: 'java' 14 | apply plugin: 'spring-boot' 15 | apply plugin: 'war' 16 | 17 | 18 | war { 19 | baseName = 'spring-boot-petclinic-api' 20 | version = '0.0.1-SNAPSHOT' 21 | } 22 | sourceCompatibility = 1.8 23 | targetCompatibility = 1.8 24 | 25 | repositories { 26 | mavenCentral() 27 | } 28 | 29 | configurations { 30 | providedRuntime 31 | } 32 | 33 | dependencies { 34 | /* Bare minumum to get started with Spring Data REST */ 35 | compile("org.springframework.boot:spring-boot-starter-web") 36 | compile("org.springframework.boot:spring-boot-starter-data-jpa") 37 | compile("org.springframework.boot:spring-boot-starter-data-rest") 38 | // https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310 39 | compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") 40 | compile("org.hsqldb:hsqldb") 41 | testCompile("org.springframework.boot:spring-boot-starter-test") 42 | /* JUnitParams for parameterized tests */ 43 | testCompile "pl.pragmatists:JUnitParams:1.0.6" 44 | } 45 | 46 | bootRun { 47 | // It is for running application with profiles 48 | // e.g. gradle bootRun -Dspring.profiles.active=h2,dev 49 | systemProperties = System.properties 50 | } 51 | 52 | task wrapper(type: Wrapper) { 53 | gradleVersion = '4.1' 54 | } 55 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kolorobot/spring-boot-petclinic-api/a86e05e20ceee52c2d46f0dd8e2f700fcee1e53f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Apr 07 20:54:54 CEST 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'spring-boot-petclinic-api' 2 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/Application.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.autoconfigure.domain.EntityScan; 6 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters; 9 | import org.springframework.web.cors.CorsConfiguration; 10 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 11 | import org.springframework.web.filter.CorsFilter; 12 | 13 | @EntityScan(basePackageClasses = {Application.class, Jsr310JpaConverters.class}) 14 | @SpringBootApplication 15 | public class Application { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | 21 | // CORS. See https://jira.spring.io/browse/DATAREST-573 22 | @Bean 23 | public FilterRegistrationBean corsFilter() { 24 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 25 | CorsConfiguration config = new CorsConfiguration(); 26 | config.setAllowCredentials(true); 27 | config.addAllowedOrigin("*"); 28 | config.addAllowedHeader("*"); 29 | config.addAllowedMethod("*"); 30 | source.registerCorsConfiguration("/**", config); 31 | FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); 32 | bean.setOrder(0); 33 | return bean; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/CustomErrorController.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.boot.autoconfigure.web.ErrorAttributes; 5 | import org.springframework.boot.autoconfigure.web.ErrorController; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | import org.springframework.web.context.request.RequestAttributes; 10 | import org.springframework.web.context.request.ServletRequestAttributes; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | import java.time.LocalDateTime; 15 | import java.time.ZoneId; 16 | import java.util.Map; 17 | 18 | @RestController 19 | @RequestMapping("${server.error.path:/error}") 20 | public class CustomErrorController implements ErrorController { 21 | 22 | private final ErrorAttributes errorAttributes; 23 | 24 | @Value("${server.error.path:/error}") 25 | private String serverErrorPath; 26 | 27 | public CustomErrorController(ErrorAttributes errorAttributes) { 28 | this.errorAttributes = errorAttributes; 29 | } 30 | 31 | @RequestMapping 32 | public ResponseEntity handleError(HttpServletRequest request, HttpServletResponse response) { 33 | return ResponseEntity.status(response.getStatus()).body(getError(getErrorAttributes(request))); 34 | } 35 | 36 | @Override 37 | public String getErrorPath() { 38 | return serverErrorPath; 39 | } 40 | 41 | private Map getErrorAttributes(HttpServletRequest request) { 42 | RequestAttributes requestAttributes = new ServletRequestAttributes(request); 43 | return errorAttributes.getErrorAttributes(requestAttributes, true); 44 | } 45 | 46 | private Error getError(Map errorAttrributes) { 47 | Error error = new Error(); 48 | error.setTimestamp(LocalDateTime.now(ZoneId.of("UTC"))); 49 | error.setMessage((String) errorAttrributes.get("message")); 50 | error.setError((String) errorAttrributes.get("error")); 51 | error.setPath((String) errorAttrributes.get("path")); 52 | return error; 53 | } 54 | 55 | private static class Error { 56 | private LocalDateTime timestamp; 57 | private String error; 58 | private String message; 59 | private String path; 60 | 61 | public LocalDateTime getTimestamp() { 62 | return timestamp; 63 | } 64 | 65 | void setTimestamp(LocalDateTime timestamp) { 66 | this.timestamp = timestamp; 67 | } 68 | 69 | public String getError() { 70 | return error; 71 | } 72 | 73 | void setError(String error) { 74 | this.error = error; 75 | } 76 | 77 | public String getMessage() { 78 | return message; 79 | } 80 | 81 | void setMessage(String message) { 82 | this.message = message; 83 | } 84 | 85 | public String getPath() { 86 | return path; 87 | } 88 | 89 | void setPath(String path) { 90 | this.path = path; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/ServletInitializer.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic; 2 | 3 | import org.springframework.boot.builder.SpringApplicationBuilder; 4 | import org.springframework.boot.web.support.SpringBootServletInitializer; 5 | 6 | public class ServletInitializer extends SpringBootServletInitializer { 7 | 8 | @Override 9 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 10 | return application.sources(Application.class); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/BaseEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.model; 17 | 18 | import com.fasterxml.jackson.annotation.JsonIgnore; 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 needing this property. 27 | * 28 | * @author Ken Krebs 29 | * @author Juergen Hoeller 30 | */ 31 | @MappedSuperclass 32 | public class BaseEntity { 33 | @Id 34 | @GeneratedValue(strategy = GenerationType.IDENTITY) 35 | protected Integer id; 36 | 37 | 38 | public void setId(Integer id) { 39 | this.id = id; 40 | } 41 | 42 | public Integer getId() { 43 | return id; 44 | } 45 | 46 | @JsonIgnore 47 | public boolean isNew() { 48 | return (this.id == null); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/NamedEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.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 | 36 | public void setName(String name) { 37 | this.name = name; 38 | } 39 | 40 | public String getName() { 41 | return this.name; 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return this.getName(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/Owner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.model; 17 | 18 | import org.hibernate.validator.constraints.NotEmpty; 19 | import org.springframework.core.style.ToStringCreator; 20 | 21 | import javax.persistence.*; 22 | import javax.validation.constraints.Digits; 23 | import java.util.Set; 24 | 25 | /** 26 | * Simple JavaBean domain object representing an owner. 27 | * 28 | * @author Ken Krebs 29 | * @author Juergen Hoeller 30 | * @author Sam Brannen 31 | * @author Michael Isvy 32 | */ 33 | @Entity 34 | @Table(name = "owners") 35 | public class Owner extends Person { 36 | @Column(name = "address") 37 | @NotEmpty 38 | private String address; 39 | 40 | @Column(name = "city") 41 | @NotEmpty 42 | private String city; 43 | 44 | @Column(name = "telephone") 45 | @NotEmpty 46 | @Digits(fraction = 0, integer = 10) 47 | private String telephone; 48 | 49 | @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true) 50 | private Set pets; 51 | 52 | public Set getPets() { 53 | return pets; 54 | } 55 | 56 | public String getAddress() { 57 | return this.address; 58 | } 59 | 60 | public void setAddress(String address) { 61 | this.address = address; 62 | } 63 | 64 | public String getCity() { 65 | return this.city; 66 | } 67 | 68 | public void setCity(String city) { 69 | this.city = city; 70 | } 71 | 72 | public String getTelephone() { 73 | return this.telephone; 74 | } 75 | 76 | public void setTelephone(String telephone) { 77 | this.telephone = telephone; 78 | } 79 | 80 | 81 | @Override 82 | public String toString() { 83 | return new ToStringCreator(this) 84 | 85 | .append("id", this.getId()) 86 | .append("new", this.isNew()) 87 | .append("lastName", this.getLastName()) 88 | .append("firstName", this.getFirstName()) 89 | .append("address", this.address) 90 | .append("city", this.city) 91 | .append("telephone", this.telephone) 92 | .toString(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/Person.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.model; 17 | 18 | import javax.persistence.Column; 19 | import javax.persistence.MappedSuperclass; 20 | 21 | import org.hibernate.validator.constraints.NotEmpty; 22 | 23 | /** 24 | * Simple JavaBean domain object representing an person. 25 | * 26 | * @author Ken Krebs 27 | */ 28 | @MappedSuperclass 29 | public class Person extends BaseEntity { 30 | 31 | @Column(name = "first_name") 32 | @NotEmpty 33 | protected String firstName; 34 | 35 | @Column(name = "last_name") 36 | @NotEmpty 37 | protected String lastName; 38 | 39 | public String getFirstName() { 40 | return this.firstName; 41 | } 42 | 43 | public void setFirstName(String firstName) { 44 | this.firstName = firstName; 45 | } 46 | 47 | public String getLastName() { 48 | return this.lastName; 49 | } 50 | 51 | public void setLastName(String lastName) { 52 | this.lastName = lastName; 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/Pet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.model; 17 | 18 | import org.springframework.format.annotation.DateTimeFormat; 19 | 20 | import javax.persistence.*; 21 | import java.time.LocalDate; 22 | import java.util.Set; 23 | 24 | /** 25 | * Simple business object representing a pet. 26 | * 27 | * @author Ken Krebs 28 | * @author Juergen Hoeller 29 | * @author Sam Brannen 30 | */ 31 | @Entity 32 | @Table(name = "pets") 33 | public class Pet extends NamedEntity { 34 | 35 | @Column(name = "birth_date") 36 | // @Temporal(TemporalType.DATE) 37 | @DateTimeFormat(pattern = "yyyy/MM/dd") 38 | // @JsonFormat(pattern = "yyyy/MM/dd") 39 | private LocalDate birthDate; 40 | 41 | @ManyToOne 42 | @JoinColumn(name = "type_id") 43 | private PetType type; 44 | 45 | @ManyToOne(cascade = CascadeType.ALL, optional = true) // as defined in schema 46 | @JoinColumn(name = "owner_id") 47 | private Owner owner; 48 | 49 | @OneToMany(cascade = CascadeType.ALL, mappedBy = "pet", fetch = FetchType.EAGER) 50 | private Set visits; 51 | 52 | 53 | public void setBirthDate(LocalDate birthDate) { 54 | this.birthDate = birthDate; 55 | } 56 | 57 | public LocalDate getBirthDate() { 58 | return this.birthDate; 59 | } 60 | 61 | public void setType(PetType type) { 62 | this.type = type; 63 | } 64 | 65 | public PetType getType() { 66 | return this.type; 67 | } 68 | 69 | protected void setOwner(Owner owner) { 70 | this.owner = owner; 71 | } 72 | 73 | public Owner getOwner() { 74 | return this.owner; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/PetType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.model; 17 | 18 | import javax.persistence.Entity; 19 | import javax.persistence.Table; 20 | 21 | /** 22 | * @author Juergen Hoeller 23 | */ 24 | @Entity 25 | @Table(name = "types") 26 | public class PetType extends NamedEntity { 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/Specialty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.model; 17 | 18 | import javax.persistence.Entity; 19 | import javax.persistence.Table; 20 | 21 | /** 22 | * Models a {@link Vet Vet's} specialty (for example, dentistry). 23 | * 24 | * @author Juergen Hoeller 25 | */ 26 | @Entity 27 | @Table(name = "specialties") 28 | public class Specialty extends NamedEntity { 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/Vet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.model; 17 | 18 | import javax.persistence.*; 19 | import java.util.Set; 20 | 21 | /** 22 | * Simple JavaBean domain object representing a veterinarian. 23 | * 24 | * @author Ken Krebs 25 | * @author Juergen Hoeller 26 | * @author Sam Brannen 27 | * @author Arjen Poutsma 28 | */ 29 | @Entity 30 | @Table(name = "vets", 31 | uniqueConstraints = 32 | @UniqueConstraint(columnNames = {"first_name", "last_name"}) 33 | ) 34 | public class Vet extends Person { 35 | 36 | @ManyToMany(fetch = FetchType.EAGER) 37 | @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), 38 | inverseJoinColumns = @JoinColumn(name = "specialty_id")) 39 | private Set specialties; 40 | 41 | public Set getSpecialties() { 42 | return specialties; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/VetAddress.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic.model; 2 | 3 | import org.hibernate.validator.constraints.NotBlank; 4 | 5 | import javax.persistence.*; 6 | 7 | @Entity 8 | @Table(name = "vet_addresses") 9 | public class VetAddress extends BaseEntity { 10 | 11 | @Column(name = "postal_code") 12 | @NotBlank 13 | private String postalCode; 14 | 15 | @Column(name = "city") 16 | @NotBlank 17 | private String city; 18 | 19 | @Column(name = "province") 20 | @NotBlank 21 | private String province; 22 | 23 | @OneToOne(optional = false) 24 | @JoinColumn(name = "vet_id") 25 | private Vet vet; 26 | 27 | public String getPostalCode() { 28 | return postalCode; 29 | } 30 | 31 | public void setPostalCode(String postalCode) { 32 | this.postalCode = postalCode; 33 | } 34 | 35 | public String getProvince() { 36 | return province; 37 | } 38 | 39 | public void setProvince(String province) { 40 | this.province = province; 41 | } 42 | 43 | public String getCity() { 44 | return city; 45 | } 46 | 47 | public void setCity(String city) { 48 | this.city = city; 49 | } 50 | 51 | public Vet getVet() { 52 | return vet; 53 | } 54 | 55 | public void setPerson(Vet vet) { 56 | this.vet = vet; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/Visit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.model; 17 | 18 | import org.hibernate.validator.constraints.NotEmpty; 19 | import org.springframework.format.annotation.DateTimeFormat; 20 | 21 | import javax.persistence.*; 22 | import java.time.LocalDateTime; 23 | 24 | /** 25 | * Simple JavaBean domain object representing a visit. 26 | * 27 | * @author Ken Krebs 28 | */ 29 | @Entity 30 | @Table(name = "visits") 31 | public class Visit extends BaseEntity { 32 | 33 | /** 34 | * Holds value of property date. 35 | */ 36 | @Column(name = "visit_date") 37 | // @Temporal(TemporalType.TIMESTAMP) 38 | @DateTimeFormat(pattern = "yyyy/MM/dd") 39 | // @JsonFormat(pattern = "yyyy/MM/dd") 40 | private LocalDateTime date; 41 | 42 | /** 43 | * Holds value of property description. 44 | */ 45 | @NotEmpty 46 | @Column(name = "description") 47 | private String description; 48 | 49 | /** 50 | * Holds value of property pet. 51 | */ 52 | @ManyToOne 53 | @JoinColumn(name = "pet_id") 54 | private Pet pet; 55 | 56 | 57 | /** 58 | * Creates a new instance of Visit for the current date 59 | */ 60 | public Visit() { 61 | this.date = LocalDateTime.now(); 62 | } 63 | 64 | 65 | /** 66 | * Getter for property date. 67 | * 68 | * @return Value of property date. 69 | */ 70 | public LocalDateTime getDate() { 71 | return this.date; 72 | } 73 | 74 | /** 75 | * Setter for property date. 76 | * 77 | * @param date New value of property date. 78 | */ 79 | public void setDate(LocalDateTime date) { 80 | this.date = date; 81 | } 82 | 83 | /** 84 | * Getter for property description. 85 | * 86 | * @return Value of property description. 87 | */ 88 | public String getDescription() { 89 | return this.description; 90 | } 91 | 92 | /** 93 | * Setter for property description. 94 | * 95 | * @param description New value of property description. 96 | */ 97 | public void setDescription(String description) { 98 | this.description = description; 99 | } 100 | 101 | /** 102 | * Getter for property pet. 103 | * 104 | * @return Value of property pet. 105 | */ 106 | public Pet getPet() { 107 | return this.pet; 108 | } 109 | 110 | /** 111 | * Setter for property pet. 112 | * 113 | * @param pet New value of property pet. 114 | */ 115 | public void setPet(Pet pet) { 116 | this.pet = pet; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/model/package-info.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 4 | * The classes in this package represent PetClinic's business layer. 5 | * 6 | */ 7 | package sample.petclinic.model; 8 | 9 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/repository/OwnerRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | /* 17 | * Copyright 2002-2013 the original author or authors. 18 | * 19 | * Licensed under the Apache License, Version 2.0 (the "License"); 20 | * you may not use this file except in compliance with the License. 21 | * You may obtain a copy of the License at 22 | * 23 | * http://www.apache.org/licenses/LICENSE-2.0 24 | * 25 | * Unless required by applicable law or agreed to in writing, software 26 | * distributed under the License is distributed on an "AS IS" BASIS, 27 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | * See the License for the specific language governing permissions and 29 | * limitations under the License. 30 | */ 31 | package sample.petclinic.repository; 32 | 33 | import org.springframework.data.repository.PagingAndSortingRepository; 34 | import org.springframework.data.repository.query.Param; 35 | import sample.petclinic.model.Owner; 36 | 37 | import java.util.List; 38 | 39 | public interface OwnerRepository extends PagingAndSortingRepository { 40 | List findBylastName(@Param("lastName") String lastName); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/repository/PetRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.repository; 17 | 18 | import org.springframework.data.repository.PagingAndSortingRepository; 19 | import sample.petclinic.model.Pet; 20 | 21 | public interface PetRepository extends PagingAndSortingRepository { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/repository/PetTypeRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | /* 17 | * Copyright 2002-2013 the original author or authors. 18 | * 19 | * Licensed under the Apache License, Version 2.0 (the "License"); 20 | * you may not use this file except in compliance with the License. 21 | * You may obtain a copy of the License at 22 | * 23 | * http://www.apache.org/licenses/LICENSE-2.0 24 | * 25 | * Unless required by applicable law or agreed to in writing, software 26 | * distributed under the License is distributed on an "AS IS" BASIS, 27 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | * See the License for the specific language governing permissions and 29 | * limitations under the License. 30 | */ 31 | package sample.petclinic.repository; 32 | 33 | import org.springframework.data.repository.PagingAndSortingRepository; 34 | import sample.petclinic.model.PetType; 35 | 36 | public interface PetTypeRepository extends PagingAndSortingRepository { 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/repository/SpecialtyRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | /* 17 | * Copyright 2002-2013 the original author or authors. 18 | * 19 | * Licensed under the Apache License, Version 2.0 (the "License"); 20 | * you may not use this file except in compliance with the License. 21 | * You may obtain a copy of the License at 22 | * 23 | * http://www.apache.org/licenses/LICENSE-2.0 24 | * 25 | * Unless required by applicable law or agreed to in writing, software 26 | * distributed under the License is distributed on an "AS IS" BASIS, 27 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 28 | * See the License for the specific language governing permissions and 29 | * limitations under the License. 30 | */ 31 | package sample.petclinic.repository; 32 | 33 | import org.springframework.data.repository.PagingAndSortingRepository; 34 | import sample.petclinic.model.Specialty; 35 | 36 | public interface SpecialtyRepository extends PagingAndSortingRepository { 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/repository/VetAddressRepository.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic.repository; 2 | 3 | import org.springframework.data.repository.PagingAndSortingRepository; 4 | import sample.petclinic.model.VetAddress; 5 | 6 | public interface VetAddressRepository extends PagingAndSortingRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/repository/VetRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.repository; 17 | 18 | import org.springframework.data.repository.PagingAndSortingRepository; 19 | import sample.petclinic.model.Vet; 20 | 21 | 22 | public interface VetRepository extends PagingAndSortingRepository { 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/sample/petclinic/repository/VisitRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2013 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 | package sample.petclinic.repository; 17 | 18 | import org.springframework.data.repository.PagingAndSortingRepository; 19 | import sample.petclinic.model.Visit; 20 | 21 | 22 | public interface VisitRepository extends PagingAndSortingRepository { 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.platform = hsqldb 2 | spring.jpa.generate-ddl = false 3 | spring.jpa.hibernate.ddl-auto = none 4 | spring.jpa.show-sql = false 5 | 6 | server.error.path=/error 7 | spring.jackson.serialization.write_dates_as_timestamps=false -------------------------------------------------------------------------------- /src/main/resources/data-hsqldb.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/schema-hsqldb.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 | DROP TABLE vet_addresses IF EXISTS; 9 | 10 | CREATE TABLE vets ( 11 | id INTEGER IDENTITY PRIMARY KEY, 12 | first_name VARCHAR(30), 13 | last_name VARCHAR(30), 14 | UNIQUE (first_name, last_name) 15 | ); 16 | CREATE INDEX vets_last_name ON vets (last_name); 17 | 18 | CREATE TABLE specialties ( 19 | id INTEGER IDENTITY PRIMARY KEY, 20 | name VARCHAR(80) 21 | ); 22 | CREATE INDEX specialties_name ON specialties (name); 23 | 24 | CREATE TABLE vet_specialties ( 25 | vet_id INTEGER NOT NULL, 26 | specialty_id INTEGER NOT NULL 27 | ); 28 | ALTER TABLE vet_specialties ADD CONSTRAINT fk_vet_specialties_vets FOREIGN KEY (vet_id) REFERENCES vets (id); 29 | ALTER TABLE vet_specialties ADD CONSTRAINT fk_vet_specialties_specialties FOREIGN KEY (specialty_id) REFERENCES specialties (id); 30 | 31 | CREATE TABLE types ( 32 | id INTEGER IDENTITY PRIMARY KEY, 33 | name VARCHAR(80) 34 | ); 35 | CREATE INDEX types_name ON types (name); 36 | 37 | CREATE TABLE owners ( 38 | id INTEGER IDENTITY PRIMARY KEY, 39 | first_name VARCHAR(30), 40 | last_name VARCHAR(30), 41 | address VARCHAR(255), 42 | city VARCHAR(80), 43 | telephone VARCHAR(20) 44 | ); 45 | CREATE INDEX owners_last_name ON owners (last_name); 46 | 47 | CREATE TABLE pets ( 48 | id INTEGER IDENTITY PRIMARY KEY, 49 | name VARCHAR(30), 50 | birth_date DATE, 51 | type_id INTEGER NOT NULL, 52 | owner_id INTEGER NOT NULL 53 | ); 54 | ALTER TABLE pets ADD CONSTRAINT fk_pets_owners FOREIGN KEY (owner_id) REFERENCES owners (id); 55 | ALTER TABLE pets ADD CONSTRAINT fk_pets_types FOREIGN KEY (type_id) REFERENCES types (id); 56 | CREATE INDEX pets_name ON pets (name); 57 | 58 | CREATE TABLE visits ( 59 | id INTEGER IDENTITY PRIMARY KEY, 60 | pet_id INTEGER NOT NULL, 61 | visit_date DATE, 62 | description VARCHAR(255) 63 | ); 64 | ALTER TABLE visits ADD CONSTRAINT fk_visits_pets FOREIGN KEY (pet_id) REFERENCES pets (id); 65 | CREATE INDEX visits_pet_id ON visits (pet_id); 66 | 67 | CREATE TABLE vet_addresses ( 68 | id INTEGER IDENTITY PRIMARY KEY, 69 | postal_code VARCHAR(10), 70 | province VARCHAR(30), 71 | city VARCHAR(100), 72 | vet_id INTEGER NOT NULL 73 | ); 74 | 75 | ALTER TABLE vet_addresses ADD CONSTRAINT fk_vet_addresses_vets FOREIGN KEY (vet_id) REFERENCES vets (id); 76 | CREATE INDEX vet_addresses_vet_id ON vet_addresses (vet_id); -------------------------------------------------------------------------------- /src/test/java/sample/petclinic/BaseIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic; 2 | 3 | import junitparams.JUnitParamsRunner; 4 | import org.junit.Before; 5 | import org.junit.ClassRule; 6 | import org.junit.Rule; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Value; 12 | import org.springframework.boot.test.web.client.TestRestTemplate; 13 | import org.springframework.boot.test.context.SpringBootTest; 14 | import org.springframework.test.context.junit4.rules.SpringClassRule; 15 | import org.springframework.test.context.junit4.rules.SpringMethodRule; 16 | import org.springframework.web.util.UriComponentsBuilder; 17 | 18 | import java.util.concurrent.TimeUnit; 19 | 20 | @RunWith(JUnitParamsRunner.class) 21 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class) 22 | public abstract class BaseIntegrationTest { 23 | 24 | @ClassRule 25 | public static final SpringClassRule SCR = new SpringClassRule(); 26 | 27 | @Rule 28 | public final SpringMethodRule springMethodRule = new SpringMethodRule(); 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(BaseIntegrationTest.class); 31 | 32 | TestRestTemplate restTemplate = new TestRestTemplate(); 33 | 34 | /* port the application is running */ 35 | @Value("${local.server.port}") 36 | private int port; 37 | 38 | @Before 39 | public void setUp() throws Exception { 40 | LOG.info("\n\n\tLocal server port: {}\n", port); 41 | } 42 | 43 | public UriComponentsBuilder localUriBuilder() { 44 | return UriComponentsBuilder.fromHttpUrl("http://localhost:" + port); 45 | } 46 | 47 | @Test 48 | public void simulatesLongRunningOperation() throws InterruptedException { 49 | Thread.sleep(TimeUnit.SECONDS.toMillis(5)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/sample/petclinic/OwnersGetTests.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic; 2 | 3 | import junitparams.Parameters; 4 | import org.junit.Test; 5 | import org.springframework.core.ParameterizedTypeReference; 6 | import org.springframework.hateoas.Resource; 7 | import org.springframework.http.ResponseEntity; 8 | import sample.petclinic.model.Owner; 9 | 10 | import java.net.URI; 11 | 12 | import static junitparams.JUnitParamsRunner.$; 13 | import static org.junit.Assert.assertEquals; 14 | import static org.springframework.http.HttpMethod.GET; 15 | 16 | public class OwnersGetTests extends BaseIntegrationTest { 17 | 18 | @Test 19 | public void getsOwnerResource() { 20 | // arrange 21 | URI uri = localUriBuilder().path("owners/{id}") 22 | .buildAndExpand(1).toUri(); 23 | ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() { 24 | }; 25 | // act 26 | ResponseEntity> responseEntity = 27 | restTemplate.exchange(uri, GET, null, responseType); 28 | 29 | // assert 30 | Owner owner = responseEntity.getBody().getContent(); 31 | assertEquals("George", owner.getFirstName()); 32 | } 33 | 34 | @Test 35 | @Parameters 36 | public void getsOwnerEntity(String expectedName, int id) { 37 | // arrange 38 | URI uri = localUriBuilder().path("owners/{id}") 39 | .buildAndExpand(id).toUri(); 40 | // act 41 | ResponseEntity responseEntity = restTemplate.getForEntity(uri, Owner.class); 42 | // assert 43 | Owner owner = responseEntity.getBody(); 44 | assertEquals(expectedName, owner.getFirstName()); 45 | } 46 | 47 | public Object[] parametersForGetsOwnerEntity() { 48 | return $( 49 | $("George", 1), 50 | $("Betty", 2), 51 | $("Eduardo", 3), 52 | $("Harold", 4) 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/sample/petclinic/PetsGetTest.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic; 2 | 3 | import junitparams.Parameters; 4 | import org.junit.Test; 5 | import org.springframework.core.ParameterizedTypeReference; 6 | import org.springframework.hateoas.Resource; 7 | import org.springframework.http.ResponseEntity; 8 | import sample.petclinic.model.Pet; 9 | 10 | import java.net.URI; 11 | 12 | import static junitparams.JUnitParamsRunner.$; 13 | import static org.junit.Assert.assertEquals; 14 | import static org.springframework.http.HttpMethod.GET; 15 | 16 | 17 | public class PetsGetTest extends BaseIntegrationTest { 18 | 19 | @Test 20 | public void getsPetResource() { 21 | // arrange 22 | URI uri = localUriBuilder().path("pets/{id}") 23 | .buildAndExpand(1).toUri(); 24 | ParameterizedTypeReference> responseType 25 | = new ParameterizedTypeReference>() {}; 26 | 27 | // act 28 | ResponseEntity> responseEntity 29 | = restTemplate.exchange(uri, GET, null, responseType); 30 | 31 | // assert 32 | Pet vet = responseEntity.getBody().getContent(); 33 | assertEquals("Leo", vet.getName()); 34 | } 35 | 36 | @Test 37 | @Parameters 38 | public void getsPetEntity(String expectedName, int id) { 39 | // arrange 40 | URI uri = localUriBuilder().path("pets/{id}") 41 | .buildAndExpand(id).toUri(); 42 | // act 43 | ResponseEntity responseEntity 44 | = restTemplate.getForEntity(uri, Pet.class); 45 | 46 | // assert 47 | Pet vet = responseEntity.getBody(); 48 | assertEquals(expectedName, vet.getName()); 49 | } 50 | 51 | public Object[] parametersForGetsPetEntity() { 52 | return $( 53 | $("Leo", 1), 54 | $("Basil", 2), 55 | $("Rosy", 3), 56 | $("Jewel", 4) 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/sample/petclinic/VetsGetTest.java: -------------------------------------------------------------------------------- 1 | package sample.petclinic; 2 | 3 | import junitparams.Parameters; 4 | import org.junit.Test; 5 | import org.springframework.core.ParameterizedTypeReference; 6 | import org.springframework.hateoas.Resource; 7 | import org.springframework.http.ResponseEntity; 8 | import sample.petclinic.model.Vet; 9 | 10 | import java.net.URI; 11 | 12 | import static junitparams.JUnitParamsRunner.$; 13 | import static org.junit.Assert.assertEquals; 14 | import static org.springframework.http.HttpMethod.GET; 15 | 16 | 17 | public class VetsGetTest extends BaseIntegrationTest { 18 | 19 | @Test 20 | public void getsVetResource() { 21 | // arrange 22 | URI uri = localUriBuilder().path("vets/{id}") 23 | .buildAndExpand(1).toUri(); 24 | ParameterizedTypeReference> responseType 25 | = new ParameterizedTypeReference>() {}; 26 | 27 | // act 28 | ResponseEntity> responseEntity 29 | = restTemplate.exchange(uri, GET, null, responseType); 30 | 31 | // assert 32 | Vet vet = responseEntity.getBody().getContent(); 33 | assertEquals("James", vet.getFirstName()); 34 | } 35 | 36 | @Test 37 | @Parameters 38 | public void getsVetEntity(String expectedName, int id) { 39 | // arrange 40 | URI uri = localUriBuilder().path("vets/{id}") 41 | .buildAndExpand(id).toUri(); 42 | // act 43 | ResponseEntity responseEntity 44 | = restTemplate.getForEntity(uri, Vet.class); 45 | 46 | // assert 47 | Vet vet = responseEntity.getBody(); 48 | assertEquals(expectedName, vet.getFirstName()); 49 | } 50 | 51 | public Object[] parametersForGetsVetEntity() { 52 | return $( 53 | $("James", 1), 54 | $("Helen", 2), 55 | $("Linda", 3), 56 | $("Rafael", 4) 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.platform = hsqldb 2 | spring.jpa.generate-ddl = false 3 | spring.jpa.hibernate.ddl-auto = none 4 | spring.jpa.show-sql = true --------------------------------------------------------------------------------