JSF/JPA problem

M

markspace

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?
 
A

Arved Sandstrom

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.
[ SNIP ]

You're using application-managed entity managers because of your use of
an EntityManagerFactory. You must therefore use EntityTransaction.

If you want container-managed then inject with @PersistenceContext, and
specify JTA in your persistence.xml (Note: with application-managed
you'd typically have RESOURCE_LOCAL).

AHS
 
A

Arved Sandstrom

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.
[ SNIP ]

You're using application-managed entity managers because of your use of
an EntityManagerFactory. You must therefore use EntityTransaction.

If you want container-managed then inject with @PersistenceContext, and
specify JTA in your persistence.xml (Note: with application-managed
you'd typically have RESOURCE_LOCAL).

AHS
I should elaborate: if you're in a JTA environment there is also the
option of using UserTransaction with your application-managed EMs (see
http://download.oracle.com/docs/cd/E19798-01/821-1841/bnbra/index.html)

This is not something that I have found myself doing personally: I
either use application-managed EMs with the EntityTransaction API (hence
RESOURCE_LOCAL), or container-managed EMs with container-managed JTA
transactions.

On a side note: if you're Java EE 6 (and judging by the
"postBean.createNewPost()" maybe you are) then you might want to use CDI
and the @Named and @Inject annotations rather than @ManagedBean and
@ManagedProperty. With a Java EE 6 server (like Glassfish 3) you'll have
the Weld reference implementation of CDI included most likely, and all
you have to do is set up a beans.xml file in your WEB-INF to kickstart it.

HTH,
AHS
 
M

markspace

Wow, are you kidding me? I have three books and I've read the spec and
don't recall seeing that piece of magic documentation. Could I trouble
you to point out where you found it?

(Yes, I'm using JEE 6 and JTA transactions.)

On a side note: if you're Java EE 6 (and judging by the
"postBean.createNewPost()" maybe you are) then you might want to use CDI
and the @Named and @Inject annotations rather than @ManagedBean and
@ManagedProperty. With a Java EE 6 server (like Glassfish 3) you'll have
the Weld reference implementation of CDI


Yes, I have CDI available. I haven't read up on CDI completely yet, and
it's a bit more involved than ManagedBean/ManagedProperty, so I'm
playing with those two while I come up to speed on CDI. It'll happen soon.
 
M

markspace

Hmm, ok not working still. I think I remember now switching from
PersistenceContext to PersistenceUnit because the former was making
errors on me too.

Here's the full persistence.xml file (it's short).

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
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">
<persistence-unit name="techDarwinia2PU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/techdarwinia</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>
</persistence>


Here's the error I'm getting now:

WARNING: #{postBean.createNewPost()}:
javax.persistence.TransactionRequiredException
javax.faces.FacesException: #{postBean.createNewPost()}:
javax.persistence.TransactionRequiredException
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.persistence.TransactionRequiredException
at
com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:163)
at
com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:145)
at
com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:263)
at
com.techdarwinia.website.services.PostService.createPost(PostService.java:27)
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)
at java.lang.reflect.Method.invoke(Method.java:601)


which now moves the error up to the em.persist( post ); line, one above
the previous error at the line em.flush();

Here's what I changed the PostService to:

import com.techdarwinia.website.dto.Post;
import javax.ejb.Stateless;
import javax.faces.bean.ManagedBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
*
* @author Brenden
*/
@ManagedBean
@Stateless
public class PostService
{

@PersistenceContext
EntityManager em;

public void createPost( Post post )
{
em.persist( post );
em.flush();
}
}

Anyone got ideas?
 
A

Arved Sandstrom

Wow, are you kidding me? I have three books and I've read the spec and
don't recall seeing that piece of magic documentation. Could I trouble
you to point out where you found it?

(Yes, I'm using JEE 6 and JTA transactions.)

Seeing that you're using JTA I'll modify my previous remarks some. :) I
was half-thinking you had RESOURCE_LOCAL, and couched my remarks to that
effect.

Referring to the EJB 3.0 Persistence spec, Section 5.3 (and 5.4)
indicates that "The EntityManagerFactory interface is used by the
application to create an application-managed entity manager". Sections
5.3.1 and 5.3.2 cover how the EntityManagerFactory is obtained, one of
which you are using (in fact the Java SE method works fine in Java EE as
well).

Backtracking to Section 5.2, it is noted that container-managed EMs are
obtained directly from JNDI lookup or dependency injection; the
application does _not_ directly use an EntityManagerFactory here, the
container does that on your behalf.

Section 5.1 is a good overview.

Section 5.5 specifies that container-managed EMs must be JTA;
application-managed may be RESOURCE_LOCAL (EntityTransaction interface)
or JTA.

