Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step5]
In [step4] we have created DAO layer with Mock implementation. In this article we will start to explains how to implement DAO with JPA to use Database. We will use:
- EclipseLink as JPA Implementation
- Derby as Database.
- Spring Data JPA to implement our DAO with JPA. Spring Data gives some DAO interface like org.springframework.data.repository.PagingAndSortingRepository which provides several CRUD methods like :
- Iterable findAll(): to find all entity.
- T save(T model): to save an entity.
- Page findAll(Pageable pageable): to find all entity with pagination.
The basic idea of Spring Data JPA is extends this interface in your DAO, and you not need to implements this methods with JPA query. It’s the goal of Spring Data JPA.
But it’s very long to explain how to configure and creates bundles to do that. So I decided to split the explanation into 2 articles :
- [step5]: explains how to download Spring Data JPA, use Java Spring Data Structure in our Mock and API DAO, and configure the OSGi launch.
- [step6]: explains how to create and configure bundles to use Spring Data JPA with EclipseLink and Derby.
Download
You can download eclipsespring_step5.zip which contains the following explained projects :
- fr.opensagres.domain : OSGi bundle domain which hosts fr.opensagres.domain.User class.
- fr.opensagres.dao : OSGi bundle Dao API which hosts fr.opensagres.dao.UserDao interface.
- fr.opensagres.dao.mock : OSGi bundle Dao Mock Implementation (Dao implemented with Java Map) which hosts a Spring file which declares the implementation of UserDao in a Spring bean and publish it the OSGi services registry with Spring DM <osgi:service.
- fr.opensagres.services : OSGi bundle Services API which hosts fr.opensagres.services.UserService interface.
- fr.opensagres.services.impl : OSGi bundle Services Implementation which hosts a Spring file which declares the implementation of UserService in a Spring bean and publish it the OSGi services registry with Spring DM <osgi:service.
- fr.opensagres.data.injector : OSGi bundle Data Injector which hosts a Spring file which declares a DataInjector in a Spring bean. This DataInjector consumes the UserService injected by Spring which is retrieved from the OSGi services registry with Spring DM <osgi:reference and call UserService#saveUser(User user) to inject User data.
- fr.opensagres.simpleclient : OSGi bundle simple client which hosts a Spring file which declares a thread in a Spring bean. This thread consumes the UserService injected by Spring which is retrieved from the OSGi services registry with Spring DM <osgi:reference.
- fr.opensagres.config.log4j : OSGi fragment which configures log4j.
- TargetPlatform: simple project which hosts the Spring DM JARS, the target definition and launch.
To use this zip, unzip it :
- import those projects in a workspace.
- open the TargetPlatform/eclipsespring.target file and click on Set as Target Platform.
- select TargetPlatform/launch/Simple OSGi client.launch and Run it.
TargetPLatform & Spring Data JPA
Here we will download
- The JPA API.
- EclipseLink used as JPA Implementation
- Derby used as Database.
- Commons DBCP used as connection pool.
- Spring Data JPA to implement our DAO with JPA.
Download Spring Data JPA
- delete the TargetPlatform/lib folder.
- Modify the pom.xml to download Spring Data JPA JARs, etc like this :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>fr.opensagres.samples</groupId> <artifactId>fr.opensagres.samples.targetplatform</artifactId> <packaging>pom</packaging> <version>0.0.1-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>2.1</version> <executions> <execution> <id>copy-dependencies</id> <phase>process-resources</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>lib</outputDirectory> <overWriteReleases>true</overWriteReleases> <overWriteSnapshots>true</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> </execution> </executions> </plugin> </plugins> </build> <properties> <spring.dm.version>1.2.1</spring.dm.version> <slf4j.version>1.6.1</slf4j.version> <org.aopalliance>1.0.0</org.aopalliance> <spring.data.jpa>1.0.3.RELEASE</spring.data.jpa> <annotation.version>1.0.1</annotation.version> <jpa.version>1.1</jpa.version> <eclipselink>2.3.0</eclipselink> <commons.dbcp>1.2.2.osgi</commons.dbcp> <database.derby>10.5.1000001.764942</database.derby> </properties> <repositories> <repository> <id>spring-maven-milestone</id> <name>Springframework Maven Repository</name> <url>http://maven.springframework.org/milestone</url> </repository> <repository> <id>com.springsource.repository.bundles.external</id> <name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name> <url>http://repository.springsource.com/maven/bundles/external</url> </repository> <repository> <id>EclipseLink Repo</id> <url>http://download.eclipse.org/rt/eclipselink/maven.repo</url> </repository> </repositories> <dependencies> <!-- Spring DM --> <dependency> <groupId>org.springframework.osgi</groupId> <artifactId>spring-osgi-extender</artifactId> <version>${spring.dm.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <!-- API logger: Commons Logging required by Spring DM --> <dependency> <groupId>org.slf4j</groupId> <artifactId>com.springsource.slf4j.org.apache.commons.logging</artifactId> <version>${slf4j.version}</version> <scope>provided</scope> </dependency> <!-- Implementation logger: log4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>com.springsource.slf4j.log4j</artifactId> <version>${slf4j.version}</version> <scope>provided</scope> </dependency> <!-- OSGi AOP Alliance (need do that since we have exclude org.springframework) --> <dependency> <groupId>org.aopalliance</groupId> <artifactId>com.springsource.org.aopalliance</artifactId> <version>${org.aopalliance}</version> </dependency> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> <version>${spring.data.jpa}</version> </dependency> <!-- API : javax.annotation --> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-annotation_1.1_spec</artifactId> <version>${annotation.version}</version> </dependency> <!-- API JPA: annotation --> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-jpa_2.0_spec</artifactId> <version>${jpa.version}</version> </dependency> <!-- Implementation JPA: EclipseLink --> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa</artifactId> <version>${eclipselink}</version> </dependency> <!-- Database Connection Pool --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>com.springsource.org.apache.commons.dbcp</artifactId> <version>${commons.dbcp}</version> </dependency> <!-- Database Derby --> <dependency> <groupId>org.apache.derby</groupId> <artifactId>com.springsource.org.apache.derby</artifactId> <version>${database.derby}</version> </dependency> </dependencies> </project>
You can notice that org.springframework groupid is excluded in the org.springframework.osgi dependency to avoid downloading Spring 2.5.6 JARs, because Spring Data JPA requires Spring 3.0.5.
- Open a dos/sh command, go to the folder TargetPlaform and launch mvn like this (or use M2Eclipse) :
mvn process-resources
- this command download Spring Data JPA JARs and their dependencies and copy it to the TargetPlatform/lib folder. Once maven has finished, refresh TargetPlatform project, lib folder must appears:
Target Definition
At this step we need to refresh the Target Platform. To do that :
- close the editor of TargetPlatform/eclispespring.target.
- reopen the editor of TargetPlatform/eclispespring.target. PDE will resolve the target platform and bundles that you have downloaded must appears in the Target Paltform.
- Activate the Target Platform with Set as Target Platform link.
The existing launch TargetPlatform/launch/Simple OSGi Client.launch is broken because we have new bundles (for instance Spring 3.0.5 bundles instead of 2.5.6).
We will fix this launch on the end of this article.
Bundles – Mock Dao
To use Spring Data JPA, we need extends the Spring Data org.springframework.data.repository.PagingAndSortingRepository interface in our API UserDao.
DAO API
Modify the fr.opensagres.dao.UserDao interface like this:
package fr.opensagres.dao; import org.springframework.data.repository.PagingAndSortingRepository; import fr.opensagres.domain.User; public interface UserDao extends PagingAndSortingRepository<User, Long> { // Iterable<User> findAll(); // User save(User user); }
MANIFEST.MF
In the META-INF/MANIFEST-MF of the Dao API bundle:
- import the org.springframework.data.repository package
Here the full content of this MANIFEST.MF:
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Dao API Bundle-SymbolicName: fr.opensagres.dao Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: fr.opensagres.domain, org.springframework.data.repository Export-Package: fr.opensagres.dao
Mock Dao
We must modify our MockDao to implement the Spring Data interface org.springframework.data.repository.PagingAndSortingRepository. We should do that because we have Mock Dao but when we will use Spring Data JPA, we need not implement the UserDao with JPA. I think it should be cool if Spring Data will provides a new project to manage Mock DAO. I have started this project in the org.springframework.data.domain.collections but it’s an another topic. At this step we implement Mock Dao at hand.
MockUserDao class
Modify the fr.opensagres.dao.mock.MockUserDao class like this:
package fr.opensagres.dao.mock; import java.util.LinkedHashMap; import java.util.Map; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import fr.opensagres.dao.UserDao; import fr.opensagres.domain.User; public class MockUserDao implements UserDao { private final Map<Long, User> users = new LinkedHashMap<Long, User>(); private long currentId = 0; public Iterable<User> findAll() { return users.values(); } public User save(User user) { Long id = user.getId(); if (id == null) { id = generateId(); user.setId(id); } users.put(id, user); return user; } public synchronized Long generateId() { return currentId++; } public long count() { return users.values().size(); } public void delete(Long id) { users.remove(id); } public void delete(User user) { users.remove(user); } public void delete(Iterable<? extends User> users) { throw new UnsupportedOperationException(); } public void deleteAll() { users.clear(); } public boolean exists(Long id) { return users.containsKey(id); } public User findOne(Long id) { return users.get(id); } public Iterable<User> save(Iterable<? extends User> arg0) { throw new UnsupportedOperationException(); } public Iterable<User> findAll(Sort sort) { throw new UnsupportedOperationException(); } public Page<User> findAll(Pageable pageable) { throw new UnsupportedOperationException(); } }
MANIFEST.MF
In the META-INF/MANIFEST-MF of the Dao Mock bundle:
- import the org.springframework.data.domain package
- import the org.springframework.data.repository package
Here the full content of this MANIFEST.MF:
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Dao Mock Implementation Bundle-SymbolicName: fr.opensagres.dao.mock Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: fr.opensagres.dao, fr.opensagres.domain, org.springframework.data.domain, org.springframework.data.repository
Servives Implementation
MANIFEST.MF
In the META-INF/MANIFEST-MF of the Services implementation bundle:
- import the org.springframework.data.domain package
- import the org.springframework.data.repository package
Here the full content of this MANIFEST.MF:
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Services Implementation Bundle-SymbolicName: fr.opensagres.services.impl Bundle-Version: 1.0.0.qualifier Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: fr.opensagres.dao, fr.opensagres.domain, fr.opensagres.services, org.springframework.data.domain, org.springframework.data.repository
Run Mock
At this step we need fix the TargetPlatform/launch/Simple OSGi client.launch.
to do that, select the org.springframework.data.commons bundle (which provides the org.springframework.data.repository.PagingAndSortingRepository interface) and click on Add required Bundles button to add missing bundles in the selection :
and remove (why is there selected?) at hand some bundles which is not used in our context like:
- com.springsource.org.apache.commons.pool
- com.springsource.org.apache.commons.derby
- org.apache.geronimo.specs.geronimo-specs-jpa_2_0_spec
- org.eclipse.persistence.antlr
- org.eclipse.persistence.asm
- org.eclipse.persistence.core
- org.eclipse.persistence.jpa
Run the OSGi launch, and you will see on the console the User list :
User [Angelo Zerr] User [Pascal Leclercq] User [Amine Bousta] User [Mickael Baron] User [Jawher Moussa] User [Arnaud Cogoluegnes] User [Lars Vogel] User [Olivier Gierke] User [Tom Schindl] User [Wim Jongman]
Conclusion
In this article we have downloaded JARs bundles to work with Spring Data JPA:
- The JPA API.
- EclipseLink used as JPA Implementation
- Derby used as Database.
- Commons DBCP used as connection pool.
- Spring Data JPA to implement our DAO with JPA.
And we have modified our UserDao API to extends Spring Data org.springframework.data.repository.PagingAndSortingRepository interface which will be very helpfull when we will use Spring Data JPA.
In the next article [step6] we will create bundles to use Spring Data JPA with EclipseLink and Derby.
-
avril 11, 2012 à 4:06Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step4] « Angelo's Blog
-
avril 12, 2012 à 4:13Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step6] « Angelo's Blog