Test-Driven Development Problem
I'm newbie to Java EE 6 and i'm trying to develop very simple JAX-RS application. RESTfull web service working fine. However when I ran my test application, I got the following. What have I done wrong? Or am i forget any configuration? Of course i'm create a JNDI and i'm using Netbeans 6.8 IDE. In finally, thank you for any advise.
My Entity:
@Entity
@Table(name = "BOOK")
@NamedQueries({
@NamedQuery(name = "Book.findAll", query = "SELECT b FROM Book b"),
@NamedQuery(name = "Book.findById", query = "SELECT b FROM Book b WHERE b.id = :id"),
@NamedQuery(name = "Book.findByTitle", query = "SELECT b FROM Book b WHERE b.title = :title"),
@NamedQuery(name = "Book.findByDescription", query = "SELECT b FROM Book b WHERE b.description = :description"),
@NamedQuery(name = "Book.findByPrice", query = "SELECT b FROM Book b WHERE b.price = :price"),
@NamedQuery(name = "Book.findByNumberofpage", query = "SELECT b FROM Book b WHERE b.numberofpage = :numberofpage")})
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "ID")
private Integer id;
@Basic(optional = false)
@Column(name = "TITLE")
private String title;
@Basic(optional = false)
@Column(name = "DESCRIPTION")
private String description;
@Basic(optional = false)
@Column(name = "PRICE")
private double price;
@Basic(optional = false)
@Column(name = "NUMBEROFPAGE")
private int numberofpage;
public Book()
{
}
public Book(Integer id)
{
this.id = id;
}
public Book(Integer id, String title, String description, double price, int numberofpage)
{
this.id = id;
this.title = title;
this.description = description;
this.price = price;
this.numberofpage = numberofpage;
}
public Integer getId()
{
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getNumberofpage() {
return numberofpage;
}
public void setNumberofpage(int numberofpage) {
this.numberofpage = numberofpage;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Book)) {
return false;
}
Book other = (Book) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "com.entity.Book[id=" + id + "]";
}
}
My Junit test class:
public class BookTest
{
private static EntityManager em;
private static EntityManagerFactory emf;
public BookTest()
{
}
@BeforeClass
public static void setUpClass() throws Exception
{
emf = Persistence.createEntityManagerFactory("E01R01PU");
em = emf.createEntityManager();
}
@AfterClass
public static void tearDownClass() throws Exception
{
em.close();
emf.close();
}
@Test
public void createBook()
{
Book book = new Book();
book.setId(1);
book.setDescription("Mastering the Behavior Driven Development with Ruby on Rails");
book.setTitle("Mastering the BDD");
book.setPrice(25.9f);
book.setNumberofpage(1029);
em.persist(book);
assertNotNull("ID should not be null", book.getId());
}
}
My persistence.xml
<persistence>
<persistence-unit name="E01R01PU" transaction-type="JTA">
<jta-data-source>BookstoreJNDI</jta-data-source>
<properties />
</persistence-unit>
</persistence>
And exception is:
May 7, 2009 11:10:37 AM org.hibernate.validator.util.Version
INFO: Hibernate Validator bean-validator-3.0-JBoss-4.0.2
May 7, 2009 11:10:37 AM org.hibernate.validator.engine.resolver.DefaultTraversableResolver detectJPA
INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver.
[EL Info]: 2009-05-07 11:10:37.531--ServerSession(13671123)--EclipseLink, version: Eclipse Persistence Services - 2.0.0.v20091127-r5931
May 7, 2009 11:10:40 AM com.sun.enterprise.transaction.JavaEETransactionManagerSimplified initDelegates
INFO: Using com.sun.enterprise.transaction.jts.JavaEETransactionManagerJTSDelegate as the delegate
May 7, 2009 11:10:43 AM com.sun.enterprise.connectors.ActiveRAFactory createActiveResourceAdapter
SEVERE: rardeployment.class_not_found
May 7, 2009 11:10:43 AM com.sun.enterprise.connectors.ActiveRAFactory createActiveResourceAdapter
SEVERE:
com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Error in creating active RAR
at com.sun.enterprise.connectors.ActiveRAFactory.createActiveResourceAdapter(ActiveRAFactory.java:104)
at com.sun.enterprise.connectors.service.ResourceAdapterAdminServiceImpl.createActiveResourceAdapter(ResourceAdapterAdminServiceImpl.java:216)
at com.sun.enterprise.connectors.ConnectorRuntime.createActiveResourceAdapter(ConnectorRuntime.java:352)
at com.sun.enterprise.resource.naming.ConnectorObjectFactory.getObjectInstance(ConnectorObjectFactory.java:106)
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)
at com.sun.enterprise.naming.impl.SerialContext.getObjectInstance(SerialContext.java:472)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:437)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:569)
at javax.naming.InitialContext.lookup(InitialContext.java:396)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:110)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:94)
at org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:162)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:584)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:228)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:368)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:151)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:207)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:195)
at com.entity.BookTest.setUpClass(BookTest.java:31)
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:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at junit.framework.JUnit4TestAdapter.run(JUnit4TestAdapter.java:39)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:515)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:1031)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:888)
Caused by: java.lang.ClassNotFoundException: com.sun.gjc.spi.ResourceAdapter
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at com.sun.enterprise.connectors.ActiveRAFactory.createActiveResourceAdapter(ActiveRAFactory.java:96)
... 32 more
[EL Severe]: 2009-05-07 11:10:43.937--ServerSession(13671123)--Local Exception Stack:
Exception [EclipseLink-7060] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Cannot acquire data source [BookstoreJNDI].
Internal Exception: javax.naming.NamingException: Lookup failed for 'BookstoreJNDI' in SerialContext ,orb'sInitialHost=localhost,orb'sInitialPort=3700 [Root exception is javax.naming.NamingException: Failed to look up ConnectorDescriptor from JNDI [Root exception is com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Error in creating active RAR]]
at org.eclipse.persistence.exceptions.ValidationException.cannotAcquireDataSource(ValidationException.java:451)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:116)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:94)
at org.eclipse.persistence.sessions.DatasourceLogin.connectToDatasource(DatasourceLogin.java:162)
at org.eclipse.persistence.internal.sessions.DatabaseSessionImpl.loginAndDetectDatasource(DatabaseSessionImpl.java:584)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login(EntityManagerFactoryProvider.java:228)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:368)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.getServerSession(EntityManagerFactoryImpl.java:151)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:207)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:195)
at com.entity.BookTest.setUpClass(BookTest.java:31)
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:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
at org.junit.internal.runner开发者_如何学Pythons.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at junit.framework.JUnit4TestAdapter.run(JUnit4TestAdapter.java:39)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.run(JUnitTestRunner.java:515)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.launch(JUnitTestRunner.java:1031)
at org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.main(JUnitTestRunner.java:888)
Caused by: javax.naming.NamingException: Lookup failed for 'BookstoreJNDI' in SerialContext ,orb'sInitialHost=localhost,orb'sInitialPort=3700 [Root exception is javax.naming.NamingException: Failed to look up ConnectorDescriptor from JNDI [Root exception is com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Error in creating active RAR]]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:569)
at javax.naming.InitialContext.lookup(InitialContext.java:396)
at org.eclipse.persistence.sessions.JNDIConnector.connect(JNDIConnector.java:110)
... 23 more
Caused by: javax.naming.NamingException: Failed to look up ConnectorDescriptor from JNDI [Root exception is com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Error in creating active RAR]
at com.sun.enterprise.resource.naming.ConnectorObjectFactory.getObjectInstance(ConnectorObjectFactory.java:109)
at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)
at com.sun.enterprise.naming.impl.SerialContext.getObjectInstance(SerialContext.java:472)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:437)
... 26 more
Caused by: com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Error in creating active RAR
at com.sun.enterprise.connectors.ActiveRAFactory.createActiveResourceAdapter(ActiveRAFactory.java:104)
at com.sun.enterprise.connectors.service.ResourceAdapterAdminServiceImpl.createActiveResourceAdapter(ResourceAdapterAdminServiceImpl.java:216)
at com.sun.enterprise.connectors.ConnectorRuntime.createActiveResourceAdapter(ConnectorRuntime.java:352)
at com.sun.enterprise.resource.naming.ConnectorObjectFactory.getObjectInstance(ConnectorObjectFactory.java:106)
... 29 more
Caused by: java.lang.ClassNotFoundException: com.sun.gjc.spi.ResourceAdapter
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at com.sun.enterprise.connectors.ActiveRAFactory.createActiveResourceAdapter(ActiveRAFactory.java:96)
... 32 more
Exception Description: Cannot acquire data source [BookstoreJNDI].
Internal Exception: javax.naming.NamingException: Lookup failed for 'BookstoreJNDI' in SerialContext ,orb'sInitialHost=localhost,orb'sInitialPort=3700 [Root exception is javax.naming.NamingException: Failed to look up ConnectorDescriptor from JNDI [Root exception is com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Error in creating active RAR]])
First, you are missing some JARs on your classpath and my suggestion is to add $GF_HOME/modules/gf-client.jar
(don't copy the JAR to your project, point directly on it).
Second, your test won't pass in it current state, it's missing some parts:
persist
needs to be called inside a transaction- you need to
flush
the changes to get an ID assigned.
Here is a improved version that will run each test method with its own EntityManager
and inside a transaction (that is rolled back at the end of the test method):
public class BookTest {
private static EntityManager em;
private static EntityManagerFactory emf;
@BeforeClass
public static void createEntityManagerFactory() {
emf = Persistence.createEntityManagerFactory("E01R01PU");
}
@AfterClass
public static void closeEntityManagerFactory() throws Exception {
emf.close();
}
@Before
public void beginTransaction() {
em = emf.createEntityManager();
em.getTransaction().begin();
}
@After
public void rollbackTransaction() {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em.isOpen()) {
em.close();
}
}
@Test
public void createBook() {
Book book = new Book();
book.setId(1);
book.setDescription("Mastering the Behavior Driven Development with " +
"Ruby on Rails");
book.setTitle("Mastering the BDD");
book.setPrice(25.9f);
book.setNumberofpage(1029);
em.persist(book);
em.flush(); // sync the in-memory changes with the db
// now this will pass
assertNotNull("ID should not be null", book.getId());
}
}
Bonus: this test will pass :)
Note that people usually prefer being able to run tests without having to start a container i.e. without relying on JNDI. Here is a persistence.xml
showing how to configure EclipseLink to connect to a Derby database running in server mode that you could use in a testing context:
<?xml version="1.0" encoding="UTF-8"?>
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="TestPu" transaction-type="RESOURCE_LOCAL">
<class>com.acme.Foo</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<!--property name="eclipselink.target-database" value="DERBY"/-->
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527//path/to/derbyDBs/TestDB;create=true"/>
<property name="javax.persistence.jdbc.user" value="APP"/>
<property name="javax.persistence.jdbc.password" value="APP"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.weaving" value="static" />
<property name="eclipselink.debug" value="ALL"/>
<property name="eclipselink.logging.level.sql" value="FINEST" />
<property name="eclipselink.logging.level" value="FINEST" />
<property name="eclipselink.logging.level.cache" value="FINEST" />
</properties>
</persistence-unit>
</persistence>
You have first a "Caused by: java.lang.ClassNotFoundException: com.sun.gjc.spi.ResourceAdapter " error in your output. This should be the first thing you should fix (something missing). On the other hand i see so many annotations in you Book class, which are in the majority not needed. In particular those for the column names. BTW: Why are you annotating the attributes instead of the getters? You have overwritten equals() but not really implemented it (only for Id field, what about the other fields?). And if you need to overwrite equals you have to overwrite hashCode as well. Let the IDE create them it's much more simpler.
精彩评论