Help

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.

Hibernate is the default persistence provider in Seam but it is theoretically possible use other persistence provider. Seam 2.1.1.GA documentation states that in the future, this will be easier.

If you cannot wait the future, this walkthrough describes the changes required to switch a CRUD application from Hibernate to OpenJPA.

Requirements: in order to use OpenJPA as an alternate JPA provider, you will need:

  • Seam 2.1.2-SNAPSHOT (at least, but using the latest snapshot is recommended)
  • Open JPA 1.2.1 SNAPSHOT (at least, but using the latest snapshot is recommended)

First, let's see the functionality differences between Hibernate and OpenJPA:

Functionality Hibernate OpenJPA
Query result pagination Yes No (see OPENJPA-759)
Identifier alias 'id' Yes No
Expression in LIKE query parameter Yes No (see OPENJPA-920)
Auditing 1) JPA-standard
2) HibernateInterceptor
1) JPA-standard

Note: JPA-standard Auditing is done via @EntityListeners, @PrePersist, @PreUpdate, ...

There is also syntax differences between these two persistence providers:

Functionality Hibernate OpenJPA
Key generator interface org.hibernate.id.IdentifierGenerator org.apache.openjpa.kernel.Seq
Key generator annotation @GenericGenerator @SequenceGenerator with specific name
Yes/No type @org.hibernate.annotations.Type("yes_no") @ExternalValues("true=Y", "false=N") @org.apache.openjpa.persistence.Type(char.class)
Logging proprietary Hibernate format proprietary OpenJPA format

Walkthrough

  1. Create a new PersistenceProvider for OpenJPA (note: this is a light implementation which may be improved)
    //@Name("org.jboss.seam.persistence.persistenceProvider") // see next step
    @Scope(ScopeType.STATELESS)
    @BypassInterceptors
    @Install(precedence=FRAMEWORK, classDependencies={"javax.persistence.EntityManager"})
    public class OpenJpaPersistenceProvider extends PersistenceProvider {
      Log log = Logging.getLog(OpenJpaPersistenceProvider.class);
    
      @Override
      public void setFlushModeManual(EntityManager entityManager) {
        // see also https://jira.jboss.org/jira/browse/JBSEAM-3030
        log.warn("setFlushModeManual is not supported by OpenJPA");
      }
    }
  2. Register the new PersistenceProvider in components.xml
    <!--
    the persistence provider cannot be a named Seam component with the @Name annotation,
    otherwise Seam raises an error because HibernatePersistenceProvider already define
    this name (duplicate component). Thus, we are defining the component here
    (see http://docs.jboss.com/seam/2.1.1.GA/reference/en-US/html_single/#alt-jpa-providers for details)
    -->
    <component name="org.jboss.seam.persistence.persistenceProvider" 
               class="org.your.package.OpenJpaPersistenceProvider">
    </component>
    Note: in the future, this should be easier, see JBSEAM-2785
  3. If you get any, convert your HibernateInterceptor to JPA-standard @EntityListeners.
    Each entity must be annotated by @EntityListeners (this can be done in seam-gen/pojo/Ejb3TypeDeclaration.ftl, extracted and customized from hibernate-tools.jar/pojo/Ejb3TypeDeclaration.ftl).
    You may hit the following issues: OPENJPA-754, OPENJPA-1018 (if you use Runtime Unenhanced Subclassing), HV-138 (if you use Hibernate Validator)
    See also: http://webspherepersistence.blogspot.com/2009/01/auditing-with-openjpa.html
  4. If you get any, convert your Hibernate Yes/No type to OpenJPA Yes/No type
    You should change seam-gen/pojo/GetPropertyAnnotation.ftl as described in JBSEAM-4088:
    //replace: 
    //@${pojo.importType("org.hibernate.annotations.Type")}(type="yes_no")}
    
    // by:
    @${pojo.importType("org.apache.openjpa.persistence.ExternalValues")}({"true=Y", "false=N"})
    @${pojo.importType("org.apache.openjpa.persistence.Type")}(char.class)
    Note: you may hit the following issue: OPENJPA-828
  5. If you get any, convert you Hibernate GenericGenerator to OpenJPA custom SequenceGenerator
    Note: the best is to add this annotation for all required entities in the seam-gen/pojo/GetPropertyAnnotation.ftl
  6. Modify your persistence.xml for OpenJPA:
    • Change the persistence provider (<provider> tag)
    • If you use runtime enhancement, add each entity class (<class> tag)
    • You should keep Hibernate and OpenJpa properties in the same file so that you can swith between them easily later
  7. Patch Seam for JBSEAM-4093 and JBSEAM-4117 if not yet included in your Seam version
  8. Deploy your application
    Note: if you run under Websphere 6.1, you may hit JBSEAM-4093
  9. Test the CRUD application
    Note: you may hit the following issue: OPENJPA-1025

Using the walkthrough above, you will be able to switch from Hibernate to OpenJPA (and vice-versa) just by doing the following operations:

  1. Generate entities using seam-gen by changing the annotation mode (Hibernate/OpenJPA)
  2. Change the <provider> in persistence.xml
  3. Change the PersistenceProvider in components.xml (comment/uncomment the component named org.jboss.seam.persistence.persistenceProvider)

Convenient, isn't?