Built with Seam

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.

Active development of Seam Persistence has been halted by Red Hat. This project has been migrated over to Apache DeltaSpike .

Seam Persistence

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)

* Maven artifacts are located in the JBoss Community Repository:

Module team

Name Module role Commit username (Git) Hometown (Time zone)
Stuart Douglas Lead stuartwdouglas Sydney, AU (UTC+10)
Want your name to appear in this list? Join us in #seam-dev on freenode and let us know you want to get involved.


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:

  • Declarative transaction support for managed beans
  • A simplified transaction API
  • A seam managed persistence context usable in both SE and EE environments
  • Envars Integration
  • Hibernate Search Integration
  • Injection into entities
  • A CDI Transaction Scope

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.

Release plan

(status: draft) - This plan is still being defined.

Version Time frame Focus
3.0.0.Alpha1 Available
  • Project structure compliant with Module Anatomy
  • Transaction interceptor for managed beans
  • Transaction API-agnostic UserTransaction producer (depended on by Faces lifecycle transactions)
  • Simplified transaction API
  • Seam Managed Persistence Context
  • Hibernate Search Integration
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
  • REQUIRES_NEW Support including stopping SPMC propagation (this will be configurable behaviour)
  • Envars Integration

Design whiteboard

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.

Declarative transactions

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).

Unified transaction API

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:

  • isActive
  • isActiveOrMarkedRollback
  • isRolledBackOrMarkedRollback
  • isMarkedRollback
  • isNoTransaction
  • isRolledBack
  • isCommitted

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:

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 events

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.

Persistence management

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.

  • We should be encouraging the use of the web profile at a minimum, which provides container-managed persistence
  • Spring could use container-managed persistence, allowing it to cleanly integrate with Java EE and Seam applications

The Seam Managed Persistence Context can be configured as follows:

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.

Transaction enlistment

The SMPC is automatically enlisted in the current transaction, this is achieved by proxying the EntityManager.

Manual flush mode activation

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.

JSF integration

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.

Envers integration

We will want to integration with Envers to make it easy for a developer to add auditing to their database-oriented application.

  • injecting AuditReader (wrapper around the current EntityManager to read history)
  • fireing and observing a new revision event

Hibernate Search Integration

We should provide hibernate search integration in a similar manner to seam 2.