Accueil > Spring Data JPA > Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step7]

Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step7]


In [step6] we have implemented the API Dao UserDao with JPA by using Spring Data JPA :

  • the API Dao fr.opensagres.dao.UserDao extends the Spring Data org.springframework.data.repository.PagingAndSortingRepository.
  • the JPA User Dao implementation is created on runtime by Spring Data JPA by declaring a jpa:repository:
    <!-- Spring Data JPA-->
    <jpa:repositories base-package="fr.opensagres.dao">
      <jpa:repository id="userDao" />
    </jpa:repositories>
    

At this step the UserDao provides the CRUD methods and pagination methods for User entity 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.

With Spring Data JPA, it’s possible to add your own method to manage search entities by criteria : to do that the method name of the UserDao must just follow some convention name (see Query creation for more information). In this article we will add the 2 following methods to the UserDao :

  • findByFirstNameLikeAndLastNameLike to retrieve a list of User by first name (like) and last name (like):
    List<User> findByFirstNameLikeAndLastNameLike(String firstName,	String lastName);
    
  • findByFirstNameLikeAndLastNameLike to retrieve a list of User by first name (like) and last name (like) with pagination:
    Page<User> findByFirstNameLikeAndLastNameLike(String firstName,	String lastName, Pageable pageable);
    

Just add those 2 methods to UserDao API and Spring Data JPA will manage for you the JPA implementation!

Download

You can download eclipsespring_step7.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.dao.jpa the bundle implementation of UserDao with JPA by using Spring Data JPA to avoid coding the JPAUserDao class.
  • fr.opensagres.dao.jpa.eclipselink the fragment which configures the JPA fr.opensagres.dao.jpa to use EclipseLink and Deby as dialect.
  • fr.opensagres.data.datasource the bundle which publishes the Derby Datasource used by the fr.opensagres.dao.jpa.
  • 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 :

  1. import those projects in a workspace.
  2. open the TargetPlatform/eclipsespring.target file and click on Set as Target Platform.
  3. select TargetPlatform/launch/Simple OSGi client.launch – Mock Dao to test the launch with Mock Dao and Run it.
  4. select TargetPlatform/launch/Simple OSGi client.launch – JPA Dao to test the launch with JPA Dao and Run it.

Bundles

DAO API Bundle

Here we modify UserDao to add 2 methods:

  • findByFirstNameLikeAndLastNameLike to retrieve a list of User by first name (like) and last name (like).
  • findByFirstNameLikeAndLastNameLike to retrieve a list of User by first name (like) and last name (like) with pagination.

UserDao interface

Modify the fr.opensagres.dao.UserDao like this :

package fr.opensagres.dao;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
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);

	List<User> findByFirstNameLikeAndLastNameLike(String firstName,
			String lastName);

	Page<User> findByFirstNameLikeAndLastNameLike(String firstName,
			String lastName, Pageable pageable);

}

MANIFEST.MF

In the META-INF/MANIFEST-MF of the fr.opensagres.dao bundle:

  • import the org.springframework.data.domain 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.domain,
 org.springframework.data.repository
Export-Package: fr.opensagres.dao

Mock DAO Bundle

As we have added 2 new methods, we must modify MockDao to manage criteria and pagination. But this code is not very interesting (manage pagination with java List). I just give you the code without explanation.

I thhink it should be cool if Spring Data provides a « Spring Data Collections » to manage MockDao like JPA Dao.

MockDaoHelper class

Create the fr.opensagres.dao.mock.MockDaoHelper like this :

package fr.opensagres.dao.mock;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;

import fr.opensagres.domain.User;

public class MockDaoHelper {

	public static String getCriteria(String criteria) {
		if (criteria == null) {
			return null;
		}
		if (criteria.endsWith("%")) {
			criteria = criteria.substring(0, criteria.length() - 1);
		}
		if (criteria.length() == 0) {
			return null;
		}
		return criteria;
	}

	public static Page createPage(List<?> list, Pageable pageable) {

		int totalSize = list.size();
		int pageSize = pageable.getPageSize();
		int pageIndex = pageable.getOffset();

		int fromIndex = pageIndex;
		int toIndex = pageIndex + pageSize;
		if (toIndex > totalSize) {
			toIndex = totalSize;
		}
		List content = list.subList(fromIndex, toIndex);
		return new PageImpl(content, pageable, totalSize);

	}

	public static Page<User> createPage(Collection<?> list, Pageable pageable) {
		return createPage(new ArrayList(list), pageable);
	}

}

MockUserDao class

Modify the fr.opensagres.dao.mock.MockUserDao like this :

