petclinic-uncached
Changes
pom.xml 564(+244 -320)
src/main/less/header.less 0(+0 -0)
src/main/less/petclinic.less 4(+2 -2)
src/main/less/responsive.less 0(+0 -0)
src/main/less/typography.less 0(+0 -0)
src/main/resources/templates/error.html 11(+11 -0)
src/main/resources/templates/welcome.html 16(+16 -0)
Details
pom.xml 564(+244 -320)
diff --git a/pom.xml b/pom.xml
index 1b6a5ed..e0477cb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,340 +1,264 @@
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.springframework.samples</groupId>
- <artifactId>springboot-petclinic</artifactId>
- <version>1.4.1</version>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>1.4.1.RELEASE</version>
- </parent>
- <name>petclinic</name>
- <packaging>war</packaging>
-
- <properties>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.springframework.samples</groupId>
+ <artifactId>springboot-petclinic</artifactId>
+ <version>1.4.1</version>
- <!-- Generic properties -->
- <java.version>1.7</java.version>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <docker.image.prefix>arey</docker.image.prefix>
+ <parent>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-parent</artifactId>
+ <version>1.4.1.RELEASE</version>
+ </parent>
+ <name>petclinic</name>
- <!-- Web dependencies -->
- <webjars-bootstrap.version>3.3.6</webjars-bootstrap.version>
- <webjars-jquery-ui.version>1.11.4</webjars-jquery-ui.version>
- <webjars-jquery.version>2.2.4</webjars-jquery.version>
+ <properties>
- <cobertura.version>2.7</cobertura.version>
+ <!-- Generic properties -->
+ <java.version>1.8</java.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- </properties>
+ <!-- Web dependencies -->
+ <webjars-bootstrap.version>3.3.6</webjars-bootstrap.version>
+ <webjars-jquery-ui.version>1.11.4</webjars-jquery-ui.version>
+ <webjars-jquery.version>2.2.4</webjars-jquery.version>
- <dependencies>
- <!-- Spring et Spring Boot dependencies -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-cache</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-jpa</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- <!-- Uncomment bellow lines in order to deploy the Springboot Petlinic WAR file into an external Jetty -->
- <!--exclusions>
- <exclusion>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-tomcat</artifactId>
- </exclusion>
- </exclusions-->
- </dependency>
+ <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
+ <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
- <dependency>
- <groupId>org.apache.tomcat.embed</groupId>
- <artifactId>tomcat-embed-jasper</artifactId>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>jstl</artifactId>
- </dependency>
+ <cobertura.version>2.7</cobertura.version>
- <!-- Databases - Uses HSQL by default -->
- <dependency>
- <groupId>org.hsqldb</groupId>
- <artifactId>hsqldb</artifactId>
- <scope>runtime</scope>
- </dependency>
+ </properties>
- <!-- For MySql only -->
- <!--dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>${mysql-driver.version}</version>
- </dependency-->
+ <dependencies>
+ <!-- Spring and Spring Boot dependencies -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-actuator</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-cache</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-thymeleaf</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
- <!-- EhCache -->
- <dependency>
- <groupId>javax.cache</groupId>
- <artifactId>cache-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.ehcache</groupId>
- <artifactId>ehcache</artifactId>
- </dependency>
+ <!-- Databases - Uses HSQL by default -->
+ <dependency>
+ <groupId>org.hsqldb</groupId>
+ <artifactId>hsqldb</artifactId>
+ <scope>runtime</scope>
+ </dependency>
- <!-- webjars -->
- <dependency>
- <groupId>org.webjars</groupId>
- <artifactId>jquery</artifactId>
- <version>${webjars-jquery.version}</version>
- </dependency>
- <dependency>
- <groupId>org.webjars</groupId>
- <artifactId>jquery-ui</artifactId>
- <version>${webjars-jquery-ui.version}</version>
- </dependency>
- <dependency>
- <groupId>org.webjars</groupId>
- <artifactId>bootstrap</artifactId>
- <version>${webjars-bootstrap.version}</version>
- </dependency>
- <!-- end of webjars -->
+ <!-- EhCache -->
+ <dependency>
+ <groupId>javax.cache</groupId>
+ <artifactId>cache-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.ehcache</groupId>
+ <artifactId>ehcache</artifactId>
+ </dependency>
- </dependencies>
+ <!-- webjars -->
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>webjars-locator</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>jquery</artifactId>
+ <version>${webjars-jquery.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>jquery-ui</artifactId>
+ <version>${webjars-jquery-ui.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>bootstrap</artifactId>
+ <version>${webjars-bootstrap.version}</version>
+ </dependency>
+ <!-- end of webjars -->
- <!-- Maven plugin versions are mentioned in order to guarantee the build reproducibility in the long term -->
- <build>
- <finalName>petclinic</finalName>
- <defaultGoal>install</defaultGoal>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <executions>
- <execution>
- <!-- Spring Boot Actuator displays build-related information if a META-INF/build-info.properties file is present -->
- <goals>
- <goal>build-info</goal>
- </goals>
- <configuration>
- <additionalProperties>
- <encoding.source>${project.build.sourceEncoding}</encoding.source>
- <encoding.reporting>${project.reporting.outputEncoding}</encoding.reporting>
- <java.source>${maven.compiler.source}</java.source>
- <java.target>${maven.compiler.target}</java.target>
- </additionalProperties>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>3.0</version>
- <configuration>
- <compilerArguments>
- <Xlint/>
- </compilerArguments>
- <verbose>true</verbose>
- <source>${java.version}</source>
- <target>${java.version}</target>
- <showWarnings>true</showWarnings>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <version>2.13</version>
- <configuration>
- <includes>
- <include>**/*Tests.java</include>
- </includes>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-eclipse-plugin</artifactId>
- <version>2.9</version>
- <configuration>
- <downloadSources>true</downloadSources>
- <downloadJavadocs>true</downloadJavadocs>
- <wtpversion>2.0</wtpversion>
- <sourceIncludes>
- <sourceInclude>**/*.*</sourceInclude>
- </sourceIncludes>
- <additionalBuildcommands>
- <buildCommand>
- <name>org.springframework.ide.eclipse.core.springbuilder</name>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.m2e.core.maven2Builder</name>
- </buildCommand>
- </additionalBuildcommands>
- <additionalProjectnatures>
- <projectnature>org.eclipse.jdt.core.javanature</projectnature>
- <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
- <projectnature>org.eclipse.m2e.core.maven2Nature</projectnature>
- </additionalProjectnatures>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>cobertura-maven-plugin</artifactId>
- <version>${cobertura.version}</version>
- <configuration>
- <check/>
- </configuration>
- <executions>
- <execution>
- <goals>
- <goal>clean</goal>
- <goal>check</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-devtools</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
- <!-- Spring Boot Actuator displays build-related information if a git.properties file is present at the classpath -->
- <plugin>
- <groupId>pl.project13.maven</groupId>
- <artifactId>git-commit-id-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>revision</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <verbose>true</verbose>
- <dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
- <generateGitPropertiesFile>true</generateGitPropertiesFile>
- <generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties
- </generateGitPropertiesFilename>
- </configuration>
- </plugin>
-
- <plugin>
- <!--
- right now lesscss maven plugin does NOT support @Import from classpath
- https://github.com/marceloverdijk/lesscss-maven-plugin/issues/72
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <!-- Spring Boot Actuator displays build-related information
+ if a META-INF/build-info.properties file is present -->
+ <goals>
+ <goal>build-info</goal>
+ </goals>
+ <configuration>
+ <additionalProperties>
+ <encoding.source>${project.build.sourceEncoding}</encoding.source>
+ <encoding.reporting>${project.reporting.outputEncoding}</encoding.reporting>
+ <java.source>${maven.compiler.source}</java.source>
+ <java.target>${maven.compiler.target}</java.target>
+ </additionalProperties>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>${cobertura.version}</version>
+ <configuration>
+ <check />
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>clean</goal>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
- workaround here will be unpacking the bootstrap on-the-fly
+ <!-- Spring Boot Actuator displays build-related information if a git.properties
+ file is present at the classpath -->
+ <plugin>
+ <groupId>pl.project13.maven</groupId>
+ <artifactId>git-commit-id-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>revision</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <verbose>true</verbose>
+ <dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
+ <generateGitPropertiesFile>true</generateGitPropertiesFile>
+ <generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties
+ </generateGitPropertiesFilename>
+ </configuration>
+ </plugin>
- remove this plugin config when the issue is resolved OR a better resolution is found
- -->
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>unpack</id>
- <phase>process-resources</phase>
- <goals>
- <goal>unpack</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.webjars</groupId>
- <artifactId>bootstrap</artifactId>
- <version>3.3.6</version>
- <overWrite>false</overWrite>
- <outputDirectory>${project.basedir}/src/main/webapp/resources/generated
- </outputDirectory>
- <includes>**/*.less</includes>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- </executions>
- </plugin>
+ <plugin>
+ <!-- right now lesscss maven plugin does NOT support @Import from
+ classpath https://github.com/marceloverdijk/lesscss-maven-plugin/issues/72
+ workaround here will be unpacking the bootstrap on-the-fly remove this plugin
+ config when the issue is resolved OR a better resolution is found -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>unpack</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>unpack</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.webjars</groupId>
+ <artifactId>bootstrap</artifactId>
+ <version>${webjars-bootstrap.version}</version>
+ <overWrite>false</overWrite>
+ <outputDirectory>${project.basedir}/target/less
+ </outputDirectory>
+ <includes>**/*.less</includes>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
- <plugin>
- <!-- refer to dependency plugin comments above -->
- <artifactId>maven-clean-plugin</artifactId>
- <configuration>
- <filesets>
- <fileset>
- <directory>${project.basedir}/src/main/webapp/resources/generated</directory>
- </fileset>
- </filesets>
- </configuration>
- </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-resources</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/less</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/less</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
- <plugin>
- <groupId>org.lesscss</groupId>
- <artifactId>lesscss-maven-plugin</artifactId>
- <version>1.7.0.1.1</version>
- <configuration>
- <sourceDirectory>${project.basedir}/src/main/webapp/resources/less</sourceDirectory>
- <outputDirectory>${project.basedir}/src/main/webapp/resources/generated</outputDirectory>
- <compress>true</compress>
- <includes>
- <include>petclinic.less</include>
- </includes>
- </configuration>
- <executions>
- <execution>
- <phase>process-resources</phase>
- <goals>
- <goal>compile</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>com.spotify</groupId>
- <artifactId>docker-maven-plugin</artifactId>
- <version>0.4.11</version>
- <configuration>
- <imageName>${docker.image.prefix}/${project.artifactId}</imageName>
- <dockerDirectory>src/main/docker</dockerDirectory>
- <resources>
- <resource>
- <targetPath>/</targetPath>
- <directory>${project.build.directory}</directory>
- <include>${project.build.finalName}.war</include>
- </resource>
- </resources>
- <forceTags>true</forceTags>
- <imageTags>
- <imageTag>${project.version}</imageTag>
- <imageTag>latest</imageTag>
- </imageTags>
- <useConfigFile>true</useConfigFile>
- </configuration>
- </plugin>
- </plugins>
- </build>
- <reporting>
- <plugins>
- <!-- integrate maven-cobertura-plugin to project site -->
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>cobertura-maven-plugin</artifactId>
- <version>${cobertura.version}</version>
- <configuration>
- <formats>
- <format>html</format>
- </formats>
- <check/>
- </configuration>
- </plugin>
- </plugins>
- </reporting>
+ <plugin>
+ <groupId>org.lesscss</groupId>
+ <artifactId>lesscss-maven-plugin</artifactId>
+ <version>1.7.0.1.1</version>
+ <configuration>
+ <sourceDirectory>${project.build.directory}/less</sourceDirectory>
+ <outputDirectory>${project.build.directory}/classes/static/resources/css</outputDirectory>
+ <compress>true</compress>
+ <includes>
+ <include>petclinic.less</include>
+ </includes>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <reporting>
+ <plugins>
+ <!-- integrate maven-cobertura-plugin to project site -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>${cobertura.version}</version>
+ <configuration>
+ <formats>
+ <format>html</format>
+ </formats>
+ <check />
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
- <url>demopetclinic</url>
</project>
diff --git a/src/main/java/org/springframework/samples/petclinic/model/Pet.java b/src/main/java/org/springframework/samples/petclinic/model/Pet.java
index 205d529..d21db69 100644
--- a/src/main/java/org/springframework/samples/petclinic/model/Pet.java
+++ b/src/main/java/org/springframework/samples/petclinic/model/Pet.java
@@ -34,6 +34,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -62,7 +63,7 @@ public class Pet extends NamedEntity {
private Owner owner;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "pet", fetch = FetchType.EAGER)
- private Set<Visit> visits;
+ private Set<Visit> visits = new LinkedHashSet<>();
public void setBirthDate(Date birthDate) {
diff --git a/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java b/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
index 456b061..80859de 100644
--- a/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
+++ b/src/main/java/org/springframework/samples/petclinic/PetClinicApplication.java
@@ -18,23 +18,16 @@ package org.springframework.samples.petclinic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.boot.web.support.SpringBootServletInitializer;
/**
* PetClinic Spring Boot Application.
*
*/
@SpringBootApplication
-public class PetClinicApplication extends SpringBootServletInitializer {
+public class PetClinicApplication {
- @Override
- protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
- return application.sources(PetClinicApplication.class);
+ public static void main(String[] args) throws Exception {
+ SpringApplication.run(PetClinicApplication.class, args);
}
- public static void main(String[] args) throws Exception {
- SpringApplication.run(PetClinicApplication.class, args);
- }
-
}
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
index 841d0bc..4b0a0ad 100644
--- a/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/OwnerRepository.java
@@ -17,11 +17,9 @@ package org.springframework.samples.petclinic.repository;
import java.util.Collection;
-import org.springframework.dao.DataAccessException;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.query.Param;
-import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Owner;
/**
@@ -51,7 +49,7 @@ public interface OwnerRepository extends Repository<Owner, Integer> {
* @return the {@link Owner} if found
*/
@Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id")
- Owner findById(@Param("id") int id);
+ Owner findById(@Param("id") Integer id);
/**
* Save an {@link Owner} to the data store, either inserting or updating it.
diff --git a/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java b/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
index 58e73d7..2ddea85 100644
--- a/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
+++ b/src/main/java/org/springframework/samples/petclinic/repository/PetRepository.java
@@ -17,10 +17,8 @@ package org.springframework.samples.petclinic.repository;
import java.util.List;
-import org.springframework.dao.DataAccessException;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
-import org.springframework.samples.petclinic.model.BaseEntity;
import org.springframework.samples.petclinic.model.Pet;
import org.springframework.samples.petclinic.model.PetType;
@@ -47,7 +45,7 @@ public interface PetRepository extends Repository<Pet, Integer> {
* @param id the id to search for
* @return the {@link Pet} if found
*/
- Pet findById(int id);
+ Pet findById(Integer id);
/**
* Save a {@link Pet} to the data store, either inserting or updating it.
diff --git a/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java b/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
index f5ccbed..5c2e47a 100644
--- a/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
+++ b/src/main/java/org/springframework/samples/petclinic/service/ClinicServiceImpl.java
@@ -29,8 +29,8 @@ import javax.cache.annotation.CacheResult;
import java.util.Collection;
/**
- * Mostly used as a facade for all Petclinic controllers
- * Also a placeholder for @Transactional and @CacheResult annotations
+ * Mostly used as a facade for all Petclinic controllers Also a placeholder
+ * for @Transactional and @CacheResult annotations
*
* @author Michael Isvy
*/
@@ -43,7 +43,8 @@ public class ClinicServiceImpl implements ClinicService {
private VisitRepository visitRepository;
@Autowired
- public ClinicServiceImpl(PetRepository petRepository, VetRepository vetRepository, OwnerRepository ownerRepository, VisitRepository visitRepository) {
+ public ClinicServiceImpl(PetRepository petRepository, VetRepository vetRepository, OwnerRepository ownerRepository,
+ VisitRepository visitRepository) {
this.petRepository = petRepository;
this.vetRepository = vetRepository;
this.ownerRepository = ownerRepository;
@@ -74,14 +75,12 @@ public class ClinicServiceImpl implements ClinicService {
ownerRepository.save(owner);
}
-
@Override
@Transactional
public void saveVisit(Visit visit) throws DataAccessException {
visitRepository.save(visit);
}
-
@Override
@Transactional(readOnly = true)
public Pet findPetById(int id) throws DataAccessException {
@@ -101,10 +100,9 @@ public class ClinicServiceImpl implements ClinicService {
return vetRepository.findAll();
}
- @Override
- public Collection<Visit> findVisitsByPetId(int petId) {
- return visitRepository.findByPetId(petId);
- }
-
+ @Override
+ public Collection<Visit> findVisitsByPetId(int petId) {
+ return visitRepository.findByPetId(petId);
+ }
}
diff --git a/src/main/java/org/springframework/samples/petclinic/web/CrashController.java b/src/main/java/org/springframework/samples/petclinic/web/CrashController.java
index 29c55c1..303707b 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/CrashController.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/CrashController.java
@@ -23,18 +23,16 @@ import org.springframework.web.bind.annotation.RequestMethod;
* Controller used to showcase what happens when an exception is thrown
*
* @author Michael Isvy
- * <p/>
- * Also see how the bean of type 'SimpleMappingExceptionResolver' has been declared inside
- * /WEB-INF/mvc-core-config.xml
+ * <p/>
+ * Also see how a view that resolves to "error" has been added ("error.html").
*/
@Controller
public class CrashController {
@RequestMapping(value = "/oups", method = RequestMethod.GET)
public String triggerException() {
- throw new RuntimeException("Expected: controller used to showcase what " +
- "happens when an exception is thrown");
+ throw new RuntimeException(
+ "Expected: controller used to showcase what " + "happens when an exception is thrown");
}
-
}
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VetController.java b/src/main/java/org/springframework/samples/petclinic/web/VetController.java
index 54baf39..5bc343e 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/VetController.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/VetController.java
@@ -18,7 +18,6 @@ package org.springframework.samples.petclinic.web;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
import org.springframework.samples.petclinic.model.Vets;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Controller;
@@ -36,32 +35,28 @@ public class VetController {
private final ClinicService clinicService;
-
@Autowired
public VetController(ClinicService clinicService) {
this.clinicService = clinicService;
}
- @RequestMapping(value = {"/vets.html"})
+ @RequestMapping(value = { "/vets.html" })
public String showVetList(Map<String, Object> model) {
- // Here we are returning an object of type 'Vets' rather than a collection of Vet objects
- // so it is simpler for Object-Xml mapping
+ // Here we are returning an object of type 'Vets' rather than a collection of Vet
+ // objects so it is simpler for Object-Xml mapping
Vets vets = new Vets();
vets.getVetList().addAll(this.clinicService.findVets());
model.put("vets", vets);
return "vets/vetList";
}
- @RequestMapping(value = {"/vets.json", "/vets.xml"})
- public
- @ResponseBody
- Vets showResourcesVetList() {
- // Here we are returning an object of type 'Vets' rather than a collection of Vet objects
- // so it is simpler for JSon/Object mapping
+ @RequestMapping(value = { "/vets.json", "/vets.xml" })
+ public @ResponseBody Vets showResourcesVetList() {
+ // Here we are returning an object of type 'Vets' rather than a collection of Vet
+ // objects so it is simpler for JSon/Object mapping
Vets vets = new Vets();
vets.getVetList().addAll(this.clinicService.findVets());
return vets;
}
-
}
diff --git a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java b/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
index 144eba2..7bd87ef 100644
--- a/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
+++ b/src/main/java/org/springframework/samples/petclinic/web/VisitController.java
@@ -89,10 +89,4 @@ public class VisitController {
}
}
- @RequestMapping(value = "/owners/*/pets/{petId}/visits", method = RequestMethod.GET)
- public String showVisits(@PathVariable int petId, Map<String, Object> model) {
- model.put("visits", this.clinicService.findPetById(petId).getVisits());
- return "visitList";
- }
-
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index db5befa..c1a7ac2 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -4,8 +4,7 @@ spring.datasource.schema=classpath*:db/${database}/schema.sql
spring.datasource.data=classpath*:db/${database}/data.sql
# Web
-spring.mvc.view.prefix=/WEB-INF/jsp/
-spring.mvc.view.suffix=.jsp
+spring.thymeleaf.mode=HTML
# JPA
spring.jpa.hibernate.ddl-auto=none
@@ -18,6 +17,7 @@ management.contextPath=/manage
# Logging
logging.level.org.springframework=INFO
+logging.level.org.springframework.web=DEBUG
# Active Spring profiles
spring.profiles.active=production
src/main/resources/templates/error.html 11(+11 -0)
diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html
new file mode 100644
index 0000000..2b40d7f
--- /dev/null
+++ b/src/main/resources/templates/error.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'error')}">
+
+ <body>
+ <img src="../static/resources/images/pets.png" th:src="@{/resources/images/pets.png}"/>
+ <h2>Something happened...</h2>
+ <p th:text="${message}">Exception message</p>
+ </body>
+
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/fragments/inputField.html b/src/main/resources/templates/fragments/inputField.html
new file mode 100644
index 0000000..7cef1ee
--- /dev/null
+++ b/src/main/resources/templates/fragments/inputField.html
@@ -0,0 +1,26 @@
+<html>
+<body>
+ <form>
+ <th:block th:fragment="input (label, name)">
+ <div th:with="valid=${!#fields.hasErrors(name)}"
+ th:class="${'form-group' + (valid ? '' : ' has-error')}"
+ class="form-group">
+ <label class="col-sm-2 control-label" th:text="${label}">Label</label>
+ <div class="col-sm-10">
+ <input class="form-control" type="text"
+ th:field="*{__${name}__}" />
+ <span th:if="${valid}"
+ class="glyphicon glyphicon-ok form-control-feedback"
+ aria-hidden="true"></span>
+ <th:block th:if="${!valid}">
+ <span
+ class="glyphicon glyphicon-remove form-control-feedback"
+ aria-hidden="true"></span>
+ <span class="help-inline" th:errors="*{__${name}__}">Error</span>
+ </th:block>
+ </div>
+ </div>
+ </th:block>
+ </form>
+</body>
+</html>
diff --git a/src/main/resources/templates/fragments/layout.html b/src/main/resources/templates/fragments/layout.html
new file mode 100644
index 0000000..1ff2861
--- /dev/null
+++ b/src/main/resources/templates/fragments/layout.html
@@ -0,0 +1,94 @@
+<!doctype html>
+<html th:fragment="layout (template, menu)">
+
+ <head>
+
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <link rel="shortcut icon" type="image/x-icon" th:href="@{/resources/images/favicon.png}">
+
+ <title>PetClinic :: a Spring Framework demonstration</title>
+
+ <!--[if lt IE 9]>
+ <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
+ <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+ <![endif]-->
+
+ <link rel="stylesheet" th:href="@{/resources/css/petclinic.css}"/>
+
+ </head>
+
+<body>
+
+ <nav class="navbar navbar-default" role="navigation">
+ <div class="container">
+ <div class="navbar-header">
+ <a class="navbar-brand" th:href="@{/}"><span></span></a>
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#main-navbar">
+ <span class="sr-only"><os-p>Toggle navigation</os-p></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ </div>
+ <div class="navbar-collapse collapse" id="main-navbar">
+ <ul class="nav navbar-nav navbar-right">
+
+ <li th:fragment="menuItem (path,active,title,glyph,text)" class="active" th:class="${active==menu ? 'active' : ''}">
+ <a th:href="@{__${path}__}" th:title="${title}">
+ <span th:class="'glyphicon glyphicon-'+${glyph}" class="glyphicon glyphicon-home" aria-hidden="true"></span>
+ <span th:text="${text}">Template</span>
+ </a>
+ </li>
+
+ <li th:replace="::menuItem ('/','home','home page','home','Home')">
+ <span class="glyphicon glyphicon-home" aria-hidden="true"></span>
+ <span>Home</span>
+ </li>
+
+ <li th:replace="::menuItem ('/owners/find','owners','find owners','search','Find owners')">
+ <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
+ <span>Find owners</span>
+ </li>
+
+ <li th:replace="::menuItem ('/vets.html','vets','veterinarians','th-list','Veterinarians')">
+ <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
+ <span>Veterinarians</span>
+ </li>
+
+ <li th:replace="::menuItem ('/oups','error','trigger a RuntimeException to see how it is handled','th-warning-sign','Error')">
+ <span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
+ <span>Error</span>
+ </li>
+
+ </ul>
+ </div>
+ </div>
+ </nav>
+ <div class="container-fluid">
+ <div class="container xd-container">
+
+ <div th:replace="${template}"/>
+
+ <br/>
+ <br/>
+ <div class="container">
+ <div class="row">
+ <div class="col-12 text-center">
+ <img src="../static/resources/images/spring-pivotal-logo.png" th:src="@{/resources/images/spring-pivotal-logo.png}"
+ alt="Sponsored by Pivotal"/></div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <script th:src="@{/webjars/jquery/jquery.min.js}"></script>
+ <script th:src="@{/webjars/jquery-ui/jquery-ui.min.js}"></script>
+ <script th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script>
+
+</body>
+
+</html>
diff --git a/src/main/resources/templates/fragments/selectField.html b/src/main/resources/templates/fragments/selectField.html
new file mode 100644
index 0000000..4384744
--- /dev/null
+++ b/src/main/resources/templates/fragments/selectField.html
@@ -0,0 +1,29 @@
+<html>
+<body>
+ <form>
+ <th:block th:fragment="select (label, name, items)">
+ <div th:with="valid=${!#fields.hasErrors(name)}"
+ th:class="${'form-group' + (valid ? '' : ' has-error')}"
+ class="form-group">
+ <label class="col-sm-2 control-label" th:text="${label}">Label</label>
+
+ <div class="col-sm-10">
+ <select th:field="*{__${name}__}">
+ <option th:each="item : ${items}" th:value="${item}"
+ th:text="${item}">dog</option>
+ </select>
+ <span th:if="${valid}"
+ class="glyphicon glyphicon-ok form-control-feedback"
+ aria-hidden="true"></span>
+ <th:block th:if="${!valid}">
+ <span
+ class="glyphicon glyphicon-remove form-control-feedback"
+ aria-hidden="true"></span>
+ <span class="help-inline" th:errors="*{__${name}__}">Error</span>
+ </th:block>
+ </div>
+ </div>
+ </th:block>
+ </form>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/owners/createOrUpdateOwnerForm.html b/src/main/resources/templates/owners/createOrUpdateOwnerForm.html
new file mode 100644
index 0000000..a34a39c
--- /dev/null
+++ b/src/main/resources/templates/owners/createOrUpdateOwnerForm.html
@@ -0,0 +1,30 @@
+<html xmlns:th="http://www.thymeleaf.org"
+ th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
+
+<body>
+
+ <h2>Owner</h2>
+ <form th:object="${owner}" class="form-horizontal" id="add-owner-form" method="post">
+ <div class="form-group has-feedback">
+ <input
+ th:replace="~{fragments/inputField :: input ('First Name', 'firstName')}" />
+ <input
+ th:replace="~{fragments/inputField :: input ('Last Name', 'lastName')}" />
+ <input
+ th:replace="~{fragments/inputField :: input ('Address', 'address')}" />
+ <input
+ th:replace="~{fragments/inputField :: input ('City', 'city')}" />
+ <input
+ th:replace="~{fragments/inputField :: input ('Telephone', 'telephone')}" />
+ </div>
+ <div class="form-group">
+ <div class="col-sm-offset-2 col-sm-10">
+ <button
+ th:with="text=${owner['new']} ? 'Add Owner' : 'Update Owner'"
+ class="btn btn-default" type="submit" th:text="${text}">Add
+ Owner</button>
+ </div>
+ </div>
+ </form>
+</body>
+</html>
diff --git a/src/main/resources/templates/owners/findOwners.html b/src/main/resources/templates/owners/findOwners.html
new file mode 100644
index 0000000..911ac95
--- /dev/null
+++ b/src/main/resources/templates/owners/findOwners.html
@@ -0,0 +1,35 @@
+<html xmlns:th="http://www.thymeleaf.org"
+ th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
+
+<body>
+
+ <h2>Find Owners</h2>
+
+ <form th:object="${owner}" th:action="@{/owners}" method="get"
+ class="form-horizontal" id="search-owner-form">
+ <div class="form-group">
+ <div class="control-group" id="lastName">
+ <label class="col-sm-2 control-label">Last name </label>
+ <div class="col-sm-10">
+ <input class="form-control" th:field="*{lastName}" size="30"
+ maxlength="80" /> <span class="help-inline"><div
+ th:if="${#fields.hasAnyErrors()}">
+ <p th:each="err : ${#fields.allErrors()}" th:text="${err}">Error</p>
+ </div></span>
+ </div>
+ </div>
+ </div>
+ <div class="form-group">
+ <div class="col-sm-offset-2 col-sm-10">
+ <button type="submit" class="btn btn-default">Find
+ Owner</button>
+ </div>
+ </div>
+
+ </form>
+
+ <br />
+ <a class="btn btn-default" th:href="@{/owners/new}">Add Owner</a>
+
+</body>
+</html>
diff --git a/src/main/resources/templates/owners/ownerDetails.html b/src/main/resources/templates/owners/ownerDetails.html
new file mode 100644
index 0000000..746d569
--- /dev/null
+++ b/src/main/resources/templates/owners/ownerDetails.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+
+<html xmlns:th="http://www.thymeleaf.org"
+ th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
+
+ <body>
+
+
+ <h2>Owner Information</h2>
+
+
+ <table class="table table-striped" th:object="${owner}">
+ <tr>
+ <th>Name</th>
+ <td><b th:text="*{firstName + ' ' + lastName}"></b></td>
+ </tr>
+ <tr>
+ <th>Address</th>
+ <td th:text="*{address}" /></td>
+ </tr>
+ <tr>
+ <th>City</th>
+ <td th:text="*{city}" /></td>
+ </tr>
+ <tr>
+ <th>Telephone</th>
+ <td th:text="*{telephone}" /></td>
+ </tr>
+ </table>
+
+ <a th:href="@{{id}/edit(id=${owner.id})}" class="btn btn-default">Edit
+ Owner</a>
+ <a th:href="@{{id}/pets/new(id=${owner.id})}" class="btn btn-default">Add
+ New Pet</a>
+
+ <br />
+ <br />
+ <br />
+ <h2>Pets and Visits</h2>
+
+ <table class="table table-striped">
+
+ <tr th:each="pet : ${owner.pets}">
+ <td valign="top">
+ <dl class="dl-horizontal">
+ <dt>Name</dt>
+ <dd th:text="${pet.name}" /></dd>
+ <dt>Birth Date</dt>
+ <dd
+ th:text="${#calendars.format(pet.birthDate, 'yyyy-MM-dd')}" /></dd>
+ <dt>Type</dt>
+ <dd th:text="${pet.type}" /></dd>
+ </dl>
+ </td>
+ <td valign="top">
+ <table class="table-condensed">
+ <thead>
+ <tr>
+ <th>Visit Date</th>
+ <th>Description</th>
+ </tr>
+ </thead>
+ <tr th:each="visit : ${pet.visits}">
+ <td th:text="${#calendars.format(visit.date, 'yyyy-MM-dd')}"></td>
+ <td th:text="${visit?.description}"></td>
+ </tr>
+ <tr>
+ <td><a
+ th:href="@{{ownerId}/pets/{petId}/edit(ownerId=${owner.id},petId=${pet.id})}">Edit
+ Pet</a></td>
+ <td><a
+ th:href="@{{ownerId}/pets/{petId}/visits/new(ownerId=${owner.id},petId=${pet.id})}">Add
+ Visit</a></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+
+ </table>
+
+ </body>
+
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/owners/ownersList.html b/src/main/resources/templates/owners/ownersList.html
new file mode 100644
index 0000000..dc4c446
--- /dev/null
+++ b/src/main/resources/templates/owners/ownersList.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
+
+ <body>
+
+ <h2>Owners</h2>
+
+ <table id="vets" class="table table-striped">
+ <thead>
+ <tr>
+ <th style="width: 150px;">Name</th>
+ <th style="width: 200px;">Address</th>
+ <th>City</th>
+ <th style="width: 120px">Telephone</th>
+ <th>Pets</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="owner : ${selections}">
+ <td>
+ <a th:href="@{owners/__${owner.id}__}" th:text="${owner.firstName + ' ' + owner.lastName}"/></a>
+ </td>
+ <td th:text="${owner.address}"/>
+ <td th:text="${owner.city}"/>
+ <td th:text="${owner.telephone}"/>
+ <td><span th:each="pet : ${owner.pets}" th:text="${pet.name} "/></td>
+ </tr>
+ </tbody>
+ </table>
+
+ </body>
+</html>
diff --git a/src/main/resources/templates/pets/createOrUpdatePetForm.html b/src/main/resources/templates/pets/createOrUpdatePetForm.html
new file mode 100644
index 0000000..bfa07d1
--- /dev/null
+++ b/src/main/resources/templates/pets/createOrUpdatePetForm.html
@@ -0,0 +1,38 @@
+<html xmlns:th="http://www.thymeleaf.org"
+ th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
+
+<body>
+
+ <h2>
+ <th:block th:if="${pet['new']}">New </th:block>
+ Pet
+ </h2>
+ <form th:object="${pet}" class="form-horizontal" method="post">
+ <input type="hidden" name="id" th:value="*{id}" />
+ <div class="form-group has-feedback">
+ <div class="form-group">
+ <label class="col-sm-2 control-label">Owner</label>
+ <div class="col-sm-10">
+ <span th:text="${pet.owner?.firstName + ' ' + pet.owner?.lastName}" />
+ </div>
+ </div>
+ <input
+ th:replace="~{fragments/inputField :: input ('Name', 'name')}" />
+ <input
+ th:replace="~{fragments/inputField :: input ('Birth Date', 'birthDate')}" />
+ <input
+ th:replace="~{fragments/selectField :: select ('Type', 'type', ${types})}" />
+ </div>
+ <div class="form-group">
+ <div class="col-sm-offset-2 col-sm-10">
+ <button
+ th:with="text=${owner['new']} ? 'Add Pet' : 'Update Pet'"
+ class="btn btn-default" type="submit" th:text="${text}">Add
+ Pet</button>
+ </div>
+ </div>
+ </form>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/pets/createOrUpdateVisitForm.html b/src/main/resources/templates/pets/createOrUpdateVisitForm.html
new file mode 100644
index 0000000..c96c324
--- /dev/null
+++ b/src/main/resources/templates/pets/createOrUpdateVisitForm.html
@@ -0,0 +1,61 @@
+<html xmlns:th="http://www.thymeleaf.org"
+ th:replace="~{fragments/layout :: layout (~{::body},'owners')}">
+
+<body>
+
+ <h2>
+ <th:block th:if="${visit['new']}">New </th:block>
+ Visit
+ </h2>
+
+ <b>Pet</b>
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Birth Date</th>
+ <th>Type</th>
+ <th>Owner</th>
+ </tr>
+ </thead>
+ <tr>
+ <td th:text="${visit.pet.name}" /></td>
+ <td
+ th:text="${#calendars.format(visit.pet.birthDate, 'yyyy-MM-dd')}" /></td>
+ <td th:text="${visit.pet.type}" /></td>
+ <td
+ th:text="${visit.pet.owner?.firstName + ' ' + visit.pet.owner?.lastName}" /></td>
+ </tr>
+ </table>
+
+ <form th:object="${visit}" class="form-horizontal" method="post">
+ <div class="form-group has-feedback">
+ <input
+ th:replace="~{fragments/inputField :: input ('Date', 'date')}" />
+ <input
+ th:replace="~{fragments/inputField :: input ('Description', 'description')}" />
+ </div>
+
+ <div class="form-group">
+ <div class="col-sm-offset-2 col-sm-10">
+ <input type="hidden" name="petId" th:value="${visit.pet.id}" />
+ <button class="btn btn-default" type="submit">Add Visit</button>
+ </div>
+ </div>
+ </form>
+
+ <br />
+ <b>Previous Visits</b>
+ <table class="table table-striped">
+ <tr>
+ <th>Date</th>
+ <th>Description</th>
+ </tr>
+ <tr th:if="${!visit['new']}" th:each="visit : ${visit.pet.visits}">
+ <td th:text="${#calendars.format(visit.date, 'yyyy-MM-dd')}" /></td>
+ <td th:text=" ${visit.description}" /></td>
+ </tr>
+ </table>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/resources/templates/vets/vetList.html b/src/main/resources/templates/vets/vetList.html
new file mode 100644
index 0000000..6d741ee
--- /dev/null
+++ b/src/main/resources/templates/vets/vetList.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+
+<html xmlns:th="http://www.thymeleaf.org"
+ th:replace="~{fragments/layout :: layout (~{::body},'vets')}">
+
+<body>
+
+ <h2>Veterinarians</h2>
+
+ <table id="vets" class="table table-striped">
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Specialties</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr th:each="vet : ${vets.vetList}">
+ <td th:text="${vet.firstName + ' ' + vet.lastName}"></td>
+ <td><span th:each="specialty : ${vet.specialties}"
+ th:text="${specialty.name + ' '}" /> <span
+ th:if="${vet.nrOfSpecialties == 0}">none</span></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <table class="table-buttons">
+ <tr>
+ <td><a th:href="@{/vets.html}">View
+ as XML</a></td>
+ <td><a th:href="@{/vets.json}">View as JSON</a></td>
+ </tr>
+ </table>
+
+</body>
+</html>
src/main/resources/templates/welcome.html 16(+16 -0)
diff --git a/src/main/resources/templates/welcome.html b/src/main/resources/templates/welcome.html
new file mode 100644
index 0000000..6b4ff04
--- /dev/null
+++ b/src/main/resources/templates/welcome.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+
+<html xmlns:th="http://www.thymeleaf.org" th:replace="~{fragments/layout :: layout (~{::body},'home')}">
+
+ <body>
+
+ <h2 th:text="#{welcome}">Welcome</h2>
+ <div class="row">
+ <div class="col-md-12">
+ <img class="img-responsive" src="../static/resources/images/pets.png" th:src="@{/resources/images/pets.png}"/>
+ </div>
+ </div>
+
+ </body>
+
+</html>
\ No newline at end of file
diff --git a/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java b/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java
index 8a1934c..237f0f4 100644
--- a/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java
+++ b/src/test/java/org/springframework/samples/petclinic/web/VisitControllerTests.java
@@ -65,13 +65,4 @@ public class VisitControllerTests {
.andExpect(view().name("pets/createOrUpdateVisitForm"));
}
- @Test
- public void testShowVisits() throws Exception {
- mockMvc.perform(get("/owners/*/pets/{petId}/visits", TEST_PET_ID))
- .andExpect(status().isOk())
- .andExpect(model().attributeExists("visits"))
- .andExpect(view().name("visitList"));
- }
-
-
}