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    }