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 take this class as given.
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. Ensure that the environment variables are specified like in thelocalEnvironmentSetup.sh
script. - 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