You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
Brings transactions and persistence to managed beans, provides a simplified transaction API and hooks transaction propagation events to the CDI event bus.
To get started, add one of the following dependency groups below to your pom.xml:
Individual JARs | Combined JAR (API & implementation) |
---|---|
<dependency> <groupId>org.jboss.seam.persistence</groupId> <artifactId>seam-persistence-api</artifactId> <version>3.0.0.Final</version> </dependency> <dependency> <groupId>org.jboss.seam.persistence</groupId> <artifactId>seam-persistence-impl</artifactId> <version>3.0.0.Final</version> <scope>runtime</scope> </dependency> |
<dependency> <groupId>org.jboss.seam.persistence</groupId> <artifactId>seam-persistence</artifactId> <version>3.0.0.Final</version> </dependency> |
Name | Module role | Commit username (Git) | Hometown (Time zone) |
---|---|---|---|
Stuart Douglas | Lead | stuartwdouglas | Sydney, AU (UTC+10) |
Brings transactions and persistence to non-EJB managed beans, provides a simplified transaction API and hooks transaction propagation events to the CDI event bus. It may also bring features handled by Java EE containers to your CDI application running on Java SE or servlet containers, like Tomcat or Jetty. This module also includes abstractions for Persistence as a general concept (JDBC, JPA, Hibernate, NoSQL, and JDO,) otherwise referred to as the Seam-persistence framework - making CRUD easy, and more.
The overall goal of EJB 3.1 was to simplify overall usability so that developers would choose either an EJB stateful or stateless session bean when needing declarative transaction or security capabilities. The difference between an EJB and managed bean has been reduced to a single annotation on the class:
managed bean:
public class ManagedBean {}
stateful session bean:
@Stateful public class ManagedBean {}
stateless session bean:
@Stateless public class ManagedBean {}
An EJB no longer requires an interface and can be packaged in a war. What sets apart an EJB is that it has transactions enabled by default (type REQUIRED), whereas the managed bean has no out-of-the-box interceptors.
In Java EE 6, the only beans that support transactions out of the box
are EJBs. You can, of course, apply your own interceptor to any bean, but there is no off the shelf
transaction interceptor. Many people, including us, believe that non-EJB managed beans should enjoy declarative transaction capability as well. It didn't happen for Java EE 6. That is the need we seek to fill to some extent in Seam 3, and perhaps weave into the platform in the future.
The Seam Persistence module will provide the following:
It would also be nice to support REQUIRES_NEW for managed beans, although this will probably require configuring a transaction manager in xml as support for this varies between application servers.
(status: draft) - This plan is still being defined.
Version | Time frame | Focus |
---|---|---|
3.0.0.Alpha1 | Available |
|
3.0.0.Beta1 | Available | Managed Hibernate Sessions |
3.0.0.Beta2 | Available | Updated to use Seam Solder |
3.0.0.CR1 | Available | Improved documentation, especially for people who are new to JPA/Hibernate Tests for all containers (Jboss 6, Jetty, Jetty + openjpa, Glassfish, Glassfish + Hibernate, Jboss 5) |
3.1 | TBA |
|
This section serves as a whiteboard for design and ideas for this module. Once you've decided to pursue a feature, it should be added to JIRA as a feature request and optionally linked from this page. |
Most of the time when a developer chooses to use a managed bean, it's because they do not need transactional capabilities. In fact, transactional components are typically limited to a single layer of the application (call it the service layer) or set of components (call them business components). The case we are trying to address is the developer that wants to use managed beans to serve in this role.
Therefore, it's safe to say that declarative transactions are something the developer should have to specify explicitly (not on by default, like with EJB). Having every bean be transactional would be an unnecessary overhead. But the transaction annotation would only be needed on the class to apply to all public methods and the default attribute would be REQUIRED to be consistent w/ EJB.
Seam persistence allows you to use @TransactionAttribute on managed beans as well as EJB's. It also provides an @Transactional annotation for use in non EE environments where @TransactionAttribute is unavailable. It also provides @SeamApplicationException for this same purpose (as a replacement for @ApplicationException).
Forum discussion: here.
Transactions will only be rolled back if an exception is propagated out of the managed bean that started the transaction, unlike seam 2 where a rollback would occur if an exception propagated out of any component.
Transaction support is implemented in a similar manner to seam 2. The default is to use JTA, however EntityTransaction and HibernateTransaction will also be provided, and the user can provide their own SeamTransaction implementation.
This brings us to the unified transaction API (with important convenience methods).
The JTA transaction API (javax.transaction.UserTransaction) makes you work pretty hard to find out basic information about the state of the transaction. Consider these questions:
Each of these questions must be answered by calling UserTransaction#getStatus() and comparing the result value to a static constant in the class javax.transaction.Status.
We will provide SeamTransaction which will extend javax.transaction.UserTransaction with these convenience methods. The SeamTransaction object can be injected as follows:
@Inject @DefaultTransaction SeamTransaction transaction;
Providing declarative transactions on managed beans also requires that we register the bean to receive transaction synchronization events. We may be able to handle this with a more general event mechanism, but if not, then it makes sense to add this support to the transaction abstraction API.
Transaction success and failure should be placed on the CDI event bus to that managed beans can react to them. We may need to receive JTA transaction completion notifications from the EJB container and pass them on to registered synchronizations, or just onto the CDI event bus.
This is difficult to achieve for all cases, as there is no general mechanism for being notified of transaction start, so if no transactional resources from seam-persistence participate in a transaction we will not be able to register a synchronisation, and no event will be fired. I think the best we can do is fire a transaction completed event for every SMPC that participated in the transaction.
Java EE 6 has vastly improved in that all managed beans, EJB or not, get @Resource and family injections. This means that, as long as there is container-managed persistence available (web profile and up), it's possible to inject the EntityManager.
@PersistenceContext EntityManager em;
Of course, this is a weak
injection point for several reasons. First, if there is a more than one persistence unit, the string-based unit name is required:
@PersistenceContext(unitName = "erp") EntityManager erpEm;
Additionally, there are propagation issues depending on the order of invocation of beans hosting this annotation. So it makes more sense to centralize the injection, which CDI makes possible using a producer field.
@Produces @Erp @PersistenceContext(unitName = "erp") EntityManager erpEm;
The EntityManager can now be injected elsewhere in the application using:
@Inject @Erp EntityManager erpEm;
The string-based unit name is relegated to a single injection point.
The problems with this are similar to that of transactions. It will not work in a servlet contaienr, nor does it play well with an application-managed EntityManager (created using Persistence#createEntityManager()).
This EntityManager is also a transaction scoped container managed EntityManager. It is not possible to create extended persistence contexts in this manner.
The Seam Managed Persistence Context can be configured as follows:
@ExtensionManaged @ConversationScoped @Produces @PersistenceUnit(unitName="myPu") EntityManagerFactory emf;
This will even work in a servlet/se environment, as seam persistence will detect this and bootstrap the entity manager factory automatically.
A configurable persistence context is needed by other modules as well. It raises the question:
How should we be providing persistence contexts to the beans in our own modules that manipulate persistent data (e.g. JpaIdentityStore)?
Likely a simple @Inject EntityManager entityManager; declaration would be best, meaning that it would be up to the application itself to provide the EntityManager producer method. However, it would be nice to have the persistence module provide a built-in producer that can be configured via XML.
It's important the when the EntityManager is injected, regardless of how it's implemented, it gets enlisted in the current transaction.
The SMPC is automatically enlisted in the current transaction, this is achieved by proxying the EntityManager.
Default flush mode settings need to be configurable in a fine grained manner. e.g. It should be possible to have manual flush mode by default, except for pages in /app/crud, which use auto flush mode.
We will want to provide the Seam-managed transaction around the JSF lifecycle like we did in Seam 2. We'll have to think about where this code belongs (probably the Faces module) and how best to loosely link it to this module (optional dependency).
Forum discussion: here.
We will want to integration with Envers to make it easy for a developer to add auditing to their database-oriented application.
new revisionevent
We should provide hibernate search integration in a similar manner to seam 2.