package fr.opensagres.dao.mock;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
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) {
		return MockDaoHelper.createPage((Collection) findAll(), pageable);
	}

	public List<User> findByFirstNameLikeAndLastNameLike(String firstName,
			String lastName) {
		Iterable<User> allUsers = findAll();

		String firstNameCriteria = MockDaoHelper.getCriteria(firstName);
		String lastNameCriteria = MockDaoHelper.getCriteria(lastName);

		List<User> filteredList = new ArrayList<User>();
		for (User user : allUsers) {
			if (isUserOK(user, firstNameCriteria, lastNameCriteria)) {
				filteredList.add(user);
			}
		}
		return filteredList;
	}

	private boolean isUserOK(User user, String firstNameCriteria,
			String lastNameCriteria) {
		String firstName = user.getFirstName();
		if (firstNameCriteria != null) {
			if (!(firstName != null && firstName.toUpperCase().startsWith(
					firstNameCriteria.toUpperCase()))) {
				return false;
			}

		}
		String lastName = user.getLastName();
		if (lastNameCriteria != null) {
			if (!(lastName != null && lastName.toUpperCase().startsWith(
					lastNameCriteria.toUpperCase()))) {
				return false;
			}
		}
		return true;

	}

	public Page<User> findByFirstNameLikeAndLastNameLike(String firstName,
			String lastName, Pageable pageable) {
		List<User> filteredList = findByFirstNameLikeAndLastNameLike(firstName,
				lastName);
		return MockDaoHelper.createPage(filteredList, pageable);
	}

}

JPA DAO Bundle

Here we have nothing to do. Thank’s to Spring Data JPA!

Services API Bundle

Here we must add methods to the UserService to use our 2 new UserDao methods. Modify the fr.opensagres.services.UserService interface like this :

package fr.opensagres.services;

import java.util.Collection;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import fr.opensagres.domain.User;

public interface UserService {

	Collection<User> findAll();

	Page<User> findAll(Pageable pageable);
		
	Collection<User> findByFirstNameLikeAndLastNameLike(String firstName,
			String lastName);

	Page<User> findByFirstNameLikeAndLastNameLike(String firstName,
			String lastName, Pageable pageable);

	User saveUser(User user);

}

MANIFEST.MF

In the META-INF/MANIFEST-MF of the fr.opensagres.services bundle:

  • import the org.springframework.data.domain package

Here the full content of this MANIFEST.MF:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Services API
Bundle-SymbolicName: fr.opensagres.services
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: fr.opensagres.services
Import-Package: fr.opensagres.domain,
 org.springframework.data.domain

Services Implementation Bundle

Modify the fr.opensagres.services.impl.UserServiceImpl like this:

package fr.opensagres.services.impl;

import java.util.Collection;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import fr.opensagres.dao.UserDao;
import fr.opensagres.domain.User;
import fr.opensagres.services.UserService;

public class UserServiceImpl implements UserService {

	private UserDao userDao;

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Collection<User> findAll() {
		return (Collection) userDao.findAll();
	}

	public Page<User> findAll(Pageable pageable) {
		return userDao.findAll(pageable);
	}

	public Collection<User> findByFirstNameLikeAndLastNameLike(
			String firstName, String lastName) {
		firstName = getCriteriaLike(firstName);
		lastName = getCriteriaLike(lastName);
		return userDao.findByFirstNameLikeAndLastNameLike(firstName, lastName);
	}

	public Page<User> findByFirstNameLikeAndLastNameLike(String firstName,
			String lastName, Pageable pageable) {
		firstName = getCriteriaLike(firstName);
		lastName = getCriteriaLike(lastName);
		return userDao.findByFirstNameLikeAndLastNameLike(firstName, lastName,
				pageable);
	}

	private String getCriteriaLike(String criteria) {
		return criteria == null || criteria.length() < 1 ? "%" : criteria + "%";
	}

	public User saveUser(User user) {
		return userDao.save(user);
	}

}

You can notice that « % » is added for first name and last name criteria before calling the methods of UserDao.

MANIFEST.MF

In the META-INF/MANIFEST-MF of the fr.opensagres.services.impl bundle:

  • import the org.springframework.data.domain 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

Simple Client Bundle