Section 5.7 has the specifics on application-managed EMs and
transactions. Examples 5.7.1.1 and 5.7.1.2 demonstrate the use of
application-managed JTA entity managers: note that in 5.7.1.1 the EM was
created inside a container-managed JTA transaction, and in 5.7.1.2
outside so you have to use .joinTransaction in the latter. The other
examples are well worth perusing as well.

You could try leaving out the flush(), and simply close the EM at the
end of createPost(). This would track Example 5.7.1.1. Let's see if you
still get the TransactionRequiredException. That would then demonstrate
that there really is no active JTA transaction, and we could solve that.
flush() in and of itself ought not to be the problem here.

Since you expect to be set up for JTA, you could also dispense with the
use of application-managed, and use @PersistenceContext DI instead, a la
Example 5.6.4.1 - this is about as easy as it gets.

As I mentioned prior, I myself use either RESOURCE_LOCAL
application-managed EMs explicitly obtained via
EntityManagerFactory.createEntityManager, with the EntityTransactionAPI,
*or* I use container-managed JTA entity managers with
@PersistenceContext DI. I won't say that the combo you are using -
application-managed JTA EMs - is uncommon, but it is to me. :)

You have me interested; I will try this situation out on Glassfish.
Yes, I have CDI available. I haven't read up on CDI completely yet, and
it's a bit more involved than ManagedBean/ManagedProperty, so I'm
playing with those two while I come up to speed on CDI. It'll happen soon.

Cool, it's well worth it.

AHS
 
M

markspace

You could try leaving out the flush(), and simply close the EM at the
end of createPost(). This would track Example 5.7.1.1. Let's see if you
still get the TransactionRequiredException. That would then demonstrate
that there really is no active JTA transaction...
Since you expect to be set up for JTA, you could also dispense with the
use of application-managed, and use @PersistenceContext DI instead, a la
Example 5.6.4.1 - this is about as easy as it gets.


Just to reiterate the post I just added to this thread, I already
switched to PersistenceContext for DI, and the error has now moved from
the em.flush() to the em.persist( post ) on the line previous. So I
have to conclude that if I add an em.close(), I'll still now have the
error previous to the close(). I'll give it a try at some point.

You have me interested; I will try this situation out on Glassfish.


Thanks for playing around with this, it really has me stumped.
 
A

Arved Sandstrom

Just to reiterate the post I just added to this thread, I already
switched to PersistenceContext for DI, and the error has now moved from
the em.flush() to the em.persist( post ) on the line previous. So I
have to conclude that if I add an em.close(), I'll still now have the
error previous to the close(). I'll give it a try at some point.




Thanks for playing around with this, it really has me stumped.

I just now fired up a new EAR app in Eclipse Indigo running Glassfish
3.1; two projects, a WAR, and a EJB project with the JPA facet. I am
using PostgreSQL 9.0, and set up a datasourec against that in the
Glassfish admin console. The persistence.xml was extremely simple:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
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">
<persistence-unit name="StateMachinesServices
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider
<jta-data-source>jdbc/PostgreSQLPool</jta-data-source
<class>org.ahs.sm.model.State</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.ddl-generation" value="none"/>
<property name="eclipselink.target-database" value="PostgreSQL"/
</properties>
</persistence-unit>
</persistence>

The single test entity is set up as

@Entity
public class State implements Serializable {
private static final long serialVersionUID = 1L;

@Id
@SequenceGenerator(name = "STATE_ID_GEN",
sequenceName="STATE_ID_SEQ", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE,
generator = "STATE_ID_GEN")
private Integer id;
private String name;
private String status;

...
}

The session bean I set up as

@Stateless
@LocalBean
public class CreateState {

@PersistenceUnit
EntityManagerFactory emf;

public void createState() {
EntityManager em = emf.createEntityManager();
State state = new State();
state.setName("state1");
state.setStatus("OK");
em.persist(state);
em.close();
}
}

This is simply called from a JSF managed bean method hit through a
h:commandButton. So essentially your setup.

I just now noticed something, though, which might well explain the
problem. I have a genuine unvarnished EJB (my CreateState session bean).
You on the other hand have something that looks like a hybrid: both
javax.ejb.Stateless and javax.faces.bean.ManagedBean annotations on it.
I have no idea what this combo will do. :)

When I call my session bean from my JSF managed bean, I inject it with
@EJB. You're not doing that, so you have basically what looks like a
basic Java method call, and there's a good chance the annotations are
being ignored.

Side note: when I set this new project up tonight I started out with JDK
1.7. Bad move - VerifyErrors and what have you. I had to switch back to
JDK 1.6.

AHS
 
A

Arved Sandstrom

