Hi -
I have an EE6 Jersey/CDI/JPA2 application which is packaged as a WAR
and deployed to GFv3b74.2. It's a pretty simple test app. The entry
point is a ReST resource that looks like this:
@Path("/test/")
@RequestScoped
public class HelloWorld {
@Inject
PersonBean myPersonBean;
@Context
UriInfo uriInfo;
@Get
@Produces("text/plain")
@Path("/clickMe")
public String getClicked() {
Person aPerson = new Person();
aPerson.setName("John Smith");
myPersonBean.create(aPerson);
return "Created a new person";
}
Then I have the PersonBean class that looks like this:
@Named("personbean")
@RequestScoped
public class PersonBean {
@PersistenceContext(unitname = "myEmbeddedDerby-PU")
EntityManager em;
public void create(Person aPerson) {
em.persist(aPerson);
}
....
My Person entity class is pretty straight forward:
@Entity
public class Person implements Serializable {
@Id
@GeneratedValue
private long id;
@NotNull
private String name;
getters/setters/etc
.....
I am trying to use the Container-Managed Entity Manager. The relevant
bits of my persistence.xml look like this:
<persistence-unit name="myEmbeddedDerby-PU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/__MyTestDBPool</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
...
</persistence-unit>
I have an empty beans.xml, and my web.xml simply contains references
to the Jersey servlet.
I'm using an embedded Derby JDBC connection pool / resource which I
created like so:
asadmin create-jdbc-connection-pool --datasourceclassname
org.apache.derby.jdbc.EmbeddedDataSource --restype
javax.sql.ConnectionPoolDataSource --property
"databaseName=\$\{com.sun.aas.instanceRoot\}/databases/mytestdb:connectionAttributes=\;create\=true"
MyTestDBPool
2. Cause the DB to get generated by pinging it
asadmin ping-connection-pool MyTestDBPool
3. Create the JDBC resource
asadmin create-jdbc-resource --connectionpoolid=MyTestDBPool jdbc/__MyTestDBPool
So - when I run this application and I get the follow exception at
em.persist(aPerson):
javax.persistence.TransactionRequiredException
On a hunch I tried injecting a UserTransaction into my PersonBean like so:
@Resource
private UserTransaction utx;
Then changing my create method like so:
try {
utx.begin();
em.persist(aPerson);
utx.commit();
.....
That worked and caused my entity to be persisted, however, that
indicates that I am using an Application-Managed Entity Manager
instead of my desired Container-Managed Entity Manager.
Any thoughts on what am I missing here to enable using the
Container-Managed Entity Manager.
...
Actually, before I hit post I went off and did some more digging and
on a hunch I turned by PersonBean into a Stateless EJB Session bean by
removing @RequestScoped and adding @Stateless, the I changed how it
was being injected into the ReST resource by changing @Inject
PersonBean myPersonBean to @EJB PersonBean myPersonBean et voila it is
working in a Container-Managed fashion.
So this leads me to the question, why was the RequestScoped CDI bean
not providing a container managed EM w/transactions? Are EJBs the only
EE components which do?
While pondering that I tried another hunch and made one more round of
changes, namely I re-added @RequestScoped to my PersonBean and changed
@Stateless to @Stateful then in my ReST resource I changed the @EJB
annotation back to @Inject et voila it work this way as well.
Now that said, does this mean that because I used an EJB annotation
(to trigger the Container Managed EM) that this class can not act as a
CDI ManagedBean? I ask this based on the Java EE 6 Tutorial section on
Managed Beans in Part V Contexts and Dependency Injection which says
"A top-level Java class is a managed bean if it is defined to be a
managed bean by any other Java EE technology specification (for
example, the JavaServer Faces technology specification), or if it
meets all of the following conditions:
....
* It is not annotated with an EJB component-defining annotation or
declared as an EJB bean in ejb-jar.xml
...
Or is it a CDI ManagedBean because I have the class annotated with
@RequestScoped even though it is also annotated with @Stateful ?
Thanks,
-Noah