At this step we can use our 2 new services methods in the client side. We will displays on the console:

  1. findAll: to display the all users:
    Collection<User> users = userService.findAll();
    
  2. findAll with pagination: to display the 2 first users with pagination:
    Pageable pageable = new PageRequest(0, 2);
    Page<User> usersPage = userService.findAll(pageable);
    List<User> users = usersPage.getContent();
    
  3. findByFirstNameLikeAndLastNameLike: to display the all users who match first name (like) with ‘A’:
    Collection<User> users = userService.findByFirstNameLikeAndLastNameLike("A", "");
    
  4. findByFirstNameLikeAndLastNameLike with pagination: to display the 2 first users who match first name (like) with ‘A’ with pagination:
    Pageable pageable = new PageRequest(0, 2);
    Page<User> usersPage = userService.findByFirstNameLikeAndLastNameLike("A", "",pageable);
    List<User> users = usersPage.getContent();
    

FindAllUsersThread

Modify fr.opensagres.simpleclient.FindAllUsersThread like this :

package fr.opensagres.simpleclient;

import java.util.Collection;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import fr.opensagres.domain.User;
import fr.opensagres.services.UserService;

public class FindAllUsersThread extends Thread {

	private static final long TIMER = 5000;

	private UserService userService;

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public UserService getUserService() {
		return userService;
	}

	@Override
	public void run() {
		while (!super.isInterrupted()) {
			try {
				// 1. Get UserService
				UserService userService = getUserService();
				// 2. Display users by using UserServive
				displayUsers(userService);
			} catch (Throwable e) {
				e.printStackTrace();
			} finally {
				try {
					if (!super.isInterrupted())
						sleep(TIMER);
				} catch (InterruptedException e) {
					e.printStackTrace();
					Thread.currentThread().interrupt();
				}
			}
		}
	}

	private void displayUsers(UserService userService) {
		Collection<User> users = null;
		Pageable pageable = new PageRequest(0, 2);
		Page<User> usersPage = null;

		// 1) findAll
		users = userService.findAll();
		displayUsers("findAll", users);

		// 2) findAll with Pagination
		usersPage = userService.findAll(pageable);
		users = usersPage.getContent();
		displayUsers("findAll with Pagination [0,2]", users);

		// 3) findByFirstNameLikeAndLastNameLike
		users = userService.findByFirstNameLikeAndLastNameLike("A", "");
		displayUsers("findByFirstNameLikeAndLastNameLike('A', '')", users);

		// 4) findByFirstNameLikeAndLastNameLike with Pagination
		usersPage = userService.findByFirstNameLikeAndLastNameLike("A", "",
				pageable);
		users = usersPage.getContent();
		displayUsers(
				"findByFirstNameLikeAndLastNameLike('A', '') with Pagination [0,2]",
				users);
	}

	private void displayUsers(String title, Collection<User> users) {
		System.out
				.println("----------------- " + title + " ----------------- ");
		for (User user : users) {
			System.out.println("User [" + user.getFirstName() + " "
					+ user.getLastName() + "]");
		}
	}

	@Override
	public synchronized void start() {
		System.out.println("Start Thread FindAllUsersThread");
		super.start();
	}

	@Override
	public void interrupt() {
		System.out.println("Interrupt Thread FindAllUsersThread");
		super.interrupt();
	}

}

MANIFEST.MF

In the META-INF/MANIFEST-MF of the fr.opensagres.simpleclient bundle:

  • import the org.springframework.data.domain package

Here the full content of this MANIFEST.MF:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Simple Client
Bundle-SymbolicName: fr.opensagres.simpleclient
Bundle-Version: 1.0.0.qualifier
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: fr.opensagres.domain,
 fr.opensagres.services,
 org.springframework.data.domain

Run

At this step we can play with our 2 OSGi launch:

  • TargetPlatform/launch/Simple OSGi client.launch – Mock Dao to test Mock Dao.
  • TargetPlatform/launch/Simple OSGi client.launch JPA Dao to test JPA Dao (Spring Data JPA).

You will see on the console:

----------------- findAll ----------------- 
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]
----------------- findAll with Pagination [0,2] ----------------- 
User [Angelo Zerr]
User [Pascal Leclercq]
----------------- findByFirstNameLikeAndLastNameLike('A', '') ----------------- 
User [Angelo Zerr]
User [Amine Bousta]
User [Arnaud Cogoluegnes]
----------------- findByFirstNameLikeAndLastNameLike('A', '') with Pagination [0,2] ----------------- 
User [Angelo Zerr]
User [Amine Bousta]

Conclusion

In this article we have seen how to manage Dao methods with criteria and pagination with Spring Data JPA, that is very simply (just name your Dao method with some convention name).

In the next article [step8], we will create an Eclipse RCP Application which will show in a View the list of the users. We will see in this article how to we can consume in a RCP View our UserService by using Spring DM.

Catégories :Spring Data JPA

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :