Reputation: 9584
I am trying to use JPA for persistence in a Java Web Application for a RESTful WebService. The program runs through the EntityManager, persisting an Entity class, being surrounded bz a transaction (begin and commit). The transaction makes troubles though. When I check the MySQL database the necessary tables are created, but no entries inside of them. How can that be? What's wrong in the code?
My service class:
@Stateless
public class ReportService {
@PersistenceContext(unitName = "AbcPU") // default type is PersistenceContextType.TRANSACTION
EntityManager em;
public void saveDog() {
System.out.println("BBBBB Start ReportService.saveDog();");
Doggy doggy = new Doggy();
doggy.setDogName("Wuffi");
try {
System.out.println("BBBBB Persist Success ReportService.saveDog();");
em.getTransaction().begin();
em.persist(doggy);
em.flush();
em.getTransaction().commit();
} catch (Exception ex) {
System.out.println("BBBBB Persist Fail ReportService.saveDog();");
System.err.println("Error with em.persist(doggy): " + ex.getMessage());
}
System.out.println("BBBBB Stop ReportService.saveDog();");
}
}
My resource class:
@Path("report")
@Produces(MediaType.APPLICATION_JSON)
public class ReportResource {
@EJB
private ReportService rs;
@GET
public Response findReports() {
final List<Report> reports = rs.findAllReports();
System.out.println("AAAAA Start rs.saveDog();");
rs.saveDog();
System.out.println("AAAAA Stop rs.saveDog();");
return Response.ok(new GenericEntity<List<Report>>(reports) {})
.build();
}
}
My entity class:
@Entity
public class Doggy implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
private String dogName;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDogName() {
return dogName;
}
public void setDogName(String dogName) {
this.dogName = dogName;
}
@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 Doggy)) {
return false;
}
Doggy other = (Doggy) 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.glasses.pandora.domain.Doggy[ id=" + id + " ]";
}
}
My persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="AbcPU" transaction-type="JTA">
<jta-data-source>java:/jdbc/abc</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
</properties>
</persistence-unit>
</persistence>
My Maven dependencies in the pom.xml:
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.1.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>hibernate-jpamodelgen-4.3.1.Final</artifactId>
<version>SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
My console output after having run:
01:58:54,158 INFO [stdout] (default task-23) AAAAA Start rs.saveDog();
01:58:54,160 INFO [stdout] (default task-23) BBBBB Start ReportService.saveDog();
01:58:54,160 INFO [stdout] (default task-23) BBBBB Persist Success ReportService.saveDog();
01:58:54,160 INFO [stdout] (default task-23) BBBBB Persist Fail ReportService.saveDog();
01:58:54,161 ERROR [stderr] (default task-23) Error with em.persist(doggy): A JTA EntityManager cannot use getTransaction()
01:58:54,161 INFO [stdout] (default task-23) BBBBB Stop ReportService.saveDog();
01:58:54,162 INFO [stdout] (default task-23) AAAAA Stop rs.saveDog();
The mysql show tables:
mysql> show tables;
+--------------------+
| Tables_in_abc |
+--------------------+
| Doggy |
| hibernate_sequence |
+--------------------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM Doggy;
Empty set (0.00 sec)
mysql>
Upvotes: 1
Views: 5408
Reputation: 18040
Look at the error - Error with em.persist(doggy): A JTA EntityManager cannot use getTransaction()
. EJB is handling transactions automatically - remove the following from your ReportService em.getTransaction().begin()
, em.flush();
and em.getTransaction().commit();
Your method should be like this:
public void saveDog() {
System.out.println("BBBBB Start ReportService.saveDog();");
Doggy doggy = new Doggy();
doggy.setDogName("Wuffi");
try {
System.out.println("BBBBB Persist Success ReportService.saveDog();");
em.persist(doggy);
} catch (Exception ex) {
System.out.println("BBBBB Persist Fail ReportService.saveDog();");
System.err.println("Error with em.persist(doggy): " + ex.getMessage());
}
System.out.println("BBBBB Stop ReportService.saveDog();");
}
Upvotes: 1
Reputation: 21155
There are a few problems. The first, mentioned by hwellmann, is that you have not specified a datasource. JTA requires a so that connections associated to the JTA transaction are used.
The second is that you don't seem to have wrapped the saveDog method in a transaction. The persist call will only register the Entity with the context; it only gets inserted in the database when the associated transaction is committed, or EntityManager.flush() is called. If you call em.flush in your save method, this will validate that your EntityManager is correctly associated to a transaction and that the insert is successful.
Upvotes: 1
Reputation: 12875
Check the server logs to see if your application is indeed using a MySQL datasource or the embedded default H2 datasource.
Your persistence.xml
does not contain a <jta-data-source>
, so I'd say the default datasource is being used.
See the Wiki article about Datasource Configuration.
Upvotes: 1
Reputation: 889
I am pretty sure you need to look up your persistence context and assign the entitymanager from that.
@Dependent
@Stateful
public class ReportService {
@PersistenceContext(name = "persistence/AbcPU", unitName = "AbcPU")
public abstract EntityManager getEntityManager() {
EntityManager em = null;
try {
Context envCtx = InitialContext.doLookup("java:comp/env");
em = (EntityManager) envCtx.lookup("persistence/AbcPU");
} catch (NamingException ne) {
//Handle Exception
}
return em;
}
public void saveDog() {
System.out.println("BBBBB Start ReportService.saveDog();");
Doggy doggy = new Doggy();
doggy.setDogName("Wuffi");
try {
System.out.println("BBBBB Persist Success ReportService.saveDog();");
getEntityManager().persist(doggy);
} catch (Exception ex) {
System.out.println("BBBBB Persist Fail ReportService.saveDog();");
System.err.println("Error with em.persist(doggy): " + ex.getMessage());
}
System.out.println("BBBBB Stop ReportService.saveDog();");
}
}
Upvotes: -2