I just now fired up a new EAR app in Eclipse Indigo running Glassfish
3.1; two projects, a WAR, and a EJB project with the JPA facet. I am
using PostgreSQL 9.0, and set up a datasourec against that in the
Glassfish admin console. The persistence.xml was extremely simple:
[ SNIP ]

Err...I should have added, my setup works just fine. I see new data
being persisted. This being the application-managed JTA entity manager
scenario.

AHS
 
M

markspace

Err...I should have added, my setup works just fine. I see new data
being persisted. This being the application-managed JTA entity manager
scenario.


Thanks for that, it at least gives me a few things to try out.

If you want to test further, I'm basically using the NetBeans IDE for
this project. It has GlassFish and Derby built-in, so it uses those for
JEE projects. It even has a wizard for making the persistence.xml file,
which is what I used. I'd be curious if it's NetBeans that's setting
things up screwy, or if I missed a needed step.

Will try some of those ideas as soon as I can.
 
A

Arved Sandstrom

Thanks for that, it at least gives me a few things to try out.

If you want to test further, I'm basically using the NetBeans IDE for
this project. It has GlassFish and Derby built-in, so it uses those for
JEE projects. It even has a wizard for making the persistence.xml file,
which is what I used. I'd be curious if it's NetBeans that's setting
things up screwy, or if I missed a needed step.

Will try some of those ideas as soon as I can.
I may try NetBeans here, but I can't see that in this case that the IDE
of choice is the problem. Normally I would have used NB for this
experiment, since I have some development biases (mostly unfounded
quirks) that lead me to use NB + Glassfish, Eclipse + all other app
servers. It just so happened that I had set up Eclipse Indigo on an
Ubuntu box with Glassfish Tools just to try it out, and had a single
Facelets page + single JSF managed bean WAR project already sitting
there ready to adapt. :)

The JPA facet in Eclipse does pretty much the same thing as JPA support
in NB: back & forth wizard-driven JPA artifacts <=> DB stuff. Both are
fine, provided that you sanity-check source every so often.

Unless you don't have a data source declared in persistence.xml and not
defined in the app server I doubt you missed anything - this particular
test case is pretty simple. I think it's the added annotation of your
session EJB as a JSF managed bean (not just @Stateless), plus pulling it
in to the calling JSF managed bean with @ManagedProperty. As I mentioned
previously my session EJB is just that, @Stateless (no @ManagedBean on
that class), and where you've got @ManagedProperty I've got @EJB.

The fact that your container-managed @PersistenceContext DI is also not
working supports this conclusion.

AHS
 
M

markspace

When I call my session bean from my JSF managed bean, I inject it with
@EJB. You're not doing that


Yes, that was it exactly. I was pretty confused by all the different
types of injection. There's @ManagedProperty, @EJB, @Resource and
@Inject at least, off the top of my head. Looks like I'm going to have
to study up and make certain I understand when it's appropriate to use each.

FYI, I was confused because one of my texts does a sneaky thing. They
annotate a class like this (not syntax checked):


@Named("user")
@SessionScoped
@Stateful
public class UserBean {

@PersitenceContext
private EntityManager em;

public String getName() {...} // called from JSF view

... // other methods also called from JSF view
... // uses container manged transactions herein too

}

Which was kinda confusing how they set up this class. However, the
source listing, which occurs later, has an important detail.


import javax.ejb.Stateful;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named("user")
@SessionScoped
@Stateful
public class UserBean { ...

Yeah, after 518 pages of using javax.faces.bean.SessionScoped, they
switch to the javax.enterprise.context one without calling out the
change. I probably should have caught that, but it's a lot to digest
all at once.


I think we can declare this problem solved (and also PEBCAK). @EJB for
injection worked. Incidentally, I also removed the em.flush() from my
bean and the data was persisted anyway, which is what should have been
happening all along. Data should be persisted on a commit(), which
happens at the end of any container manged transaction, so I was
confused about that too. So actually that's two mysteries solved.
 
A

Arved Sandstrom

Yes, that was it exactly. I was pretty confused by all the different
types of injection. There's @ManagedProperty, @EJB, @Resource and
@Inject at least, off the top of my head. Looks like I'm going to have
to study up and make certain I understand when it's appropriate to use
each.
[ SNIP ]

Cool, glad to hear it. I'm not going to offer any further advice on
various annotations and possibilities; fact of the matter is that the
errors and mistakes you just now had to solve, and the further avenues
of research they suggested, considerably shrank the domain of
Rumsfeldian unknown unknowns for you. Which is a good thing - I've seen
developers who got much further because of lucky copy & paste and IDE
magic who still didn't really understand what you're now coming to good
grips with.

AHS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top