Getting Started With JPA in Spring 2.0

The motivation behind this blog entry is to provide a simple step-by-step guide for getting started with JPA in a standalone environment with the Spring Framework. While the JPA specification originated as the persistence mechanism for EJB 3.0, it was fortunately recognized that any such mechanism should in fact be able to persist simple POJOs. Therefore, with a handful of JARs in your classpath and a few Spring-configured beans, you can begin experimenting with JPA code within your favorite IDE. I will be using Glassfish JPA - which is the reference implementation and is based upon Oracle’s TopLink ORM framework.
Initial Setup
Ensure that you are using Java 5 (a prerequisite for JPA as well as EJB 3.0).
Download the glassfish JPA jar from: https://glassfish.dev.java.net/downloads/persistence/JavaPersistence.html
(NOTE: I used the “V2_build_02″ jar, but any later version should also work.)
To unbundle the jar from the “installer� jar, run:
java -jar glassfish-persistence-installer-v2-b02.jar
(this is required for acceptance of the license agreement)
Add the toplink-essentials.jar to your classpath
Add the JAR containing your database driver (I am using hsqldb.jar version 1.8.0.1 in the example, but only minor changes are necessary to adapt for another database).
Add the following Spring JARs using the 2.0 M5 versions (available here: http://sourceforge.net/project/showfiles.php?group_id=73357).
- spring.jar
- spring-jpa.jar
- spring-mock.jar
Finally, add these jars to your classpath as well:
- commons-logging.jar
- log4j.jar
- junit.jar
Code - Domain Model
This example will be based on a purposefully simple domain model of just 3 classes. Notice the use of annotations. With JPA, one may choose to use either annotations or an XML file to specify the object-relational mapping metadata - or even a combination of both approaches. Here, I have chosen to use solely annotations - for which brief descriptions will be provided immediately following the domain model code listings.
First, the Restaurant class:
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
@Entity
public class Restaurant {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
@OneToOne(cascade = CascadeType.ALL)
private Address address;
@ManyToMany
@JoinTable(inverseJoinColumns = @JoinColumn(name = "ENTREE_ID"))
private Set<Entree> entrees;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Set<Entree> getEntrees() {
return entrees;
}
public void setEntrees(Set<Entree> entrees) {
this.entrees = entrees;
}
}
Second, the Address class:
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(name = "STREET_NUMBER")
private int streetNumber;
@Column(name = "STREET_NAME")
private String streetName;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getStreetNumber() {
return streetNumber;
}
public void setStreetNumber(int streetNumber) {
this.streetNumber = streetNumber;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
}
Third, the Entree class:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Entree {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private boolean vegetarian;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
}
As you can see, not every persistent field has been annotated. JPA uses defaults (such as using a column name that matches the property name exactly) so that in many cases you do not need to specify the metadata explicitly. However, you may still choose to do so in order to provide more thoroughly self-documenting code. Notice that in the Entree class I am not using annotations for the String property “name� or the boolean property “vegetarian�. However, in the Address class, I am using the annotations, because I want to have a non-default name for the columns in the database (for example, I have chosen “STREET_NAME� whereas the default would have been “STREETNAME�).
Of course, one of the most important features of any ORM mechanism is the way in which one specifies the mapping from relationships between Objects to their database counterparts. In the Restaurant class, there is a @OneToOne annotation to describe the relationship to an Address and a @ManyToMany annotation to describe the relationship with members of the Entree class. Since instances of these other classes are also being managed by the EntityManager, it is possible to specify “cascade� rules. For example, when a Restaurant is deleted, the associated Address will also be deleted. In a moment, you will see a testcase for this scenario.
Finally, take a look at the @Id annotations and the specified “strategy� for the ID’s @GeneratedValue. This metadata is used for describing the primary key generation strategy which in turn controls the identity within the database.
To learn much more about these and additional JPA annotations, check out the JPA specification - which is actually a subset of JSR-220.
Code - Data Access Layer
For accessing instances of the domain model, it is best to create a generic interface that hides all details about the underlying persistence mechanism. That way, if switching later to something other than JPA, there will be no impact on the architecture. This also makes it easier to test the service layer, since it enables the creation of stub implementations of this data access interface - or even dynamic mock implementations.
Here is the interface. Notice that there are no dependencies on any JPA or Spring classes. In fact, the only dependencies here that are not core Java classes are the classes of my domain model (in this simple case, there is only one - Restaurant):
import java.util.List;
import blog.jpa.domain.Restaurant;
public interface RestaurantDao {
public Restaurant findById(long id);
public List<Restaurant> findByName(String name);
public List<Restaurant> findByStreetName(String streetName);
public List<Restaurant> findByEntreeNameLike(String entreeName);
public List<Restaurant> findRestaurantsWithVegetarianEntrees();
public void save(Restaurant restaurant);
public Restaurant update(Restaurant restaurant);
public void delete(Restaurant restaurant);
}
For the implementation of this interface, I am going to extend Spring’s JpaDaoSupport class. This provides a convenience method for retrieving the JpaTemplate. If you have used Spring with JDBC or other ORM technologies, then you will probably be quite familiar with this approach.
It should be noted that use of the JpaDaoSupport is optional. It is possible to construct a JpaTemplate directly by simply providing the EntityManagerFactory to its constructor. In fact, the JpaTemplate itself is optional. If you do not wish to have the automatic translation of JPA exceptions into Spring’s runtime exception hierarchy, then you can avoid JpaTemplate altogether. In that case, you may still be interested in Spring’s EntityManagerFactoryUtils class which provides a convenient static method for obtaining the shared (and thus transactional) EntityManager.
Here is the implementation:
import java.util.List;
import org.springframework.orm.jpa.support.JpaDaoSupport;
import blog.jpa.domain.Restaurant;
public class JpaRestaurantDao extends JpaDaoSupport implements RestaurantDao {
public Restaurant findById(long id) {
return getJpaTemplate().find(Restaurant.class, id);
}
public List<Restaurant> findByName(String name) {
return getJpaTemplate().find("select r from Restaurant r where r.name = ?1", name);
}
public List<Restaurant> findByStreetName(String streetName) {
return getJpaTemplate().find("select r from Restaurant r where r.address.streetName = ?1", streetName);
}
public List<Restaurant> findByEntreeNameLike(String entreeName) {
return getJpaTemplate().find("select r from Restaurant r where r.entrees.name like ?1", entreeName);
}
public List<Restaurant> findRestaurantsWithVegetarianEntrees() {
return getJpaTemplate().find("select r from Restaurant r where r.entrees.vegetarian = 'true'");
}
public void save(Restaurant restaurant) {
getJpaTemplate().persist(restaurant);
}
public Restaurant update(Restaurant restaurant) {
return getJpaTemplate().merge(restaurant);
}
public void delete(Restaurant restaurant) {
getJpaTemplate().remove(restaurant);
}
}
The Service Layer
As the purpose here is to focus on a JPA implementation for the data-access layer, the service layer is omitted. Obviously, in a realistic scenario, the service layer would play a critical role in the system architecture. It would be the point where transactions are demarcated - and typically, they would be demarcated declaratively in the Spring configuration. In the next step, when you have a look at the configuration, you will notice that I have provided a “transactionManager� bean. It is used by the base test class to automatically wrap each test method in a transaction, and it is the same “transactionManager� that would wrap service layer methods with transactions. The main point to take away is that there is NO transaction-related code in the data-access tier. Using the Spring JpaTemplate ensures that the same EntityManager is shared across all DAOs. Therefore transaction propagation occurs automatically - as dictated by the service layer. In other words, it will actually behave exactly the same as other persistence mechanisms configured within the Spring framework. There is nothing JPA-specific - hence the rationale for leaving it out of this entry which is focused on JPA.
Configuration
Since I opted for the annotation-based mappings, you have actually already seen most of the JPA-specific configuration when the domain classes were presented. As mentioned above, it also would have been possible to configure those mappings via XML (in an ‘orm.xml’ file). The only other required configuration is in ‘META-INF/persistence.xml’. In this case, that is very simple since the database-related properties will be available to the EntityManagerFactory via a dependency-injected “dataSource� provided in the Spring configuration (due up next). The only other information in this ‘persistence.xml’ is whether to use local or global (JTA) transactions. Here are the contents of the ‘persistence.xml’ file:
<persistence-unit name="SpringJpaGettingStarted" transaction-type="RESOURCE_LOCAL"/>
</persistence>
There are only 4 beans in the Spring configuration (well ok, a couple of inner-beans too). First, there is the “restaurantDao� (I purposefully left “jpa� out of the bean name since any service layer beans depending on the DAO should only be concerned with the generic interface). The only required property for the JPA implementation of this DAO is the “entityManagerFactory� which it uses to create the JpaTemplate. The “entityManagerFactory� depends on the “dataSource�, and there is nothing JPA-specific about that. In this configuration, you will see a DriverManagerDataSource, but in production code, this would be replaced by a connection pool - and typically one obtained via a JndiObjectFactoryBean (or Spring 2.0’s new convenience
<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="restaurantDao" class="blog.jpa.dao.JpaRestaurantDao">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.ContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.TopLinkJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="databasePlatform" value="oracle.toplink.essentials.platform.database.HSQLPlatform"/>
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver"/>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost/"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
First you see that the “entityManagerFactory� needs to be aware of a “dataSource�. Next there is the “jpaVendorAdapter� as there are a variety of JPA implementations. In this case, I’ve configured the TopLinkJpaVendorAdapter as an inner bean, and it has a few properties of its own. There is a boolean property to specify whether SQL should be shown and another boolean property for the generation of DDL. Both of these have been set to “true� and thus the database schema will be automatically generated each time the tests are executed. This is rather convenient in the early development phase as it provides immediate feedback for experimentations in the mappings, column names, etc. The “databasePlatformClass� provides the necessary information of what particular database is being used. Finally, the “entityManagerFactory� has a property for a “loadTimeWeaver� that plays a role in the transformation of class files by JPA persistence providers in order to accomodate certain features such as lazy-loading.
Integration Testing
Perhaps the best way to learn a new API is to write a bunch of testcases. The JpaRestaurantDaoTests class provides some basic tests. In order to learn more about JPA, modify the code and/or configuration and observe the impact on these tests. For example, try modifying the cascade settings - or the cardinality of the associations. Notice that JpaRestaurantDaoTests extends Spring’s AbstractJpaTests. You may already be familiar with Spring’s AbstractTransactionalDataSourceSpringContextTests. This class will behave the same way in that any database changes caused by the test methods will rollback by default. AbstractJpaTests actually does much more than that, but it is beyond the scope of this entry to go into those details. If interested, have a look at the source code for AbstractJpaTests.
Here is the JpaRestaurantDaoTests code:
import java.util.List;
import org.springframework.test.jpa.AbstractJpaTests;
import blog.jpa.dao.RestaurantDao;
import blog.jpa.domain.Restaurant;
public class JpaRestaurantDaoTests extends AbstractJpaTests {
private RestaurantDao restaurantDao;
public void setRestaurantDao(RestaurantDao restaurantDao) {
this.restaurantDao = restaurantDao;
}
protected String[] getConfigLocations() {
return new String[] {"classpath:/blog/jpa/dao/applicationContext.xml"};
}
protected void onSetUpInTransaction() throws Exception {
jdbcTemplate.execute("insert into address (id, street_number, street_name) values (1, 10, 'Main Street')");
jdbcTemplate.execute("insert into address (id, street_number, street_name) values (2, 20, 'Main Street')");
jdbcTemplate.execute("insert into address (id, street_number, street_name) values (3, 123, 'Dover Street')");
jdbcTemplate.execute("insert into restaurant (id, name, address_id) values (1, 'Burger Barn', 1)");
jdbcTemplate.execute("insert into restaurant (id, name, address_id) values (2, 'Veggie Village', 2)");
jdbcTemplate.execute("insert into restaurant (id, name, address_id) values (3, 'Dover Diner', 3)");
jdbcTemplate.execute("insert into entree (id, name, vegetarian) values (1, 'Hamburger', 0)");
jdbcTemplate.execute("insert into entree (id, name, vegetarian) values (2, 'Cheeseburger', 0)");
jdbcTemplate.execute("insert into entree (id, name, vegetarian) values (3, 'Tofu Stir Fry', 1)");
jdbcTemplate.execute("insert into entree (id, name, vegetarian) values (4, 'Vegetable Soup', 1)");
jdbcTemplate.execute("insert into restaurant_entree (restaurant_id, entree_id) values (1, 1)");
jdbcTemplate.execute("insert into restaurant_entree (restaurant_id, entree_id) values (1, 2)");
jdbcTemplate.execute("insert into restaurant_entree (restaurant_id, entree_id) values (2, 3)");
jdbcTemplate.execute("insert into restaurant_entree (restaurant_id, entree_id) values (2, 4)");
jdbcTemplate.execute("insert into restaurant_entree (restaurant_id, entree_id) values (3, 1)");
jdbcTemplate.execute("insert into restaurant_entree (restaurant_id, entree_id) values (3, 2)");
jdbcTemplate.execute("insert into restaurant_entree (restaurant_id, entree_id) values (3, 4)");
}
public void testFindByIdWhereRestaurantExists() {
Restaurant restaurant = restaurantDao.findById(1);
assertNotNull(restaurant);
assertEquals("Burger Barn", restaurant.getName());
}
public void testFindByIdWhereRestaurantDoesNotExist() {
Restaurant restaurant = restaurantDao.findById(99);
assertNull(restaurant);
}
public void testFindByNameWhereRestaurantExists() {
List<Restaurant> restaurants = restaurantDao.findByName("Veggie Village");
assertEquals(1, restaurants.size());
Restaurant restaurant = restaurants.get(0);
assertEquals("Veggie Village", restaurant.getName());
assertEquals("Main Street", restaurant.getAddress().getStreetName());
assertEquals(2, restaurant.getEntrees().size());
}
public void testFindByNameWhereRestaurantDoesNotExist() {
List<Restaurant> restaurants = restaurantDao.findByName("No Such Restaurant");
assertEquals(0, restaurants.size());
}
public void testFindByStreetName() {
List<Restaurant> restaurants = restaurantDao.findByStreetName("Main Street");
assertEquals(2, restaurants.size());
Restaurant r1 = restaurantDao.findByName("Burger Barn").get(0);
Restaurant r2 = restaurantDao.findByName("Veggie Village").get(0);
assertTrue(restaurants.contains(r1));
assertTrue(restaurants.contains(r2));
}
public void testFindByEntreeNameLike() {
List<Restaurant> restaurants = restaurantDao.findByEntreeNameLike("%burger");
assertEquals(2, restaurants.size());
}
public void testFindRestaurantsWithVegetarianOptions() {
List<Restaurant> restaurants = restaurantDao.findRestaurantsWithVegetarianEntrees();
assertEquals(2, restaurants.size());
}
public void testModifyRestaurant() {
String oldName = "Burger Barn";
String newName = "Hamburger Hut";
Restaurant restaurant = restaurantDao.findByName(oldName).get(0);
restaurant.setName(newName);
restaurantDao.update(restaurant);
List<Restaurant> results = restaurantDao.findByName(oldName);
assertEquals(0, results.size());
results = restaurantDao.findByName(newName);
assertEquals(1, results.size());
}
public void testDeleteRestaurantAlsoDeletesAddress() {
String restaurantName = "Dover Diner";
int preRestaurantCount = jdbcTemplate.queryForInt("select count(*) from restaurant");
int preAddressCount = jdbcTemplate.queryForInt("select count(*) from address where street_name = 'Dover Street'");
Restaurant restaurant = restaurantDao.findByName(restaurantName).get(0);
restaurantDao.delete(restaurant);
List<Restaurant> results = restaurantDao.findByName(restaurantName);
assertEquals(0, results.size());
int postRestaurantCount = jdbcTemplate.queryForInt("select count(*) from restaurant");
assertEquals(preRestaurantCount - 1, postRestaurantCount);
int postAddressCount = jdbcTemplate.queryForInt("select count(*) from address where street_name = 'Dover Street'");
assertEquals(preAddressCount - 1, postAddressCount);
}
public void testDeleteRestaurantDoesNotDeleteEntrees() {
String restaurantName = "Dover Diner";
int preRestaurantCount = jdbcTemplate.queryForInt("select count(*) from restaurant");
int preEntreeCount = jdbcTemplate.queryForInt("select count(*) from entree");
Restaurant restaurant = restaurantDao.findByName(restaurantName).get(0);
restaurantDao.delete(restaurant);
List<Restaurant> results = restaurantDao.findByName(restaurantName);
assertEquals(0, results.size());
int postRestaurantCount = jdbcTemplate.queryForInt("select count(*) from restaurant");
assertEquals(preRestaurantCount - 1, postRestaurantCount);
int postEntreeCount = jdbcTemplate.queryForInt("select count(*) from entree");
assertEquals(preEntreeCount, postEntreeCount);
}
}
Further Reading
JPA is a vast topic, and this blog has only scratched the surface - the main objective being to demonstrate the basic configuration of a JPA-based persistence implementation with Spring. Obviously this domain model is trivial in terms of Object-Relational mapping. However, once you have this working configuration, you will be able to extend the example here while exploring the ORM capabilities offered by JPA. I would highly encourage a closer look at the Spring JPA support via the JavaDoc and the Spring reference documentation. The 2.0 RC1 release contains an added sub-section on JPA within the ORM section of the reference document.
Here are a few helpful links:
JSR-220 (contains the JPA specification)
Glassfish JPA (the reference implementation)
Kodo 4.0 (BEA’s JPA implementation based on Kodo)
Hibernate JPA Migration Guide
ehsavoie says:
Added on August 3rd, 2006 at 7:46 am -QuoteHi,
in RC2 with a slight correction
The example is working fine
should be
.
I'm trying to add transaction annotation to your DAO. When I add :
All goes wrong
((
Error creating bean with name 'restaurantDao' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor': Cannot create inner bean '(inner bean)' while setting bean property 'transactionInterceptor'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restaurantDao' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor': Cannot create inner bean '(inner bean)' while setting bean property 'transactionInterceptor'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor': Cannot create inner bean '(inner bean)' while setting bean property 'transactionInterceptor'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor': Cannot create inner bean '(inner bean)' while setting bean property 'transactionInterceptor'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)': Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
Caused by: java.lang.NullPointerException
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:239)
What am I missing ??
Thanks
Emmanuel
ehsavoie says:
Added on August 3rd, 2006 at 7:49 am -QuoteSorry the XML was removed
(
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.ContainerEntityManagerFactoryBean">
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<tx:annotation-driven transaction-manager="transactionManager"/>
ehsavoie says:
Added on August 3rd, 2006 at 8:13 am -QuoteThis seems to be a bug with RC2 (http://forum.springframework.org/showthread.php?t=26771&highlight=tx:annotation-driven).
Ali says:
Added on August 11th, 2006 at 11:50 am -QuoteHi,
Thx for your Tutorial but unfortunately doesn’t work!
can you please getting your example working
and this ContainerEntityManagerFactoryBean does'nt exit so i replace it with LocalContainerEntityManagerFactoryBean
I've got the Same Problem
Thx
Best Regards
Ali
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'restaurantDao' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Error setting property values; nested exception is PropertyAccessExceptionsException (1 errors)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Cannot resolve reference to bean 'dataSource' while setting bean property 'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Error setting property values; nested exception is PropertyAccessExceptionsException (1 errors)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [blog/jpa/dao/applicationContext.xml]: Error setting property values; nested exception is PropertyAccessExceptionsException (1 errors)
Caused by: PropertyAccessExceptionsException (1 errors)
org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception; nested exception is org.springframework.jdbc.CannotGetJdbcConnectionException: Could not load JDBC driver class [org.hsqldb.jdbcDriver]; nested exception is java.lang.ClassNotFoundException: org.hsqldb.jdbcDriver
Caused by: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not load JDBC driver class [org.hsqldb.jdbcDriver]; nested exception is java.lang.ClassNotFoundException: org.hsqldb.jdbcDriver
Caused by: java.lang.ClassNotFoundException: org.hsqldb.jdbcDriver
at org.springframework.instrument.classloading.ShadowingClassLoader.doLoadClass(ShadowingClassLoader.java:97)
at org.springframework.instrument.classloading.ShadowingClassLoader.loadClass(ShadowingClassLoader.java:58)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:242)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:160)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:138)
at org.springframework.jdbc.datasource.DriverManagerDataSource.setDriverClassName(DriverManagerDataSource.java:148)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:737)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:575)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValue(AbstractPropertyAccessor.java:49)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:68)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:57)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:816)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:392)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:240)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:132)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:237)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:153)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:225)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:114)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:801)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:392)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:240)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:132)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:237)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:153)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:225)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:114)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:801)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:392)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:240)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:132)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:237)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:153)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:254)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:337)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.springframework.test.jpa.AbstractJpaTests.runBare(AbstractJpaTests.java:212)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Ali says:
Added on August 14th, 2006 at 6:13 am -QuoteThe Example works Fun after some correction!
Thx
Ali
Andre says:
Added on August 22nd, 2006 at 6:47 pm -QuoteHi,
I am running into this problem :
Exception Description: A problem was encountered resolving the class name - The descriptor for [Restaurant] was not found.
You guys that got this example goign which mods did you have to do ?
regards,
Andre
Andre says:
Added on August 22nd, 2006 at 6:58 pm -QuoteOk!!
Got it working know from in Eclipse.
This worked for me :
I added an instance of org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean for my entityManagerFactory. The important thing was to set the persistenceXmlLocation property. This refers to ones persistnce.xml file which should in the classpath.
My Config :
persistence.xml
Andrew S says:
Added on October 12th, 2006 at 2:29 am -QuoteHi , i looking for example how run spring 2.0 with toplink jpa on j2se application. Can anybody help ??
Paul Smith says:
Added on October 16th, 2006 at 2:09 am -QuoteGreat blog. The example worked perfectly for me.
However, it would be great if you could follow up with the details on how to run the same example using a Java SE main() method (instead of the test program, where the test extends AbstractJpaTests). I have tried to make it work, but unfortunately, I end up with the following error:
Object is not a known entity type.
Here is my main() (same as your example, but with my own data):
public static void main(String[] args) {
ApplicationContext appCtxt = new ClassPathXmlApplicationContext("conf/spring.xml");
meetService = (MeetDao)appCtxt.getBean("meetDao");
Meet meet = new Meet();
MeetTest.setWithTestValues(meet, "test1");
meetService.save(meet);
}
at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:3178)
at oracle.toplink.essentials.internal.ejb.cmp3.base.EntityManagerImpl.persist(EntityManagerImpl.java:170)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:237)
at $Proxy11.persist(Unknown Source)
at org.springframework.orm.jpa.JpaTemplate$5.doInJpa(JpaTemplate.java:255)
at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:183)
at org.springframework.orm.jpa.JpaTemplate.persist(JpaTemplate.java:253)
at dao.MeetDaoJpa.save(MeetDaoJpa.java:31)
at dao.MeetDaoTest3.main(MeetDaoTest3.java:20)
I'm a spring novice, so I'm probably forgetting something obvious.
Any insight into this would be *greatly* appreciated.
Thanks,
Paul
sateesh says:
Added on October 18th, 2006 at 12:00 pm -QuoteHi,
Has any one tried running this sample in NetBeans??
Do i need to have AspectJ Module installed inorder to run this one !!
Thanks
Sateesh
sateesh says:
Added on October 18th, 2006 at 2:35 pm -QuoteOn October 18, 2006 at 12:00 pm, sateesh said:
sateesh says:
Added on October 18th, 2006 at 3:04 pm -QuoteHi All,
I added the following Bean to the applicationContext.xml
and i have another Class with main() whose code is listed below..
public static void main(String[] args) {
ApplicationContext appCtxt = new ClassPathXmlApplicationContext("META-INF/applicationContext.xml");
JpaRestaurantDaoTests testsDao = (JpaRestaurantDaoTests)appCtxt.getBean("testsDao");
try{
testsDao.onSetUpInTransaction();
testsDao.testDeleteRestaurantAlsoDeletesAddress();
testsDao.testDeleteRestaurantDoesNotDeleteEntrees();
testsDao.testFindByEntreeNameLike();
testsDao.testFindByIdWhereRestaurantDoesNotExist();
testsDao.testFindByIdWhereRestaurantExists();
testsDao.testFindByNameWhereRestaurantDoesNotExist();
testsDao.testFindByNameWhereRestaurantExists();
testsDao.testFindByStreetName();
testsDao.testFindRestaurantsWithVegetarianOptions();
testsDao.testModifyRestaurant();
}
catch(Exception e){
System.out.println(e);
e.printStackTrace();
}
}
It looks like i need to create the tables before running this as i am getting the below Excep..
[TopLink Config]: 2006.10.18 03:56:46.938–ServerSession(19533676)–Thread(Thread[main,5,main])–The source foreign key column name for the many to many mapping [private java.util.Set blog.jpa.domain.Restaurant.entrees] is being defaulted to: Restaurant_ID.
[TopLink Config]: 2006.10.18 03:56:46.938–ServerSession(19533676)–Thread(Thread[main,5,main])–The target primary key column name for the many to many mapping [private java.util.Set blog.jpa.domain.Restaurant.entrees] is being defaulted to: ID.
org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [insert into address (id, street_number, street_name) values (1, 10, 'Main Street')]; nested exception is java.sql.SQLException: ORA-00942: table or view does not exist
org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [insert into address (id, street_number, street_name) values (1, 10, 'Main Street')]; nested exception is java.sql.SQLException: ORA-00942: table or view does not exist
Caused by: java.sql.SQLException: ORA-00942: table or view does not exist
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:111)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:330)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:287)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:742)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:206)
at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:945)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1159)
at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1678)
at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1644)
at org.springframework.jdbc.core.JdbcTemplate$1ExecuteStatementCallback.doInStatement(JdbcTemplate.java:336)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:310)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:343)
at blog.jpa.dao.JpaRestaurantDaoTests.onSetUpInTransaction(JpaRestaurantDaoTests.java:40)
at blog.jpa.dao.TestDao.main(TestDao.java:29)
BUILD SUCCESSFUL (total time: 2 seconds)
Sateesh
Jim Shingler says:
Added on October 24th, 2006 at 10:00 am -QuoteMark, This blog was VERY helpful.
I would like to set this up with Hibernate instead of Toplink. This has been a challenge. It is a lot easier to do with Toplink than Hibernate. Could you do a follow-up that shows how to do the same thing with Hibernate.
Thanks
Jim
lou says:
Added on January 10th, 2007 at 12:02 pm -Quote