# MAVEN + Spring + JPA + Hibernate + JUnit4



## nachtwandler86 (11. Apr 2014)

Hallo zusammen 

Wir bauen im moment eine webapp unter Eclipse EE mit Maven und Spring. Als Datenbank verwenden wir H2, die mit JPA und Hibernate über JDBC angebunden ist.

*Unser größtes Problem ist grade, dass unsere JUnit Tests nicht ausgeführt werden.*

Stacktrace JUnit- Test:

```
java.lang.IllegalArgumentException: Unknown entity: de.sep.innovativeoperation.taskscheduler.model.IssueTemplate
	at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:856)
	at de.sep.innovativeoperation.taskscheduler.test.persistence.issueentity.IssueEntityPersistenceTest.TestWriteAndReading(IssueEntityPersistenceTest.java:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	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.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
```


Wir bekommen immer Fehler:

Tests in error: 
  TestWriteAndReading(de.sep.innovativeoperation.taskscheduler.test.persistence.issueentity.IssueEntityPersistenceTest): [PersistenceUnit: Test] Unable to build EntityManagerFactory

Die Test-Klasse:

```
package de.sep.innovativeoperation.taskscheduler.test.persistence.issueentity;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.junit.Assert;
import org.junit.Test;

import de.sep.innovativeoperation.taskscheduler.model.IssueTemplate;
import de.sep.innovativeoperation.taskscheduler.model.IssueType;


/**
 * PersistenceTests for IssueEntity
 * @author Stefan
 * 
 */
public class IssueEntityPersistenceTest  {
		
	@Test	
	public void TestWriteAndReading(){		
		
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("Test");
		EntityManager em = emf.createEntityManager();

		IssueTemplate issueTemplate = new IssueTemplate("TEST","TEST",IssueType.BUG);
//		IssueEntity issueEntity = new IssueEntity();
		
		
		//write Object
	    em.getTransaction().begin();
	    em.persist(issueTemplate);
	    em.getTransaction().commit();
	    
	    //get Object
	    IssueTemplate issueTemplate2 = em.find(IssueTemplate.class, issueTemplate.getId());
	    
	    Assert.assertTrue(issueTemplate.getIssueName().equals(issueTemplate2.getIssueName()));
	    em.close();
	    emf.close();	    
	}	
}
```

unsere POM:
[XML]<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>de.sep.innovativeoperation</groupId>
	<artifactId>TaskScheduler</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>TaskScheduler Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<properties>
		<java-version>1.7</java-version>
		<jackson.version>1.9.10</jackson.version>
	</properties>

	<dependencies>

		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.2.8.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>3.2.8.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>3.2.8.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>3.2.8.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>3.2.8.RELEASE</version>
		</dependency>


		<!-- Jackson JSON Mapper -->
		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.9.10</version>
		</dependency>


	<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.8.1</version>
      <scope>test</scope>
    </dependency>

		<!-- Database Driver -->
		<!-- H2 -->
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<version>1.3.175</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate.javax.persistence</groupId>
			<artifactId>hibernate-jpa-2.0-api</artifactId>
			<version>1.0.1.Final</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>4.0.1.Final</version>
		</dependency>



		<dependency>
			<groupId>javax.validation</groupId>
			<artifactId>validation-api</artifactId>
			<version>1.1.0.Final</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>5.1.0.Final</version>
		</dependency>

	</dependencies>
	<build>
		<finalName>TaskScheduler</finalName>
	</build>
</project>
[/XML]

unsere persistance.xml:

[XML]<?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_1_0.xsd"
	version="1.0">

	<persistence-unit name="Test">

		<provider>org.hibernate.ejb.HibernatePersistence</provider>



		<properties>

			<property name="hibernate.connection.driver_class" value="org.h2.Driver" />
			<property name="hibernate.connection.url" value="jdbc:h2:tcp://localhost//sep/database/databases/database1;INIT=CREATE SCHEMA IF NOT EXISTS TASKSCHEDULER" />
			<property name="hibernate.connection.username" value="h2" />
			<property name="hibernate.connection.password" value="h2" />
			<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
			<property name="hibernate.default_schema" value="TASKSCHEDULER" />
			<property name="hibernate.hbm2ddl.auto" value="update" />
			<property name="hbm2ddl.auto" value="update"/>

		</properties>
	</persistence-unit>


