After this exercise you will know how to configure the persistence layer of a Spring application using Spring Data JPA. EclipseLink is used as the JPA implementation. While we want to connect to a PostgreSQL database in the cloud when running the application in production mode, the same method of configuring the database connection should be used when testing the persistence layer using a local database within your VM.
The task of this exercise is to setup the persistence layer in such a way that it uses the PostgreSQL database connection information from the VCAP_SERVICES
environment variables. To access our database, we make use of a convenience CRUD repository interface. This repository uses the EntityManager provided by EclipseLink.
Used dependencies:
In this exercise we provide the CloudDatabaseConfig
class which sets up a CRUD repository based on the information provided in the VCAP_SERVICES
environment variable. For this exercise it suffices to regard this class as a "black box".
Continue with your solution of the last exercise. If this does not work, you can checkout the branch origin/solution-6-Deploy-Ads-On-CF
.
Add the following dependencies to your pom.xml
using the XML view of Eclipse at the end of the list:
- Add spring cloud connector dependencies:
<!-- Spring Cloud Connector -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-spring-service-connector</artifactId>
<version>1.2.1.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
<version>1.2.2.RELEASE</version>
<scope>runtime</scope>
</dependency>
- Add
spring-data-jpa
dependency:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.2.RELEASE</version>
<exclusions>
<exclusion>
<!-- We need spring-core 4.2 or later, but spring-data includes 4.1.9 -->
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
</exclusions>
</dependency>
- Add EclipseLink (JPA implementation) dependencies:
<!-- EclipseLink as JPA implementation -->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.jpa</artifactId>
<version>2.6.2</version>
</dependency>
- Add
postgresql
dependency:
<!-- PostgreSQL database implementations -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1206-jdbc41</version>
<scope>runtime</scope>
</dependency>
- Add
commons-dbcp2
dependency:
<!-- connection pooling -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
<scope>runtime</scope>
</dependency>
Note: After you've changed the Maven settings, don't forget to update your Eclipse project! To do so right click on your Eclipse project and select Maven
- Update Project ...
(ALT-F5
)
In order to use the existing Advertisement
class as a JPA entity, you need to
- annotate the
Advertisement
class with@Entity
and - specify an identifier by adding a field
id
of typeLong
(Note primitive typelong
does not work!), which is annotated with@Id
and@GeneratedValue(strategy = GenerationType.AUTO)
. - if you decide to add a setter for the
id
field, make sure that its argument also is of typeLong
notlong
Use the annotations in the package javax.persistence
(corresponding to the JPA API).
- Create an interface
AdvertisementRepository
in thecom.sap.bulletinboard.ads.models
package that extends theCrudRepository
interface. UseAdvertisement
as the entity type andLong
as the id type.
public interface AdvertisementRepository extends CrudRepository<Advertisement, Long> {
}
- Have a look at the methods provided by the
CrudRepository
interface. By extendingCrudRepository
,AdvertisementRepository
inherits several methods for saving, deleting, and finding entities. - Note: Internally Spring uses reflection to generate a proxy class, which contains the desired implementation details of the specified interface.
- Create a class
EntityManagerFactoryProvider
in the packagecom.sap.bulletinboard.ads.util
and copy the code from here. - Create a class
CloudDatabaseConfig
in the packagecom.sap.bulletinboard.ads.config
and copy the code from here.
Some explanations to the code:
Based on the VCAP_SERVICES
environment variable the spring-cloud
connector instantiates a DataSource
instance. Note: Locally this environment variable is set so that a local PostgreSQL database named test
is used.
In order to persist the data using JPA, we provide (EclipseLink) implementations of EntityManager
and TransactionManager
using a logical database connection, which is represented by the Data Source
.
Finally the CRUD repository, which uses the EntityManager
and TransactionManager
, is instantiated by using the @EnableJpaRepositories
annotation.
- In Eclipse, in the "Servers" view, open the Tomcat server. In the opened detail view (
Overview
tab), click on "Open launch configuration". Change to the "Environment" tab, and inspect theVCAP_SERVICES
environment variable. You should see that this allows your application to connect to a local database. - Build and run the microservice.
- Ensure that the
advertisement
table is created with columnsid
andtitle
. You can use theDBeaver
Eclipse Perspective, where the table should be visible within theDatabase Navigator
view underSchemas - public - Tables
. - Also note that a
sequence
table is created. This table is used by EclipseLink to determine which (unused) ID should be used for a created entity.
Notes:
- When running the service in the terminal ensure that you've executed
localEnvironmentSetup.sh
as explained here. - If you want to run the
tomcat7:run
Maven goal in Eclipse, you need to configure the environment variables (in the corresponding run configuration) starting with this exercise. Please have a look at thelocalEnvironmentSetup.sh
file for this. Alternatively, use the Tomcat server in Eclipse (without Maven), or run Maven in the console. - Note, that the data is still read from / written into the HashMap. We will change that in the second part of the exercise.
- Annotate the
Advertisement
class with@Table(name = "advertisements")
to specify the name of the database table. - Annotate the
title
field with@Column(name = "mytitle")
to specify the name of the column. Note that names starting with an underscore might be reserved, and actually cause problems in HSQLDB. - Build and run the microservice.
- Ensure that the
advertisements
table is created with columnsid
andmytitle
. You can use theDBeaver
Eclipse Perspective, where the table should be visible within theDatabase Navigator
view underSchemas - public - Tables
. You probably need to do a refresh to visualize them. If the new table is still not shown, you need tostop
,clean...
andrestart
your Tomcat server. - Take a look at the annotations offered by JPA API.
- Spring Cloud: How to configure Service Connections for Spring
- Java Persistence API (JPA) tutorial
- Spring Data JPA
- EclipseLink Object/Relational Mapping
- Chrome JSON Editor to view / edit the
VCAP_SERVICES
variable
-
© 2018 SAP SE