001 /** 002 * Copyright 2005-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.rice.krad.app.persistence.jpa; 017 018 import org.kuali.rice.core.api.config.property.Config; 019 import org.kuali.rice.core.api.config.property.ConfigContext; 020 import org.kuali.rice.core.framework.persistence.jpa.DevHibernateJpaVendorAdapter; 021 import org.springframework.orm.jpa.JpaVendorAdapter; 022 import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 023 import org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager; 024 import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager; 025 026 import javax.sql.DataSource; 027 import java.util.HashMap; 028 import java.util.Map; 029 030 /** 031 * @author Kuali Rice Team (rice.collab@kuali.org) 032 */ 033 public class RiceLocalContainerEntityManagerFactoryBean extends LocalContainerEntityManagerFactoryBean { 034 035 public RiceLocalContainerEntityManagerFactoryBean() { 036 throw new RuntimeException(getClass().getName() + " can not be constructed without a datasource"); 037 } 038 039 public RiceLocalContainerEntityManagerFactoryBean(DataSource datasource) { 040 this("", datasource); 041 } 042 043 public RiceLocalContainerEntityManagerFactoryBean(String prefix, DataSource datasource) { 044 if (prefix.equals("")) { 045 prefix = "rice"; 046 } 047 prefix += ".jpa."; 048 049 Config config = ConfigContext.getCurrentContextConfig(); 050 051 setPersistenceUnitManager(preparePersistentUnitManager(config, prefix, datasource)); 052 setPersistenceXmlLocation(determineConfigProperty(config, prefix, "PersistenceXmlLocation", "META-INF/persistence.xml")); 053 setDataSource(datasource); 054 setPersistenceUnitName(determineConfigProperty(config, prefix, "PersistenceUnitName", "rice")); 055 setJpaDialect(new org.springframework.orm.jpa.vendor.HibernateJpaDialect()); 056 setJpaPropertyMap(prepareJpaProperties(config, prefix)); 057 setJpaVendorAdapter(prepareJpaVendorAdapter(config, prefix)); 058 059 RicePersistenceUnitPostProcessor postProcessor = new RicePersistenceUnitPostProcessor(); 060 postProcessor.setJtaDataSource(datasource); 061 setPersistenceUnitPostProcessors(new RicePersistenceUnitPostProcessor[] { postProcessor }); 062 } 063 064 065 private PersistenceUnitManager preparePersistentUnitManager(Config config, String prefix, DataSource datasource) { 066 DefaultPersistenceUnitManager persistenceUnitManager = new DefaultPersistenceUnitManager(); 067 persistenceUnitManager.setDefaultDataSource(datasource); 068 persistenceUnitManager.setPersistenceXmlLocations(new String[] {determineConfigProperty(config, prefix, "PersistenceXmlLocation", "META-INF/persistence.xml")}); 069 persistenceUnitManager.setDefaultPersistenceUnitRootLocation(determineConfigProperty(config, prefix, "PersistenceUnitRootLocation", "classpath:")); 070 RicePersistenceUnitPostProcessor postProcessor = new RicePersistenceUnitPostProcessor(); 071 postProcessor.setJtaDataSource(datasource); 072 persistenceUnitManager.setPersistenceUnitPostProcessors(new RicePersistenceUnitPostProcessor[] { postProcessor }); 073 persistenceUnitManager.afterPropertiesSet(); 074 return persistenceUnitManager; 075 } 076 077 private JpaVendorAdapter prepareJpaVendorAdapter(Config config, String prefix) { 078 DevHibernateJpaVendorAdapter jpaVendorAdapter = new DevHibernateJpaVendorAdapter(); 079 jpaVendorAdapter.setDatabasePlatform(determineConfigProperty(config, prefix, "DatabasePlatform", "org.hibernate.dialect.MySQLDialect")); 080 jpaVendorAdapter.setGenerateDdl(new Boolean(determineConfigProperty(config, prefix, "GenerateDdl", "false"))); 081 jpaVendorAdapter.setSerializationFilename(determineConfigProperty(config, prefix, "SerializationFilename", "/tmp/Ejb3Configuration.out")); 082 jpaVendorAdapter.setUseSerialization(new Boolean(determineConfigProperty(config, prefix, "UseSerialization", "true"))); 083 try { 084 jpaVendorAdapter.afterPropertiesSet(); 085 } catch (Exception e) {} 086 return jpaVendorAdapter; 087 } 088 089 private Map<String, String> prepareJpaProperties(Config config, String prefix) { 090 Map<String, String> jpaProperties = new HashMap<String, String>(); 091 092 // Load in all user specified "JPAProperties" prefixed properties 093 jpaProperties.putAll(config.getPropertiesWithPrefix(prefix + "JpaProperties.", true)); 094 095 // Load in the defaults for a Hibernate JPA Setup. Since the JPA spec states that these properties will be ignored by 096 // vendors that do not understand them, we can add all of the necessary defaults per supported JPA vendor here. 097 jpaProperties.put("hibernate.show_sql", determineConfigProperty(config, prefix, "JpaProperties.hibernate.show_sql", "false")); 098 jpaProperties.put("hibernate.format_sql", determineConfigProperty(config, prefix, "JpaProperties.hibernate.format_sql", "false")); 099 jpaProperties.put("hibernate.use_sql_comments", determineConfigProperty(config, prefix, "JpaProperties.hibernate.use_sql_comments", "false")); 100 // Default now JTOM rather than Atomikos. Atomikos can be used by setting (KULRICE-1909) 101 // JpaProperties.hibernate.transaction.manager_lookup_class=org.kuali.rice.core.jta.AtomikosTransactionManagerLookup 102 // in a configuration file for a JPA persistence unit. 103 jpaProperties.put("hibernate.transaction.manager_lookup_class", determineConfigProperty(config, prefix, "JpaProperties.hibernate.transaction.manager_lookup_class", "org.hibernate.transaction.JOTMTransactionManagerLookup")); 104 //jpaProperties.put("hibernate.transaction.manager_lookup_class", determineConfigProperty(config, prefix, "JpaProperties.hibernate.transaction.manager_lookup_class", "org.kuali.rice.core.jta.AtomikosTransactionManagerLookup")); 105 jpaProperties.put("hibernate.current_session_context_class", determineConfigProperty(config, prefix, "JpaProperties.hibernate.current_session_context_class", "org.hibernate.context.JTASessionContext")); 106 jpaProperties.put("hibernate.connection.release_mode", determineConfigProperty(config, prefix, "JpaProperties.hibernate.connection.release_mode", "auto")); 107 jpaProperties.put("hibernate.transaction.flush_before_completion", determineConfigProperty(config, prefix, "JpaProperties.hibernate.transaction.flush_before_completion", "true")); 108 jpaProperties.put("hibernate.bytecode.use_reflection_optimizer", determineConfigProperty(config, prefix, "JpaProperties.hibernate.bytecode.use_reflection_optimizer", "false")); 109 jpaProperties.put("hibernate.transaction.auto_close_session", determineConfigProperty(config, prefix, "JpaProperties.hibernate.transaction.auto_close_session", "false")); 110 jpaProperties.put("hibernate.hbm2ddl.auto", determineConfigProperty(config, prefix, "JpaProperties.hibernate.hbm2ddl.auto", "")); 111 112 // TODO: Add more vendor specific defaults... 113 114 return jpaProperties; 115 } 116 117 private String determineConfigProperty(Config config, String prefix, String key, String defaultValue) { 118 String value = config.getProperty(prefix + key); 119 // fallback on the defaults (non-module based properties) 120 if (value == null) { 121 value = config.getProperty("rice.jpa." + key); 122 } 123 // fallback on the default value passed in if still no value found for key 124 return value == null ? defaultValue : value; 125 } 126 127 }