/* * 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); } }