In the wake of Spring Pet Clinic. Maven / Spring Context / Spring Test / Spring ORM / Spring Data JPA

  • Tutorial

Spring MVC , according to the 2014 RevbelLabs Java Tools and Technology Review , is the most popular web framework.
Further, the same review calls the leader of ORM - Hibernate and the leader of web containers - Apache Tomcat. Add here the jQuery most used java script library , the most popular Bootstrap css framework , the most popular Maven build tool (not against Gradle's attack) , the absolute leader among the JUnit test frameworks, and we will get an example application on Spring from its creators:
Spring Pet Clinic ( demo application ).
In addition to the above, Spring-Jdbc, Spring-ORM,
Spring Data JPA ,
Hibernate Validator ,
Json Jackson ,
WebJars ,
Dandelion DataTables ,
Hamcrest ,
Mockito and dozens of other dependencies are also included in this rather simple functionality project .

Progress in software development implies a reduction in the volume of the application’s own code, ideally, only to the business logic of the application.
However, this is not free - the number of dependencies has exceeded fifty for even a simple project (there are 61 jar in PetClinic in WEB-INF \ lib).
Of course do not necessarily know all of them, some jar catching up in the background, and we are not even aware of them until you see the finished war or not
feasible mvn project-info-reports:dependencies(in IDEA: Show Dependencies ... in the Maven project). But you have to work with the main ones. And
sometimes it takes hours, or even days, to fight some of their features. And you have to deal with the bugs of the frameworks themselves ...

Recently, inspired by Pet Clinic, when creating a webinar on these technologies, I created the Todo Management List application: managing a to-do list
with authorization and user registration. Pet Clinic dependencies added moreSpring Security / the very recent Spring Security
jQuery Jeditable and jQuery notification plugins .
The volume of the article does not allow us to describe the steps of creating an application (a webinar on creating an application takes 30 hours),
so here I share resources, some thoughts and solutions that came in the process of creating it.
On PaaS Heroku you can find a demo of the application (the first
time you start it can take a long load and server error, repeat).

Application examples

On the Internet, there are a lot of applications built on Spring / JPA / MVC / Security. You can download sorts and choose the solution that suits you best.

Spring namespace configuration

There is a tendency in Spring configuration to hide implementation details under its namespaces.
The configuration becomes smaller and more understandable, however, the process of customization or debugging is not quite trivial: first you need to find the beans
where it is implemented.
Compare for example the initialization of the


This is especially evident when comparing the former Acegi Security with Spring Security (all filters are hidden under namespace security ).

@Transactional in tests

It is customary to use transactionality in Spring tests: after each test is completed, the database rollbacks to its original state.
However, @Transactional itself strongly influences the behavior of tests: for example, you forgot in the @Transactional service / repository, the test passed, and the application crashed.
Even worse, when the test gets entities from the database for comparison:
they fall into the same transactional context and the behavior of the tested methods becomes somewhat different (only evict or detach saves).
The base state during the test debug is also not displayed until the test transaction is completed.
It is more honest to use the base initializer before each test:

public class DbPopulator extends ResourceDatabasePopulator {
    private static final ResourceLoader RESOURCE_LOADER = new DefaultResourceLoader();
    private DataSource dataSource;
    public DbPopulator(String scriptLocation) {
    public void execute() {
        DatabasePopulatorUtils.execute(this, dataSource);
@ActiveProfiles({"postgres", "jpa"})
public class TodoItemServiceTest {
    private DbPopulator dbPopulator;
    public void setUp() throws Exception {

Update: Spring 4.1 introduced an annotation that replaces DbPopulator:

Setting EntityManagerFactory

Accustomed to bugs in Spring 3.0 about undeclared entities in persistence.xml, I was surprised that everything works without it!
After some digging in the code, I saw that all target / classes are scanned for entity annotations. Also pleased with the ability to configure JPA without persistence.xml.
You can specify specific packages for scanning the model, configure provider-specific and general JPA parameters.
And they can be moved to a common file:


Choosing a connection pool implementation.

The traditional choice of implementing DataSource Commons DBCP seems to be losing ground.
According to StackOverflow, for implementation you need to take BoneCP , which is used in playframework (if you are already using it or are planning to,
note that some efforts are required to avoid memory leaks voiced in the report from the Plumbr developer ).
And PetClinic uses tomcat-jdbc .
If the application is deployed in Tomcat, you can not include it in war (scope = provided), but at the same time
you need to put the base driver in $ TOMCAT_HOME / lib , because the libraries of your war are not available from the native tomcat-jdbc.
And of course, when deploying to Tomcat, do not forget about the ability to take the connection pool from the
context.xml resources of the Tomcat configuration:

Spring data jpa

Accustomed in each project to create its own AbstractDAO, parameterized by the entity and key with the implementation of the main CRUDs based on EntityManager, he was glad that
he finally entered Spring, however, in the Spring Data JPA project: It inherits from the more general of Spring Data Commons . Working with JPA repositories is amazing at first: just write

    public interface UserRepository extends Repository {
       User findByEmail(String email);

and the method itself will work without a single line of implementation!

An appeal to the primary sources showed that the insides of magic are proxing, regexp and reflection:
  • first, the interface is JpaRepositoryFactory.getRepositoryBaseClassproxied in one of the implementations: QueryDslJpaRepository(when using
    Unified Queries for Java ) orSimpleJpaRepository
  • then all methods are analyzed - candidates for Query ( DefaultRepositoryInformation.isQueryMethodCandidate).
    Simplified, everything with an @Queryannotation and everything that is not in gets there JpaRepository;
  • then the method names are parsed in PartTree via
        PartTree.PREFIX_TEMPLATE: Pattern.compile("^(find|read|get|count|query)(\\p{Lu}.*?)??By")

    and seeks correspondence with the essence of the property;
  • finally, the method is trivially implemented through the JPA Criteria API .

A rhetorical question for readers: can java be considered a dynamic language :)?

If the JpaRepository and the generated methods are not enough, you can write your own implementation of the methods or Query queries .
You @Querycan write in JPQL queries (which are generated in @NamedQuery), or you can refer to those already declared @NamedQueryin entities (for some reason, they are @NamedQuery
ignored in PetClinic , although such queries are built and checked at the deployment stage).
For example, the method
    @Query(name = User.DELETE)
    int delete(@Param("id") int id);

refers to declared in User @NamedQuery
       @NamedQuery(name = User.DELETE, query = "DELETE FROM User u WHERE")
    public class User extends NamedEntity {
       public static final String DELETE = "User.delete";

Unlike void CrudRepository.delete(ID id)it, it will return the number of modified records.

However, there is a problem: the inheritance of the business data access interface from JpaRepositorymeans that the service level becomes implementation dependent.
In addition, for example, in the method, the Sort class is also located in Spring Data and you do not want to set it in services. The signature of the interface methods becomes attached to the signatures in . It’s inconvenient to debase and log in. All methods that we don’t need at the service level at all, or when inheriting from the marker , we don’t have a check, get to the business interface ... Another level of delegation solves all these problems:List findAll(Sort sort)

public interface ProxyUserRepository extends JpaRepository {
    @Query("DELETE FROM User u WHERE")
    int delete(int id);
    User save(User user);
    User findOne(Integer id);
    List findAll(Sort sort);
public class DataJpaUserRepository implements UserRepository {
    private static final Sort SORT_NAME_EMAIL = new Sort("name", "email");
    private ProxyUserRepository proxy;
    public boolean delete(int id) {
        return proxy.delete(id) != 0;
    public User save(User user) {
    public User get(int id) {
        return proxy.findOne(id);
    public List getAll() {
    return proxy.findAll(SORT_NAME_EMAIL);

Lastly: Resources by topic





If I like the article, I will prepare part 2 with the inappropriate Spring MVC, Spring Security, Jackson, etc.
Thank you for your attention, it will be interesting to hear your opinion on the topics raised.

Also popular now: