Spring MVC 3.x with STS Tutorial – Part III – Add some JPA

Michelle II

Creative Commons License photo credit: Shandi-lee

In the first version of this post, I showed how to do this using Roo. However, this seems to create too much pain, so I have updated the post to describe ‘normal’ usage of JPA (with the spring-data project). So – if you see comments below that seem irrelevant – this update is the reason.
In the previous part, we set up a little request flow that used Spring MVC to define a request mapping into our DOC system, and provide the user with a list of tramps retrieved from the a service. We also hooked it all up together nicely as components (using the @Controller and @Service Spring Stereotypes) – so they all play together seamlessly.
In this part we’ll get our tramps web application to read tramps information from the database. This is quite easy to do with Spring, using the spring-data project, particularly – spring-jpa.

First, you’ll need to set this up though. (Note that all the code can be found on github)

Set up for JPA

If you’ve followed the tutorial from the beginning, you set up the project as a Spring MVC template project. While this sets you up nicely for MVC – it doesn’t help much with JPA. In a nutshell – you wouldn’t have JPA configured in the project. You’ll have to do it yourself.

SQL Note:

I am using MySQL on localhost for this project, but you don’t have to. If you want to use MySQL as well, you’ll need to install it, create a database on it, and create a user that can access the database. If you don’t care too much – you can use an in-memory database. (See step 2 below).

Add dependencies to pom.xml

Open your pom.xml file and make sure the following dependencies are found there (you’ll probably need to add most of them)

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>${org.springframework-version}</version>
</dependency>
<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-jpa</artifactId>
  <version>1.2.0.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-orm</artifactId>
  <version>${org.springframework-version}</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-entitymanager</artifactId>
  <version>4.1.7.Final</version>
</dependency>
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.5</version>
  <scope>test</scope>
</dependency>      
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>${org.springframework-version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.6</version>
</dependency>

These are the libraries required to add the jpa and test support I dig into below.

Set up the entity

JPA is all about exposing your database as an object repository. It’s funny really – because there was a huge fight, and at the end object databases became esoteric IRL – but never mind that. The main thing is that it lets your programs treat data as objects rather than ResultSets of undetermined nature.
To simplify matters, let’s pretend that there are really two main layers you need when dealing with JPA: Entities and DAOs.

An entity

is really your object. In our application, a Tramp is an entity, because it is part of the domain of the problem we are trying to solve. (I know I didn’t actually put a problem forward, but an application is about solving problems, or creating problems – depends on who you ask).

A DAO

is the way to access and manipulate the entities. There are various ways to treat the role and form of DAOs, and also whether they are really required or not (e.g. you could use Active-Records) – but this is beside the point. Mainly – because Spring-data gives us a beautiful way to create them seamlessly – with the org.springframework.data.repository.Repository interface.

Let’s start this by creating our first entity – the Tramp. and an enum to describe the tramp’s difficulty level:

package com.duckranger.goodproject.domain;

public enum Difficulty {

  EASY_ACCESS("Easy access short walk"),
  SHORT("Short walk"),
  WALKING_TRACK("Walking track"),
  EASY_TRAMP("Great walk / Easier tramping track"),
  TRAMP("Tramping track"),
  ROUTE("Route");

  private String description;

  private Difficulty(String description) {
    this.description = description;
  }

  public String getValue() {
    return name();
  }

  public String getDescription() {
    return description;
  }

}

And the entity:

package com.duckranger.goodproject.domain;

import javax.persistence.Entity;
import org.springframework.data.jpa.domain.AbstractPersistable;

@Entity
public class Tramp extends AbstractPersistable<Long> {

  private static final long serialVersionUID = 1L;

  private String name;
  private double distance;
  private Difficulty difficulty; //Difficulty is the Enum from above

  //Below here - auto-generated getters and setters

}

This is a very ordinary class. Nothing really seems strange here, and that’s great. The magic happens in lines 6-7 alone. Outside those lines, an entity class is really just a POJO.
In line 6 – we annotate this class as an Entity. This is a RUNTIME-retention annotation that registers the Tramp class as a JPA entity. In runtime, spring-data will map it to the right table, over the right columns etc.
Now, obviously, there’s quite a bit of magic going on here, and I’ll touch on it in a later post, scouts-promise or whatever.

In line 7 – we declare that the Tramp class extends the AbstractPersistable class. I want to discuss this one a bit (but it is not completely material to the tutorial, so feel free to skip).

AbstractPersistable<PK>

org.springframework.data.jpa.domain.AbstractPersistable is a helper class that serves as a base class for entities. Your entities don’t have to extend it, and in some circumstances (e.g. when you want to use property-access on your entities) you shouldn’t use it – but for most uses, it is a nice little class to extend, and gives all your entities a few goodies out of the box:

package org.springframework.data.jpa.domain;

import java.io.Serializable;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import org.springframework.data.domain.Persistable;

/**
 * Abstract base class for entities. Allows parameterization of id type, chooses auto-generation and implements
 * {@link #equals(Object)} and {@link #hashCode()} based on that id.
 *
 * @author Oliver Gierke
 * @param <PK> the the of the entity
 */
@MappedSuperclass
public abstract class AbstractPersistable<PK extends Serializable> implements Persistable<PK> {
  private static final long serialVersionUID = -5554308939380869754L;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private PK id;

  public PK getId() {
    return id;
  }

  protected void setId(final PK id) {
    this.id = id;
  }

  public boolean isNew() {
    return null == getId();
  }

  @Override
  public String toString() {
    return String.format("Entity of type %s with id: %s", this.getClass().getName(), getId());
  }

  @Override
  public boolean equals(Object obj) {
    if (null == obj) {
      return false;
    }
    if (this == obj) {
      return true;
    }
    if (!getClass().equals(obj.getClass())) {
      return false;
    }

    AbstractPersistable<?> that = (AbstractPersistable<?>) obj;
    return null == this.getId() ? false : this.getId().equals(that.getId());
  }

  @Override
  public int hashCode() {
    int hashCode = 17;
    hashCode += null == getId() ? 0 : getId().hashCode() * 31;
    return hashCode;
  }
}
  1. Line 17: The class is annotated as @MappedSuperclass. A @MappedSuperclasshas two effects on code.
    • This class can be used as a base entity for other entities. For example – you can have a Transport class that is a @MappedSuperClass and has some common characteristics (name, maxSpeed, etc), and then you have a few implementation entities, all extending Transport class – Bicycle, Car, Motorbike, etc. Presumably – you end up with something like this: transportation class diagramA bit like polymorphism really. All the inheriting classes have everything that the base class has – so you save a lot of coding.
    • Your code can never use this class as an entity for JPA.
      You don’t want anyone creating a Transport object – so you don’t want JPA to create a database table for Transport objects specifically. You are only interested in the inheriting classes. When you make Transport a @MappedSuperclass then – even if it is not abstract – the class will never have a table all for itself. It will only be used to enrich the inheriting classes.
      As all the concrete transport classes extend Transport and are annotated as @Entity – they will each have a table of their own and participate, as Entities, in the JPA game.
  2. Line 18: Using Generics, the abstract persistable class is not limited to using a specific type for the primary key. While this seems permissive, the reality is (as we’ll see later) that only specific types are allowed. Also, you are probably going to use a Long primary key anyway. (Note that the source comment in line 15 is a bit vague…)
  3. Lines 21-23 define an id on the entity. The id is going to be of the Generic type used in the declaration (line 18) and annotating it as @Id tells JPA that this is the primary key of the entity (and it is assumed that this is the primary key of the table).
    Here are the main reasons why you might not want your entities to extend AbstractPersistable:

    • By annotating the id field, you force JPA to handle your entities with filed-access. This isn’t always desirable – but will be the case because the annotation is on the field itself and not on a method (this will be discussed in a separate post).
    • Using the @Id annotation the way it is done on AbstractPersistable assumes that your table’s primary key is found in a column named id, and that it is auto-generated. This is alright-ish for some types of new web applications, but suppose you already have a database schema, and your primary key is not found in a column called id or it isn’t automatically generated – and you can’t use AbstractPersistable without changing the schema.
    • I can’t think of a perfect example here, but using the @Id annotation makes your entity have an id – which may not always be the case. For example, in many-to-many relationships, you don’t have to have a primary key for each row, as you can do with a composite primary key or no primary key at all. Additionally, there are only certain types allowed to be used as @Id (the PK generic) – these are the primitives and their wrappers, String, java.util.Date, java.sql.Data, BigDecimal and BigInteger.

The rest of the code here is quite self-explanatory, and if your entities resemble this – than it’s a good idea to use AbstractPersistable (like I did!).

The DAO – a repository!

(In Spring, you can annotate a class with @Repository, and Spring will use it as a repository or a DAO. But I am using a different mechanism here).
Say hello to com.duckranger.goodproject.repository.TrampRepository:

package com.duckranger.goodproject.repository;

import org.springframework.data.repository.JpaRepository;
import com.duckranger.goodproject.domain.Tramp;

public interface TrampRepository extends JpaRepository<Tramp, Long> { }

Neat eh?
Now, this is my entire DAO. No, seriously.
Yes, seriously.
Well, almost seriously. The truth is that you have to add the following in your applicationContext.xml:

<beans xmlns=......
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
....
xsi:schemalocation=".....http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd...">

<jpa:repositories base-package="com.duckranger.goodproject.repository"/>

This will tell Spring where to look for your repositories (so you don’t have to annotate the interface with @Repository). But – the magic still remains! All we did here is create an interface, that extends another interface: org.springframework.data.repository.JpaRepository – what is going on here?
Well, I am glad you asked, because that’s one of the strong points of spring-data.
When I defined TrampRepository to extend JpaRepository, I also supplied the @Entity class I want it to work on, and the type of primary key that this class uses. When Spring scans my package for the jpa repositories, it will encounter this interface definition. Because it extends one of Spring-data’s repository interfaces, Spring will automatically generate (in runtime only) – a concrete object, of type TrampRepository – that provides all the functionality of JpaRepository for the Tramp class (with a Long primary key).
In essence, spring-data auto-generates a DAO for you. Only we call it repository, which is a nicer name.

So what does the JpaRepository give us?
As you’d expect – it gives us a JPA repository! (There are other types of repositories spring-data can give you. Have a look at PagingAndSortingRepository for example).

@NoRepositoryBean
public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {

  List<T> findAll();
  List<T> findAll(Sort sort);
  <S extends T> List<S> save(Iterable<S> entities);
  void flush();
  T saveAndFlush(T entity);
  void deleteInBatch(Iterable<T> entities);
  void deleteAllInBatch();
}

There are many more methods in the mother interfaces: PagingAndSortingRepository, and CrudRepository, which make the repositories into very powerful DAOs indeed. Here is a list of methods from CrudRepository:

@NoRepositoryBean
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {
 
  T save(T entity);
  Iterable<T> save(Iterable<? extends T> entities);
  T findOne(ID id);
  boolean exists(ID id);
  Iterable<T> findAll();
  long count();
  void delete(ID id);
  void delete(T entity);
  void delete(Iterable<? extends T> entities);
  void deleteAll();
}

These are all “normal” DAO methods. Because TrampRepository extends this interface – spring-data will generate a concrete TrampRepository in runtime, that provides all those methods, and hooks to the database automagically (well, using some definitions that spring-roo added for us…). Note how this interface itself is annotated as @NoRepositoryBean to ensure that spring is never tempted to create the raw repository interface as a concrete repository.

And now – revisit our TrampsService – to use the repository instead of an internal Map:

package com.duckranger.goodproject.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.duckranger.goodproject.domain.Tramp;
import com.duckranger.goodproject.repository.TrampRepository;

@Service
public class TrampsService {

  private static final Logger logger = LoggerFactory.getLogger(TrampsService.class);

  @Autowired
  private TrampRepository trampRepository;

  public Iterable<Tramp> findAll() {
    return trampRepository.findAll();
  }

  public Tramp save(Tramp t) {
    return trampRepository.save(t);
  }

  public void delete(Long id) {
    trampRepository.delete(id);
  }

  public Tramp findOne(Long id) {
    return trampRepository.findOne(id);
  }

  //more methods from TrampRepository
}

Not much to see here really. The service really only exposes the TrampRepository methods one for one. This is fine for now – and we’ll see in a later part of the tutorial how you can add some more concerns here.
The only notable thing is having the TrampRepository auto-wired to the service, much the same way that we auto-wired TrampsService itself into the TrampsController in the previous part of the tutorial.

Configuring JPA

JPA needs a little bit of xml-love to work with Spring, but it is really not a lot. First – We need to define a datasource to use (in this example, we deploy a datasource bean rather than configure it directly on the server). You can add this file to your resource location (note – in the github code you’ll see that I moved the spring configuration files to reside under /src/main/resources/META-INF. This is the ‘right’ place for them in my opinion. I am not too happy with the way the Spring MVC Template project creates them inside WEB-INF – but it isn’t really material to our case in hand.
Anyway – datasource.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
	  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/tramps"/>
    <property name="username" value="tramper"/>
    <property name="password" value="tramper"/>
  </bean>
</beans>

This file defines a simple dataSource bean, which uses the tramps database on a local MySQL server. (You should create it now if you haven’t yet, and add the tramper user as well).
Next, we need to add some definitions to the servlet-context.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
      http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
      http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

	
  <!-- Enables the Spring MVC @Controller programming model -->
  <mvc:annotation-driven />

  <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
  <mvc:resources mapping="/resources/**" location="/resources/" />

  <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
  </bean>
	
  <context:component-scan base-package="com.duckranger.goodproject" />
  <jpa:repositories base-package="com.duckranger.goodproject.repository"/>
  <tx:annotation-driven/>

  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="com.duckranger.goodproject.domain" />
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence" />
    <property name="loadTimeWeaver">
      <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
    </property>
    <property name="jpaProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        <prop key="hibernate.max_fetch_depth">3</prop>
        <prop key="hibernate.jdbc.fetch_size">50</prop>
        <prop key="hibernate.jdbc.batch_size">10</prop>
        <prop key="hibernate.show_sql">true</prop>
      </props>
    </property>
  </bean>

  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
  </bean>
</beans>

So what’s new here?

  1. The main change is in lines 32-48. In here we define a JPA entityManagerFactory bean, and bind it (line 33) to the dataSource bean we defined in datasource.xml.
  2. Line 34 – defines which packages contain the domain objects. Note – this needs Spring 3.1 at least. Starting with v3.1, the LocalContainerEntityManagerFactoryBean supports the packagesToScan property, and this means that you no longer have to create persistence.xml.
  3. Line 35 defines the persistence provider as Hibernate (i.e. we use Hibernate as the persistence layer)

The rest of the definitions are not directly relevant to the discussion right now, but have to do with specific hibernate properties. For example – for MySQL5 databases – you’d want
to use the right hiberante dialect (see line 41).

Let’s create the tramps table

In your MySQL, create the tramp table:

CREATE TABLE IF NOT EXISTS `tramp` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(60) NOT NULL,
  `distance` decimal(10,1) NOT NULL,
  `difficulty` int(2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Note that the name of the table is tramp – to match the name of the entity. It is easy enough to instruct the entity to use a different name. This is done using the @Table annotation on the entity class.

And that is really it! The TrampsController already uses trampsService.findAll() to populate its tramps list, so if you did everything right, we can use a dirty trick that relies on spring’s test support to start creating data in the table.

Create the first Tramp

Create the following under src/test/java:

package com.duckranger.goodproject.domain;

import junit.framework.Assert;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.duckranger.goodproject.service.TrampsService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:servlet-context.xml", "classpath*:datasource.xml" })
public class TrampTest {

    @Autowired
    TrampsService trampsService;

    @Test
    public void CreateTest() {
	Tramp t = new Tramp();
	t.setName("Tongariro Northern Circuit");
	t.setDistance(48.0);
	t.setDifficulty(Difficulty.EASY_TRAMP);
	trampsService.save(t);
	long id = t.getId();
	t = null;
	Tramp tt = trampsService.findOne(id);
	Assert.assertEquals("Tongariro Northern Circuit", tt.getName());
	tt = null;
    }

    public TrampsService getTrampsService() {
	return trampsService;
    }

    public void setTrampsService(TrampsService trampsService) {
	this.trampsService = trampsService;
    }

}

Also – copy the datasource.xml and servlet-context.xml under /src/test/resources. We do this to let our test classes have their own version of spring-configuration files, even if currently these are exact copies. In the future, you may want to provide different configs to test runs (e.g. use a different database) – and it’s easiest if you use a separate set of config files.

Now – right click the class, and select Run as->Junit Test. If everything works correctly, the Tongariro Northern Circuit will be added to your tramp table.

Let’s make the list-view nicer

The second-to-last thing to do before testing the great walks management system – is to change the view (list.jsp) slightly – so that it displays all the information we can provide it. In the previous parts – we only displayed the key and name of the tramp – but these are no longer with us – so we need to change the view to align with the Tramp class getters:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
    <link href="<c:url value="/resources/css/tramps.css" />" rel="stylesheet" type="text/css" media="screen" />
    <title>Listing Tramps</title>
</head>
<body>
<div class="container">
<h1>Tramps of New Zealand</h1>
<c:if test="${not empty tramps}">
 
    <table class="normal-table">
        <thead>
            <tr>
            	<th>Id</th>
                <th>Name</th>
                <th>Distance</th>
                <th>Difficulty</th>
            </tr>
        </thead>
        <tbody>
        <c:forEach var="tramp" items="${tramps}">
            <tr>
            	<td>${tramp.id }</td>
                <td>${tramp.name}</td>
                <td>${tramp.distance}</td>
                <td>${tramp.difficulty.description }</td>
            </tr>
        </c:forEach>
        </tbody>
    </table>
</c:if>
 
</div>
</body>
</html>

This isn’t something too complicated. Where before (in the previous parts of the tutorial) we had a simple map, now we actually have a collection of Tramp objects on the model. Hence, we can access the real attributes of these tramps, like ${tramp.name}.
Note how we get the description of the Tramp‘s Difficulty rather than the ENUM’s name.

Update web.xml

The last thing to do before running is to update web.xml with the location of our xml files (as they have moved).

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath:META-INF\root-context.xml
			classpath:META-INF\servlet-context.xml
			classpath:META-INF\datasource.xml
		</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:META-INF\servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

Now that is it. To test that your application works beautifully – run your application on the server (right click on GoodProject and select Run as->Run on server) – STS will deploy your application on tc-server. If you then go to http://localhost:8080/goodproject/tramps – you should see the results of your hard work:

The code for this project can be found on github

30 thoughts on “Spring MVC 3.x with STS Tutorial – Part III – Add some JPA

  1. Neal

    Hi duckRanger…
    Nice work!
    Roo has the power to write a service and Repository/DAO layers right now. So was wondering why you didn’t use spring roo from top to bottom(as used in the spring roo cookbook)..why just for stealing entities created by roo? Well you always have to custom-code, but was interested in whether you used roo to start off the Tramp controller, service and repository artifacts.
    I was trying to use roo with JSF with primefaces components. Didn’t know how to create new managed beans with roo. Was able to scaffold my db however. For the mvc add-on they have a command to make controllers..but don’t see anything similar with the jsf add-on. Any experience with it you could share?

  2. Duck Ranger Post author

    @Neal – I am thinking of this tutorial more as a spring-mvc tutorial rather than a roo one – so that’s why I am using it this way. Also – I didn’t ‘steal’ entities created by roo. I only used it to add the relevant jpa dependencies into the project, because it is a very easy to shortcut to use.

    As for roo with JSF/primefaces – it is quite nicely documented here: http://static.springsource.org/spring-roo/reference/html/base-jsf.html – good luck.

  3. Neal

    Thanks for the reply…
    Prima facie looks like they have it covered at that link you provided.
    But there is no way you can make a ManagedBean the way you want to. They try to tie a ManagedBean to an entity(which may be related to many entities in the db). However, if I want make an UI which, say, use five different entities within it, then I can’t use that addon. Also the xhtml page supported by the ManagedBean generated takes the name of the entity it backs(say I have an User entity, then the page will be named user.xhtml have a ManagedBean called UserBean with the annotation like so:
    [java]
    @RooJsfManagedBean(entity = User.class, beanName = "userBean")
    public class UserBean {
    }
    [/java]
    To tie a managedBean to a single entity is lame, imo.
    They should have a command called “web jsf managedBean” just like existing “web mvc controller” and then I can do something like this in mvc world:
    web mvc controller –class com.foo.web.CarController –preferredMapping /public/car
    Now I can go and modify this controller any way I want to

    (Maybe after 10 years when I see this entry I might cringe at not understanding Roo perfectly at this point in time:)

  4. Neal

    One more thing…terminologies..managedBean and backingBean are two diff concepts.
    The former is like a pojo and the latter is like a controller. The roo jsf addon does not show how you can create a backingBean…that is my whole dilemma. They only allow to create a managedBean. ManagedBeans shld be injected into backingBeans. For example I could have a RegistrationBackingBean using UserManagedBean , ABCManagedBean, XYZManagedBean and many other managedBeans as I deem fit to be on the RegistrationBackingBean.
    So in effect roo should have a command like “web jsf backingBean -addManagedBeans UserManagedBean,ABCManagedBean,XYZManagedBean”. Currently roo jsf addon forces you to have managedBean equal your backingBean.

  5. Duck Ranger Post author

    @Neal – I think you are right and that the JSF addon to roo is “not there yet” – but we are sort of digressing from the subject of this tutorial :)

  6. john ding

    When I ran command jpa setup –provider HIBERNATE –database MYSQL, I got the following error: File ‘C:\workspace-sts-2.8.1.RELEASE\mySpringMvcJpa\src\main\resources\META-INF\spring\applicationContext.xml’ does not exist.

    How to fix it? Please help.

  7. Duck Ranger Post author

    @john – roo expects your main configuration file to be in src/main/resources/META_INF/spring/applicationContext.xml. If it isn’t found in your project- just create it. Roo will handle it.

  8. Mike

    Thanks so much this is just what I have been looking for!
    Such good explanations thanks again…

  9. st

    Very nice tutorial.
    I have followed all the steps and when I try to run the test I get the below error:

    Caused by: org.xml.sax.SAXParseException: cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ‘jpa:repositories’.

    Any idea? I know its from my Application context..

    < ?xml version="1.0" encoding="UTF-8" standalone="no"?>
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/jee
    http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

  10. Pingback: no declaration can be found for element ‘jpa:repositories’ | Jisku.com - Developers Network

  11. Alper

    Hi,

    When I try to execute “jpa setup” command, Roo says “Command was found but is not currently available”. What should I do?

    Thanks.

  12. Duck Ranger Post author

    @Alper – this means that you can’t run jpa setup “now” – as dependencies are not met. What have you done prior to running this?

  13. Alper

    I have installed STS as it is. Then I agreed to some text in order to allow STS to download stuff from internet. Nothing else.

  14. Sean

    This lesson is not as clean as the other two.
    1. applicationContext.xml is missing. “Just adding it” does not mean an empty file but it must be this:

    2. something is wrong with the roo adjustment to maven’s pom file. the pom file has an error on it but nothing within it is marked in error. I am new to all of this. I’m good at java using ant,jsps,servlets but I haven’t really used maven and when roo messes up it ends up being more painful than helpful. Bottom line, java is not recognizing the javax.persistence package or the org.springframework.data package.

    I wanted to finish this tutorial but I don’t want to keep fighting my way to the end. I have the spring cookbook book so I’m switching over to that. I do appreciate the work you’ve done here, so thanks. the first two tutorials were quite nice.

  15. DK

    @Sean
    I agree with you. I really-really like the way Duck Ranger explains things, there is nothing quite like it on the web. While others just paste their whole code saying “this is how I’ve done it”, Duck Ranger communicates why it’s done like this.
    But seems like the deeper we go the more things are left out. Maybe full working source code snapshot posted somewhere could help.

    p.s. at this point of tutorial I seem to understand all the concepts, but cannot get my project to run (looks like that same problem with applicationContext mentioned above).
    p.p.s. I’m trying to avoid Roo for now, to make everything work by hand.

  16. Duck Ranger Post author

    @Sean, @DK –
    First – thanks for your positive comments – really appreciate it.
    Second – I haven’t had a lot of time to answer here (sorry…) as I am trying to work on a better grounds-up tutorial for Spring MVC – and frankly – I’d just ditch roo altogether at this point (it has merits, but not so much for learning.. I see this now).

    I have just updated the tutorial and removed roo – as I find it was a bit useless in this context :( – I have also added the code to github.

    Cheers, Duck

  17. DK

    Great! will try it out right away. Based on the site going up and down, you’re making changes as I speak. So couple of comments:
    you’re still referencing spring-roo in the text and quoting CrudRepository while I see you switched to JpaRepository.
    Also, applicationContext.xml still appears from nowhere. Is it supposed to be servlet-context.xml there?

  18. DK

    Woo hoo!
    I followed the tutorial from the beginning creating all artifacts manually (not just pulled from the git) and it now works great! In my case the database stores birds and they are now chirping and singing happily.
    I didn’t move servlet-context.xml et al around as you did, and I find it a bit confusing that you have duplicate xmls in META-INF and WEB-INF on git… Also, getting rid of persistence.xml was a bit surprising ;).

    Anyway, with this rework of the article you really added exactly what was needed. Great job! You’re my hero! :)

    p.s. you may want to add test for the test entry in pom.xml

  19. DK

    hmm, the form removed the tags. last sentence was about limiting the scope to test for unit test stuff.

  20. Duck Ranger Post author

    @DK – good one! I like it how you did some quality-assurance here :)
    Good spotting on the spring-test scope – added it now.
    As for moving the configuration files around – like I said – you don’t absolutely have to do that – but I like keeping separate sets of configuration files for testing purposes. Of course – if you have exact copies, you can just point your test cases to use the /src/java/resources files. No harm there.

    As for persistence.xml…
    I probably should have mentioned that you need Spring 3.1 for this neat trick (I have updated it in the post now). Starting with v3.1, the LocalContainerEntityManagerFactoryBean supports the packagesToScan property (which I used in servlet-context). This means that you no longer have to create persistence.xml – neat eh?

    Good luck with those birds! I just got a Tui in my front yard… it chirps nicely.

  21. Stark

    Hi, I’m trying to set up jpa in my context. But it won’t load when I add the <jpa:repositories… tag. I'm getting this exception: java.lang.Exception: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.

    Any idea what I'm doing wrong?
    Thanks for any help you can offer.

  22. Stark

    Finally found some time to dig around in this. It was rather simple, really.

    It seems that my generated context file differed from yours in some ways. My file defined the first line of the beans tag with “http://www.springframework.org/schema/mvc” and missing some other entries that you had. I moved that behind xmlns:mvc and replaced the first line with “http://www.springframework.org/schema/beans”. After I switched around the tags, the xml loaded without errors.

    What I still don’t get is what made it fail earlier. I had mvc, beans and jpa mapped to respectively xmlns, xmlns:beans and xmlns:jpa. I would have thought that this would be fine as long as I tagged them correctly later. I.E. beans:bean, jpa:resources, annotation-driven. Rather than bean, jpa:resources and mvc:annotation-driven using your configuration.

    Hope I’m making some sense ;)

  23. Duck Ranger Post author

    @stark – there could be a number of reasons for failure, but I found in some cases there are bizarre issues with XML (e.g. – adding a space to a generated file, and saving it…) – so I wouldn’t be surprised.
    Have you had a look at STS logs?

  24. Ibn Adam

    I was able to complete the 1st two tutorials but in this one, i am getting lots of errors. I think i dont have correct pom.xml settings as everything else is matching with source code provided. is there a way to share pom.xml? thanks in advance.

  25. Dave

    I notice that you put the servlet-context.xml in both the root context and the dispatcherservlet context. I’m not sure, but isn’t this a mistake?

  26. Jack

    Rad tutorial. Got tripped up with the applicationContext.xml business but got it all squared when I decided to read this page from the bottom up (re: go to Git).

    Thanks for making Spring MVC learn-able in 1 day.

    Ps – also thanks for hot girl images on each page.

  27. Angel Camacho

    in the end of my Application context of the second application, i CAN persist anything of the first project on the second project, BUT i CAN’T persist anymore the things of the second project.

  28. denilugito

    FYI, the JPA library location changed from import “org.springframework.data.repository.JpaRepository;” into “import org.springframework.data.jpa.repository.JpaRepository;”

  29. Lotfi

    First I would like to thank you for this great work, it was very interesting for me and I followed it from the beginning without stopping ! Thank you very much !

    I have a small question on how can I configure my datasource.xml to get auto-creation of database tables (standalone application) without having to create tables manually in the MySQL Administration.

    If you have an answer for me, please notify me by mail !

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>