I am trying to build a simple REST service, using JAX-RS, that will perform the standard CRUD operations on a database table. I am able to successfully query for records, but I cannot insert new ones. I do not get any errors and when I step through the code in debug mode everything looks good. I am using a transactional CDI bean running in a Glassfish 4.1 container.
It feels like it's just never committing the transaction. I'm pretty new to Java EE, but my understanding is that since the bean is transactional the container should handle the commit for me. Anyone know why it is not?
@Path("/recipes")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class RecipeResource {
@Inject
RecipesService recipesService;
@GET
public List<Recipe> getRecipes() {
return recipesService.getAllRecipes();
}
@POST
public void addRecipse(Recipe recipe) {
recipesService.addRecipe(recipe);
}
}
public class RecipesService {
@PersistenceContext(unitName="PANTRYDB", type=PersistenceContextType.TRANSACTION)
EntityManager em;
public RecipesService () {
}
public List<Recipe> getAllRecipes () {
List<Recipe> recipes = null;
try {
TypedQuery<Recipe> typedQuery = em.createQuery("select r from Recipe r", Recipe.class);
recipes = typedQuery.getResultList();
} catch (Exception e) {
System.out.println(e);
}
return recipes;
}
@Transactional
//This is the method that seems to not commit it's transaction
//The Recipe object is populated correctly, and the persist() doesn't
//throw any errors
public void addRecipe(Recipe recipe) {
try {
em.persist(recipe);
} catch (Exception e) {
System.out.println(e);
}
}
}
@Entity
@Table(name="RECIPES", schema="COOKBOOK")
public class Recipe {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
@Column
private String name;
@Column(name="CREATED_DATE")
private Calendar createdDate;
@Column(name="LAST_MADE_DATE")
private Calendar lastMadeDate;
@Column
private String description;
@Column
private String notes;
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Calendar getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Calendar createdDate) {
this.createdDate = createdDate;
}
public Calendar getLastMadeDate() {
return lastMadeDate;
}
public void setLastMadeDate(Calendar lastMadeDate) {
this.lastMadeDate = lastMadeDate;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
@Override
public String toString() {
return name;
}
}
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="PANTRYDB" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>com.domain.Recipe</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:derby:/Users/development/eclipse/ws_playground/databases/pantry_db/PANTRYDB" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
<property name="javax.persistence.jdbc.user" value=""/>
<property name="javax.persistence.jdbc.password" value=""/>
</properties>
</persistence-unit>
</persistence>
I tried your application on a weblogic 12.2.1 and it successfully inserted in database and i do not have any problem with transaction.
Here is my code.
RecipeResource
class (I modified the @Path
to call it via web browser and also instanciated the Recipe
manually):
@Path("/recipes")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class RecipeResource {
@Inject
RecipesService recipesService;
@GET
@Path("get")
public List<Recipe> getRecipes() {
return recipesService.getAllRecipes();
}
@GET
@Path("add")
public String addRecipse() {
Recipe recipe = new Recipe();
recipe.setDescription("desc");
recipesService.addRecipe(recipe);
return "OK";
}
}
The Recipe
class is same as yours except that i commented the schema :
@Entity
@Table(name="RECIPES") //, schema="COOKBOOK")
public class Recipe {
}
My persistence.xml
(I'm using in-memory database):
<?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="PANTRYDB" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/__default</jta-data-source>
<class>org.jvi.webservice.transactional.db.Recipe</class>
<properties>
<!--<property name="eclipselink.ddl-generation" value="create-tables"/>-->
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.level.sql" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.logging.logger" value="DefaultLogger"/>
<property name="eclipselink.cache.shared.default" value="false"/>
</properties>
</persistence-unit>
So your problem might come from the Application Server.
Did you try to deploy your webapp on another server?