Skip to content
Snippets Groups Projects
Commit a6e81a51 authored by Antoine Rey's avatar Antoine Rey
Browse files

#164 Spring Boot version of Petclinic ready to deploy to an external web container (ie Tomcat)

parent 76a4ca33
No related branches found
No related tags found
No related merge requests found
Showing
with 72 additions and 593 deletions
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository.jpa;
import java.util.Collection;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.samples.petclinic.repository.VetRepository;
import org.springframework.stereotype.Repository;
/**
* JPA implementation of the {@link VetRepository} interface.
*
* @author Mike Keith
* @author Rod Johnson
* @author Sam Brannen
* @author Michael Isvy
* @since 22.4.2006
*/
@Repository
public class JpaVetRepositoryImpl implements VetRepository {
@PersistenceContext
private EntityManager em;
@Override
@Cacheable(value = "vets")
@SuppressWarnings("unchecked")
public Collection<Vet> findAll() {
return this.em.createQuery("SELECT distinct vet FROM Vet vet left join fetch vet.specialties ORDER BY vet.lastName, vet.firstName").getResultList();
}
}
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository.jpa;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.repository.VisitRepository;
import org.springframework.stereotype.Repository;
/**
* JPA implementation of the ClinicService interface using EntityManager.
* <p/>
* <p>The mappings are defined in "orm.xml" located in the META-INF directory.
*
* @author Mike Keith
* @author Rod Johnson
* @author Sam Brannen
* @author Michael Isvy
* @since 22.4.2006
*/
@Repository
public class JpaVisitRepositoryImpl implements VisitRepository {
@PersistenceContext
private EntityManager em;
@Override
public void save(Visit visit) {
if (visit.getId() == null) {
this.em.persist(visit);
} else {
this.em.merge(visit);
}
}
@Override
@SuppressWarnings("unchecked")
public List<Visit> findByPetId(Integer petId) {
Query query = this.em.createQuery("SELECT v FROM Visit v where v.pet.id= :id");
query.setParameter("id", petId);
return query.getResultList();
}
}
/**
* The classes in this package represent the JPA implementation
* of PetClinic's persistence layer.
*/
package org.springframework.samples.petclinic.repository.jpa;
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository.springdatajpa;
import java.util.Collection;
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.Owner;
import org.springframework.samples.petclinic.repository.OwnerRepository;
/**
* Spring Data JPA specialization of the {@link OwnerRepository} interface
*
* @author Michael Isvy
* @since 15.1.2013
*/
public interface SpringDataOwnerRepository extends OwnerRepository, Repository<Owner, Integer> {
@Override
@Query("SELECT DISTINCT owner FROM Owner owner left join fetch owner.pets WHERE owner.lastName LIKE :lastName%")
public Collection<Owner> findByLastName(@Param("lastName") String lastName);
@Override
@Query("SELECT owner FROM Owner owner left join fetch owner.pets WHERE owner.id =:id")
public Owner findById(@Param("id") int id);
}
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository.springdatajpa;
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.Pet;
import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.repository.PetRepository;
/**
* Spring Data JPA specialization of the {@link PetRepository} interface
*
* @author Michael Isvy
* @since 15.1.2013
*/
public interface SpringDataPetRepository extends PetRepository, Repository<Pet, Integer> {
@Override
@Query("SELECT ptype FROM PetType ptype ORDER BY ptype.name")
List<PetType> findPetTypes() throws DataAccessException;
}
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.repository.springdatajpa;
import org.springframework.data.repository.Repository;
import org.springframework.samples.petclinic.model.Visit;
import org.springframework.samples.petclinic.repository.VisitRepository;
/**
* Spring Data JPA specialization of the {@link VisitRepository} interface
*
* @author Michael Isvy
* @since 15.1.2013
*/
public interface SpringDataVisitRepository extends VisitRepository, Repository<Visit, Integer> {
}
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.util;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.StopWatch;
/**
* Simple aspect that monitors call count and call invocation time. It uses JMX annotations and therefore can be
* monitored using any JMX console such as the jConsole
* <p/>
* This is only useful if you use JPA or JDBC. Spring-data-jpa doesn't have any correctly annotated classes to join on
*
* @author Rob Harrop
* @author Juergen Hoeller
* @author Michael Isvy
* @since 2.5
*/
@ManagedResource("petclinic:type=CallMonitor")
@Aspect
public class CallMonitoringAspect {
private boolean enabled = true;
private int callCount = 0;
private long accumulatedCallTime = 0;
@ManagedAttribute
public boolean isEnabled() {
return enabled;
}
@ManagedAttribute
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@ManagedOperation
public void reset() {
this.callCount = 0;
this.accumulatedCallTime = 0;
}
@ManagedAttribute
public int getCallCount() {
return callCount;
}
@ManagedAttribute
public long getCallTime() {
if (this.callCount > 0)
return this.accumulatedCallTime / this.callCount;
else
return 0;
}
@Around("within(@org.springframework.stereotype.Repository *)")
public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
if (this.enabled) {
StopWatch sw = new StopWatch(joinPoint.toShortString());
sw.start("invoke");
try {
return joinPoint.proceed();
} finally {
sw.stop();
synchronized (this) {
this.callCount++;
this.accumulatedCallTime += sw.getTotalTimeMillis();
}
}
} else {
return joinPoint.proceed();
}
}
}
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -13,17 +13,23 @@ ...@@ -13,17 +13,23 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.samples.petclinic.repository.springdatajpa;
import org.springframework.data.repository.Repository; package org.springframework.samples.petclinic.web;
import org.springframework.samples.petclinic.model.Vet;
import org.springframework.samples.petclinic.repository.VetRepository;
/** import org.springframework.boot.autoconfigure.web.ErrorController;
* Spring Data JPA specialization of the {@link VetRepository} interface import org.springframework.stereotype.Controller;
* import org.springframework.web.bind.annotation.RequestMapping;
* @author Michael Isvy
* @since 15.1.2013 @Controller
*/ public class CustomErrorController implements ErrorController {
public interface SpringDataVetRepository extends VetRepository, Repository<Vet, Integer> {
@RequestMapping(value = "/error")
public String error() {
return "exception";
}
@Override
public String getErrorPath() {
return "/error";
}
} }
...@@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.Formatter; import org.springframework.format.Formatter;
import org.springframework.samples.petclinic.model.PetType; import org.springframework.samples.petclinic.model.PetType;
import org.springframework.samples.petclinic.service.ClinicService; import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.stereotype.Component;
/** /**
* Instructs Spring MVC on how to parse and print elements of type 'PetType'. Starting from Spring 3.0, Formatters have * Instructs Spring MVC on how to parse and print elements of type 'PetType'. Starting from Spring 3.0, Formatters have
...@@ -37,6 +38,7 @@ import org.springframework.samples.petclinic.service.ClinicService; ...@@ -37,6 +38,7 @@ import org.springframework.samples.petclinic.service.ClinicService;
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Michael Isvy * @author Michael Isvy
*/ */
@Component
public class PetTypeFormatter implements Formatter<PetType> { public class PetTypeFormatter implements Formatter<PetType> {
private final ClinicService clinicService; private final ClinicService clinicService;
......
package org.springframework.samples.petclinic.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class WelcomeController {
@RequestMapping("/")
public String welcome() {
return "welcome";
}
}
<html>
<body>
<p>
The Spring Data Binding framework, an internal library used by Spring Web Flow.
</p>
</body>
</html>
\ No newline at end of file
<head>
<style type="text/css">
table.speakersTable {
width: 70%;
padding: 10;
spacing: 10;
}
img.speakerPic {
float: right;
padding: 10;
width: 90;
}
</style>
</head>
<h1>Organisation</h1>
<h1>Speakers</h1>
<table class="speakersTable">
<tbody>
<tr>
<td>
<img class="speakerPic" alt="Sergiu Bodiu"
src="http://m.c.lnkd.licdn.com/mpr/mpr/shrink_200_200/p/4/000/16a/2ba/0ba653e.jpg"/>
<h2>Sergiu Bodiu </h2>
<h3> Java Consultant at Bank of America </h3>
<font size="5">S</font>easoned consultant experienced in large-scale e-commerce projects, passionate about
providing innovative technology solutions to solve complex business problems, have extensive knowledge and
experience delivering enterprise wide applications. He is skilled in software design, data modeling,
stakeholder management, IT strategic planning, technical know-how and security. Able to design, implement,
test and maintain software product components with strong focus on design elegance and software reuse.
</td>
</tr>
<tr>
<td>
<img alt="Sergiu Bodiu" src="http://m.c.lnkd.licdn.com/mpr/mpr/shrink_200_200/p/4/000/16a/2ba/0ba653e.jpg"
width="84" height="84" align="right" hspace="10"/>
<h2>Sergiu Bodiu </h2>
<h3> Java Consultant at Bank of America </h3>
<font size="5">S</font>easoned consultant experienced in large-scale e-commerce projects, passionate about
providing innovative technology solutions to solve complex business problems, have extensive knowledge and
experience delivering enterprise wide applications. He is skilled in software design, data modeling,
stakeholder management, IT strategic planning, technical know-how and security. Able to design, implement,
test and maintain software product components with strong focus on design elegance and software reuse.
</td>
</tr>
</tbody>
</table>
# Web
spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp
# JPA
spring.jpa.hibernate.ddl-auto: none
#spring.jpa.database: HSQL
#spring.jpa.show-sql: true
#spring.datasource.driverClassName=org.hsqldb.jdbcDriver
spring.datasource.schema: classpath*:db/hsqldb/initDB.sql
spring.datasource.data: classpath*:db/hsqldb/populateDB.sql
#spring.datasource.username: sa
#spring.datasource.password:
# Internationalization
spring.messages.basename: messages/messages
# Actuator / Management
management.contextPath: /manage
# Logging
logging.level.org.springframework=INFO
|\ _,,,--,,_
/,`.-'`' ._ \-;;,_
_______ __|,4- ) )_ .;.(__`'-'__ ___ __ _ ___ _______
| | '---''(_/._)-'(_\_) | | | | | | | | |
| _ | ___|_ _| | | | | |_| | | | __ _ _
| |_| | |___ | | | | | | | | | | \ \ \ \
| ___| ___| | | | _| |___| | _ | | _| \ \ \ \
| | | |___ | | | |_| | | | | | | |_ ) ) ) )
|___| |_______| |___| |_______|_______|___|_| |__|___|_______| / / / /
==================================================================/_/_/_/
:: Built with Spring Boot :: ${spring-boot.version}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<configuration scan="true" scanPeriod="30 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%-5level %logger{0} - %msg%n</pattern>
</encoder>
</appender>
<!--<logger name="org.hibernate" level="debug"/> -->
<logger name="org.springframework.samples.petclinic" level="debug"/>
<root level="info">
<appender-ref ref="console"/>
</root>
</configuration>
<?xml version="1.0" encoding="UTF-8"?>
<!--
Repository and Service layers
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- ========================= RESOURCE DEFINITIONS ========================= -->
<!-- import the dataSource definition -->
<import resource="datasource-config.xml"/>
<context:component-scan
base-package="org.springframework.samples.petclinic.service"/>
<!-- Configurer that replaces ${...} placeholders with values from a properties file -->
<!-- (in this case, JDBC-related settings for the JPA EntityManager definition below) -->
<context:property-placeholder location="classpath:spring/data-access.properties" system-properties-mode="OVERRIDE"/>
<!-- enables scanning for @Transactional annotations -->
<tx:annotation-driven/>
<!-- ================== 3 Profiles to choose from ===================
- jdbc (uses Spring" JdbcTemplate)
- jpa
- spring-data-jpa
=============================================================================-->
<beans profile="jpa,spring-data-jpa">
<!-- JPA EntityManagerFactory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:database="${jpa.database}" p:showSql="${jpa.showSql}"/>
<!-- the 'database' parameter refers to the database dialect being used.
By default, Hibernate will use a 'HSQL' dialect because 'jpa.database' has been set to 'HSQL'
inside file spring/data-access.properties
-->
</property>
<!-- gDickens: BOTH Persistence Unit and Packages to Scan are NOT compatible, persistenceUnit will win -->
<property name="persistenceUnitName" value="petclinic"/>
<property name="packagesToScan" value="org.springframework.samples.petclinic"/>
</bean>
<!-- Transaction manager for a single JPA EntityManagerFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>
<!--
Post-processor to perform exception translation on @Repository classes (from native
exceptions such as JPA PersistenceExceptions to Spring's DataAccessException hierarchy).
-->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
<beans profile="jdbc">
<!-- Transaction manager for a single JDBC DataSource (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<bean id="namedParameterJdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<context:component-scan base-package="org.springframework.samples.petclinic.repository.jdbc"/>
</beans>
<beans profile="jpa">
<!--
Loads JPA beans
Will automatically be transactional due to @Transactional.
EntityManager will be auto-injected due to @PersistenceContext.
PersistenceExceptions will be auto-translated due to @Repository.
-->
<context:component-scan base-package="org.springframework.samples.petclinic.repository.jpa"/>
</beans>
<beans profile="spring-data-jpa">
<jpa:repositories base-package="org.springframework.samples.petclinic.repository.springdatajpa"/>
</beans>
</beans>
# Properties file with JDBC and JPA settings.
#
# Applied by <context:property-placeholder location="jdbc.properties"/> from
# various application context XML files (e.g., "applicationContext-*.xml").
# Targeted at system administrators, to avoid touching the context XML files.
# Properties that control the population of schema and data for a new data source
jdbc.initLocation=classpath:db/hsqldb/initDB.sql
jdbc.dataLocation=classpath:db/hsqldb/populateDB.sql
jpa.showSql=true
#-------------------------------------------------------------------------------
# HSQL Settings
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:mem:petclinic
jdbc.username=sa
jdbc.password=
# Property that determines which database to use with an AbstractJpaVendorAdapter
jpa.database=HSQL
#-------------------------------------------------------------------------------
# MySQL Settings
#jdbc.driverClassName=com.mysql.jdbc.Driver
#jdbc.url=jdbc:mysql://localhost:3306/petclinic?useUnicode=true&characterEncoding=UTF-8
#jdbc.username=root
#jdbc.password=petclinic
# Property that determines which database to use with an AbstractJpaVendorAdapter
#jpa.database=MYSQL
<?xml version="1.0" encoding="UTF-8"?>
<!--
Application context definition for PetClinic Datasource.
-->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd">
<!-- ========================= DATASOURCE DEFINITION ========================= -->
<!-- Configurer that replaces ${...} placeholders with values from a properties file -->
<!-- (in this case, JDBC-related settings for the dataSource definition below) -->
<context:property-placeholder location="classpath:spring/data-access.properties" system-properties-mode="OVERRIDE"/>
<!-- DataSource configuration for the tomcat jdbc connection pool
See here for more details on commons-dbcp versus tomcat-jdbc:
http://blog.ippon.fr/2013/03/13/improving-the-performance-of-the-spring-petclinic-sample-application-part-3-of-5/-->
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"
p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.url}"
p:username="${jdbc.username}" p:password="${jdbc.password}"/>
<!-- Database initializer. If any of the script fails, the initialization stops. -->
<!-- As an alternative, for embedded databases see <jdbc:embedded-database/>. -->
<jdbc:initialize-database data-source="dataSource">
<jdbc:script location="${jdbc.initLocation}"/>
<jdbc:script location="${jdbc.dataLocation}"/>
</jdbc:initialize-database>
<beans profile="javaee">
<!-- JNDI DataSource for JEE environments -->
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/petclinic"/>
</beans>
</beans>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment