org.overlord.rtgov.common.jpa.JpaStore.java Source code

Java tutorial

Introduction

Here is the source code for org.overlord.rtgov.common.jpa.JpaStore.java

Source

/*
 * Copyright 2014 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.overlord.rtgov.common.jpa;

import java.net.URL;
import java.util.Properties;
import java.util.logging.Logger;

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.overlord.rtgov.common.util.RTGovProperties;

/**
 * Provides common JPA functionality to all data stores.
 * 
 * Note: This is actually using native Hibernate ORM, rather than JPA, but I'm
 * keeping the "JPA" name for consistency's sake. Since we need to dynamically
 * provide the DataSource, JtaPlatform, etc., we can't include incomplete
 * persistence.xml files with those values missing. EE containers grab the files
 * and automatically attempt to create JPA EntityManagerFactories with them.
 * There's not an easy, cross-platform way to prevent that. So instead, fall
 * back on native ORM.
 * 
 * @author Brett Meyer
 */
public class JpaStore {
    private static final Logger LOG = Logger.getLogger(JpaStore.class.getName());

    private static final String JTA_PLATFORM_PROPERTY = "JpaStore.jtaPlatform";

    private URL _configXml;

    private String _jndiProperty;

    private SessionFactory _sessionFactory;

    @Deprecated
    private String _persistenceUnit;

    @Deprecated
    private EntityManagerFactory _entityManagerFactory;

    private boolean _isJta = true;

    /**
     * The constructor.
     * 
     * @param configXml
     *            The hibernate.cfg.xml URL
     * @param jndiProperty
     *            The jndi name
     */
    public JpaStore(URL configXml, String jndiProperty) {
        _configXml = configXml;
        _jndiProperty = jndiProperty;
    }

    /**
     * The constructor.
     * 
     * @param configXml
     *            The hibernate.cfg.xml URL
     */
    public JpaStore(URL configXml) {
        this(configXml, null);
    }

    /**
     * The constructor.
     * 
     * @param persistenceUnit
     *            The persistence unit name
     * @param jndiProperty
     *            The jndi name
     */
    @Deprecated
    public JpaStore(String persistenceUnit, String jndiProperty) {
        _persistenceUnit = persistenceUnit;
        _jndiProperty = jndiProperty;
    }

    /**
     * The constructor.
     * 
     * @param persistenceUnit
     *            The persistence unit name
     */
    @Deprecated
    public JpaStore(String persistenceUnit) {
        this(persistenceUnit, null);
    }

    /**
     * This method returns a Session.
     * 
     * @return The Session
     */
    private Session getSession() {
        if (_persistenceUnit == null) {
            if (_sessionFactory == null) {
                final Configuration cfg = new Configuration().configure(_configXml);
                final Properties properties = RTGovProperties.getProperties();
                if (_jndiProperty != null) {
                    String prop = RTGovProperties.getProperty(_jndiProperty);
                    if (prop != null) {
                        properties.setProperty(AvailableSettings.DATASOURCE, prop);
                    }
                }
                final String jtaPlatform = RTGovProperties.getProperty(JTA_PLATFORM_PROPERTY);
                if (jtaPlatform == null) {
                    LOG.warning("JpaStore.jtaPlatform not set in overlord-rtgov.properties!");
                    _isJta = false;
                } else {
                    properties.setProperty(AvailableSettings.JTA_PLATFORM,
                            RTGovProperties.getProperty(JTA_PLATFORM_PROPERTY));
                }
                cfg.getProperties().putAll(properties);
                _sessionFactory = cfg.buildSessionFactory();
            }

            return _sessionFactory.openSession();
        } else {
            // NOTE: For backward compatibility in EAP, I'm allowing the
            // continued use of a persistence unit.
            // Simply use it to create an EntityManager, then unwrap to the
            // native Hibernate Session.
            if (_entityManagerFactory == null) {
                final Properties properties = RTGovProperties.getProperties();
                if (_jndiProperty != null) {
                    properties.setProperty(AvailableSettings.DATASOURCE,
                            RTGovProperties.getProperty(_jndiProperty));
                }
                final String jtaPlatform = RTGovProperties.getProperty(JTA_PLATFORM_PROPERTY);
                if (jtaPlatform == null) {
                    LOG.warning("JpaStore.jtaPlatform not set in overlord-rtgov.properties!");
                    _isJta = false;
                } else {
                    properties.setProperty(AvailableSettings.JTA_PLATFORM,
                            RTGovProperties.getProperty(JTA_PLATFORM_PROPERTY));
                }
                _entityManagerFactory = Persistence.createEntityManagerFactory(_persistenceUnit, properties);
            }

            return _entityManagerFactory.createEntityManager().unwrap(Session.class);
        }
    }

    /**
     * This method performs the supplied work in a transaction.
     * 
     * @param work
     *            The unit of work
     * @param <T>
     *            The type if the return value
     * @return The return value
     */
    public <T> T withJpa(JpaWork<T> work) {
        final Session s = getSession();
        try {
            if (!_isJta) {
                s.getTransaction().begin();
            }
            final T result = work.perform(s);
            s.flush();
            if (!_isJta) {
                s.getTransaction().commit();
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            s.close();
        }
    }

    /**
     * Perform work using a provided Hibernate Session.
     * 
     * @param <T>
     *            The return type
     */
    public static interface JpaWork<T> {
        /**
         * The work to be performed using the Session.
         * 
         * @param s
         *            The Session
         * @return The result of the work
         */
        public T perform(Session s);
    }
}