</persistence>
[/XML]

Ich hoffe jemand weiß um diesen Fehler bescheid... ist wahrscheinlich nur ne Kleinigkeit...


----------



## Stefan Isele (6. Mai 2014)

Im Stacktrace steht Unknown Entity....
d.h. die Klasse IssueTemplate ist nicht als Entity deklariert worden.
Die Klasse braucht eine Annotation @Entity und muß dann aber noch dem EntityManager bekannt gemacht werden, daran könnte es liegen.


Mit dem Open-Source Framework appdriver kann man solche Web-Anwendungen mit JPA, Spring REST, Maven, JQuery,Ajax, Bootstrap in wenigen Minuten aufsetzen und dann schrittweise erweitern.
Selbst wenn das für Ihre Zwecke nicht genau das Richtige ist, kommen Sie damit aber ganz schnell zu einer laufenden Anwendung und können dann 'am Lebenden Objekt' forschen.

Die Website des Projektes ist appdriver.com
Eine Live-Demo läuft unter demo.appdriver.com
Die REST-API finden Sie unter http://appdriver.prefabware.cloudbees.net/api/

Viel Erfolg !


----------



## saw (16. Mai 2014)

Hi, ich habe ein ganz aehnliches Problem mit Maven und Junit. Auch ich bekomme bei meinem Test (in diesem Fall ein Test, der einfach Testdaten in die Datenbank einfuegt) folgende Meldung:


```
mathias@id83:~/src/trainingbroker$ mvn -Dtest=InsertTestData test
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building tbrest 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.3:resources (default-resources) @ tbrest ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ tbrest ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-resources-plugin:2.3:testResources (default-testResources) @ tbrest ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] 
[INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ tbrest ---
[INFO] Compiling 2 source files to /home/mathias/src/trainingbroker/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ tbrest ---
[INFO] Surefire report directory: /home/mathias/src/trainingbroker/target/surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running net.vxpertise.tb.data.jpa.InsertTestData
May 16, 2014 11:36:39 AM org.hibernate.annotations.common.Version <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.1.Final}
May 16, 2014 11:36:39 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.0.1.Final}
May 16, 2014 11:36:39 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
May 16, 2014 11:36:39 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
May 16, 2014 11:36:39 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000402: Using Hibernate built-in connection pool (not for production use!)
May 16, 2014 11:36:39 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20
May 16, 2014 11:36:39 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000006: Autocommit mode: true
May 16, 2014 11:36:39 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/trainingbroker]
May 16, 2014 11:36:39 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000046: Connection properties: {user=trainingbroker, password=****, autocommit=true, release_mode=auto}
May 16, 2014 11:36:39 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
May 16, 2014 11:36:39 AM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
May 16, 2014 11:36:39 AM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
May 16, 2014 11:36:40 AM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 5.1.1.Final
May 16, 2014 11:36:40 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
May 16, 2014 11:36:40 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000102: Fetching database metadata
May 16, 2014 11:36:40 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000396: Updating schema
May 16, 2014 11:36:40 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000232: Schema update complete
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.59 sec <<< FAILURE!

Results :

Tests in error: 
  insert(net.vxpertise.tb.data.jpa.InsertTestData): Unknown entity: net.vxpertise.tb.data.model.tag.Tag

Tests run: 1, Failures: 0, Errors: 1, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.027s
[INFO] Finished at: Fri May 16 11:36:40 CEST 2014
[INFO] Final Memory: 19M/169M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.10:test (default-test) on project tbrest: There are test failures.
[ERROR] 
[ERROR] Please refer to /home/mathias/src/trainingbroker/target/surefire-reports for the individual test results.
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
mathias@id83:~/src/trainingbroker$
```

Im Target directory sieht es so aus:


