JSF/JPA problem
Hi all, I'm playing around with JSF and JPA on a personal project and
I've got a problem I haven't been able to figure out. Basically no
matter what I do in a certain bit of code, I always get a JPA error that
there is no transaction available for the current thread.
This is darn weird because I use almost the exact same pattern elsewhere
and it works fine. Also, everything I've read about Stateless beans
says that a transaction context should be created by default, so I can't
imagine why this one fails.
(I just thought of something just now: this is the first time I've tried
to persist this particular entity, the Post class. Could possibly be
some misconfiguration on the entity itself?)
I don't think it matters but here's where I call the method in question:
<h:commandButton
value="Create Post"
action="#{postBean.createNewPost()}" />
That calls a simple manged bean, here with getters/setters removed...
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
/**
*
* @author Brenden
*/
@RequestScoped
@ManagedBean
public class PostBean
{
@PersistenceUnit
EntityManagerFactory emf;
@ManagedProperty( value = "#{postService}" )
PostService postService;
....
public String createNewPost() { // this method is called by the JSF
.... error checking removed...
Post post = new Post();
.... build the DTO entity here...
postService.createPost( post ); // dies in this method
return "success";
}
}
The PostService is pretty simple too:
import javax.ejb.Stateless;
import javax.faces.bean.ManagedBean;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
/**
*
* @author Brenden
*/
@ManagedBean
@Stateless
public class PostService
{
@PersistenceUnit
EntityManagerFactory emf;
public void createPost( Post post )
{
EntityManager em = emf.createEntityManager();
em.persist( post );
em.flush(); // this is the line that generates the exception
}
}
Everything I've read says that the @Stateless tag should create a
transaction context, and it seems to in other parts of the web app.
Here I can only produce exceptions despite fiddling around with the tags
and double checking.
Here's a partial stack trace...
WARNING: #{postBean.createNewPost()}:
javax.persistence.TransactionRequiredException:
Exception Description: No externally managed transaction is currently
active for this thread
javax.faces.FacesException: #{postBean.createNewPost()}:
javax.persistence.TransactionRequiredException:
Exception Description: No externally managed transaction is currently
active for this thread
at
com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
at
javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
at
com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
.....
Caused by: javax.faces.el.EvaluationException:
javax.persistence.TransactionRequiredException:
Exception Description: No externally managed transaction is currently
active for this thread
at
javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
at
com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
... 32 more
Caused by: javax.persistence.TransactionRequiredException:
Exception Description: No externally managed transaction is currently
active for this thread
at
org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.throwCheckTransactionFailedException(JTATransactionWrapper.java:86)
at
org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.checkForTransaction(JTATransactionWrapper.java:46)
at
org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:1776)
at
org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:780)
at
com.techdarwinia.website.services.PostService.createPost(PostService.java:32)
at com.techdarwinia.website.beans.PostBean.createNewPost(PostBean.java:167)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
Line 32 is the one in PostService that I marked, the em.flush() statement.
I'm going to hit the books/docs again to see if I can figure this out.
Any one else have any insights while I'm doing that?