001 // Copyright 2011 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5.jpa; 016 017 import org.apache.tapestry5.ValueEncoder; 018 import org.apache.tapestry5.internal.InternalConstants; 019 import org.apache.tapestry5.internal.jpa.*; 020 import org.apache.tapestry5.internal.services.PersistentFieldManager; 021 import org.apache.tapestry5.ioc.*; 022 import org.apache.tapestry5.ioc.annotations.*; 023 import org.apache.tapestry5.ioc.services.*; 024 import org.apache.tapestry5.services.*; 025 import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; 026 import org.slf4j.Logger; 027 028 import javax.persistence.EntityManagerFactory; 029 import javax.persistence.metamodel.EntityType; 030 import javax.persistence.metamodel.Metamodel; 031 import javax.persistence.spi.PersistenceUnitInfo; 032 import java.util.Collection; 033 import java.util.Map; 034 035 /** 036 * Defines core services for JPA support. 037 * 038 * @since 5.3 039 */ 040 public class JpaModule 041 { 042 public static void bind(final ServiceBinder binder) 043 { 044 binder.bind(JpaTransactionAdvisor.class, JpaTransactionAdvisorImpl.class); 045 binder.bind(PersistenceUnitConfigurer.class, PackageNamePersistenceUnitConfigurer.class).withSimpleId(); 046 binder.bind(EntityManagerSource.class, EntityManagerSourceImpl.class); 047 } 048 049 public static JpaEntityPackageManager buildJpaEntityPackageManager(final Collection<String> packageNames) 050 { 051 return new JpaEntityPackageManager() 052 { 053 public Collection<String> getPackageNames() 054 { 055 return packageNames; 056 } 057 }; 058 } 059 060 @Scope(ScopeConstants.PERTHREAD) 061 public static EntityManagerManager buildEntityManagerManager(final EntityManagerSource entityManagerSource, 062 final PerthreadManager perthreadManager, final Logger logger) 063 { 064 final EntityManagerManagerImpl service = new EntityManagerManagerImpl(entityManagerSource, logger); 065 066 perthreadManager.addThreadCleanupListener(service); 067 068 return service; 069 } 070 071 @Contribute(JpaEntityPackageManager.class) 072 public static void provideEntityPackages(Configuration<String> configuration, 073 074 @Symbol(InternalConstants.TAPESTRY_APP_PACKAGE_PARAM) 075 String appRootPackage) 076 { 077 configuration.add(appRootPackage + ".entities"); 078 } 079 080 @Contribute(PersistentFieldManager.class) 081 public static void provideEntityPersistentFieldStrategies( 082 final MappedConfiguration<String, PersistentFieldStrategy> configuration) 083 { 084 configuration.addInstance(JpaPersistenceConstants.ENTITY, EntityPersistentFieldStrategy.class); 085 } 086 087 @Contribute(ApplicationStatePersistenceStrategySource.class) 088 public void provideApplicationStatePersistenceStrategies( 089 final MappedConfiguration<String, ApplicationStatePersistenceStrategy> configuration) 090 { 091 configuration.addInstance(JpaPersistenceConstants.ENTITY, EntityApplicationStatePersistenceStrategy.class); 092 } 093 094 @Contribute(ComponentClassTransformWorker2.class) 095 @Primary 096 public static void provideClassTransformWorkers(OrderedConfiguration<ComponentClassTransformWorker2> configuration) 097 { 098 configuration.addInstance("PersistenceContext", PersistenceContextWorker.class, "after:Property"); 099 configuration.addInstance("JPACommitAfter", CommitAfterWorker.class, "after:Log"); 100 } 101 102 @Contribute(MasterObjectProvider.class) 103 public static void provideObjectProviders(final OrderedConfiguration<ObjectProvider> configuration) 104 { 105 configuration.addInstance("EntityManager", EntityManagerObjectProvider.class, 106 "before:AnnotationBasedContributions"); 107 } 108 109 @Contribute(SymbolProvider.class) 110 @FactoryDefaults 111 public static void provideFactoryDefaults(final MappedConfiguration<String, String> configuration) 112 { 113 configuration.add(JpaSymbols.PROVIDE_ENTITY_VALUE_ENCODERS, "true"); 114 configuration.add(JpaSymbols.EARLY_START_UP, "true"); 115 configuration.add(JpaSymbols.ENTITY_SESSION_STATE_PERSISTENCE_STRATEGY_ENABLED, "true"); 116 configuration.add(JpaSymbols.PERSISTENCE_DESCRIPTOR, "/META-INF/persistence.xml"); 117 } 118 119 @Contribute(ValueEncoderSource.class) 120 public static void provideValueEncoders(final MappedConfiguration<Class, ValueEncoderFactory> configuration, 121 @Symbol(JpaSymbols.PROVIDE_ENTITY_VALUE_ENCODERS) 122 final boolean provideEncoders, final EntityManagerSource entityManagerSource, 123 final EntityManagerManager entityManagerManager, final TypeCoercer typeCoercer, 124 final PropertyAccess propertyAccess, final LoggerSource loggerSource) 125 { 126 127 if (!provideEncoders) 128 return; 129 130 for (final PersistenceUnitInfo info : entityManagerSource.getPersistenceUnitInfos()) 131 { 132 final EntityManagerFactory emf = entityManagerSource.getEntityManagerFactory(info.getPersistenceUnitName()); 133 134 final Metamodel metamodel = emf.getMetamodel(); 135 136 for (final EntityType<?> entity : metamodel.getEntities()) 137 { 138 final Class<?> javaType = entity.getJavaType(); 139 140 final ValueEncoderFactory factory = new ValueEncoderFactory() 141 { 142 public ValueEncoder create(final Class type) 143 { 144 return new JpaValueEncoder(entity, entityManagerManager, info.getPersistenceUnitName(), 145 propertyAccess, typeCoercer, loggerSource.getLogger(javaType)); 146 } 147 }; 148 149 configuration.add(javaType, factory); 150 } 151 } 152 } 153 154 @Contribute(ApplicationStateManager.class) 155 public static void provideApplicationStateContributions( 156 final MappedConfiguration<Class, ApplicationStateContribution> configuration, 157 final EntityManagerSource entityManagerSource, 158 @Symbol(JpaSymbols.ENTITY_SESSION_STATE_PERSISTENCE_STRATEGY_ENABLED) 159 final boolean entitySessionStatePersistenceStrategyEnabled) 160 { 161 162 if (!entitySessionStatePersistenceStrategyEnabled) 163 return; 164 165 for (final PersistenceUnitInfo info : entityManagerSource.getPersistenceUnitInfos()) 166 { 167 final EntityManagerFactory emf = entityManagerSource.getEntityManagerFactory(info.getPersistenceUnitName()); 168 169 final Metamodel metamodel = emf.getMetamodel(); 170 171 for (EntityType<?> entity : metamodel.getEntities()) 172 { 173 configuration.add(entity.getJavaType(), new ApplicationStateContribution(JpaPersistenceConstants.ENTITY)); 174 } 175 176 } 177 } 178 179 @Startup 180 public static void startupEarly(final EntityManagerManager entityManagerManager, @Symbol(JpaSymbols.EARLY_START_UP) 181 final boolean earlyStartup) 182 { 183 if (!earlyStartup) 184 return; 185 186 entityManagerManager.getEntityManagers(); 187 188 } 189 }