```
mathias@id83:~/src/trainingbroker/target$ ls -l
total 28
drwxrwxr-x 4 mathias mathias 4096 Mai 16 11:35 classes
drwxrwxr-x 3 mathias mathias 4096 Mai 16 11:35 generated-sources
drwxrwxr-x 3 mathias mathias 4096 Mai 16 11:35 generated-test-sources
drwxrwxr-x 3 mathias mathias 4096 Mai 16 11:36 m2e-wtp
drwxrwxr-x 2 mathias mathias 4096 Mai 16 11:36 surefire
drwxrwxr-x 2 mathias mathias 4096 Mai 16 11:36 surefire-reports
drwxrwxr-x 4 mathias mathias 4096 Mai 16 11:35 test-classes
mathias@id83:~/src/trainingbroker/target$ find test-classes/
test-classes/
test-classes/META-INF
test-classes/META-INF/persistence.xml
test-classes/net
test-classes/net/vxpertise
test-classes/net/vxpertise/tb
test-classes/net/vxpertise/tb/data
test-classes/net/vxpertise/tb/data/jpa
test-classes/net/vxpertise/tb/data/jpa/InsertTestData.class
test-classes/net/vxpertise/tb/data/LinkFactoryTest.class
test-classes/net/vxpertise/tb/data/rest
test-classes/net/vxpertise/tb/data/rest/TrainingControllerTest.class
test-classes/net/vxpertise/tb/data/rest/TagControllerTest.class
mathias@id83:~/src/trainingbroker/target$ ls -l classes/
META-INF/ net/      
mathias@id83:~/src/trainingbroker/target$ ls -l classes/
META-INF/ net/      
mathias@id83:~/src/trainingbroker/target$ ls -l classes/net/vxpertise/tb/data/model/tag/
total 8
-rw-rw-r-- 1 mathias mathias 2655 Mai 16 11:35 Tag.class
-rw-rw-r-- 1 mathias mathias  326 Mai 16 11:35 Taggable.class
mathias@id83:~/src/trainingbroker/target$
```

Also mein Tip ist, dass er beim compilieren der Tests die Files aus target/classes im Classpath hat, beim Ausfuehren dann aber nicht mehr ... Wie kann das sein?


----------



## Stefan Isele (16. Mai 2014)

Die Entität muß nicht nur im Klassenpfad liegen, sondern auch der PeristenceUnit 'bekannt' sein.
Dazu muß Sie in der peristence.xml deklariert sein.
z.B. wie hier :Persistence Units (The Java EE 6 Tutorial)

Sprinng nutzt da einen anderen Mechanismus, da muß man angeben in welchen Packages nach Entitäten gesucht werden soll.

Das sollten Sie mal prüfen....


----------



## saw (16. Mai 2014)

Hmm, ich nutze fuer den Unit Test dieselbe persistence.xml, die auch in der das Hauptprojekt nutzt. Eine habe ich in 

*src/test/resources/META-INF/persistence.xml*

und die andere in

*src/main/resources/META-INF/persistence.xml*

Beide sehen identisch aus. Die Web Applikation kann ich starten und JPA auch nutzen ohne darin explizit die Klassen angegeben zu haben. Ich dachte er sucht sich das selbst raus und scheinbar tut er das ja auch.

Gruesse
saw


----------



## Stefan Isele (18. Mai 2014)

Die JPS Spec sagt relativ deutlich, dass die Entitätsklassen explizit angegeben werden müßen, und ich habe öfter von Hibernate die Exception "Unknown entity .." gesehen, wenn die Entitäten eben nicht aufgeführt waren.

Aus der Spec :
...
A list of all named managed persistence classes must be specified in Java SE environments to insure portability

Die Entitätsklasse wird im Test auch gefunden, sonst käme eine andere Meldung wie ClassNotFound.

Warum haben sie zweimal die identische persistence.xml im Projekt ?
Beide liegen im Test im Klassenpfad, wenn sie identisch sind würde eine reichen.

-Ich würde folgendes versuchen :
- die persistence.xml aus test/resources entfernen
- die Entitätsklasse in der persistence.xml auflisten

und nochmal laufen lassen...


----------

