001// Copyright 2011-2014 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 015package org.apache.tapestry5.jpa.modules; 016 017import org.apache.tapestry5.ValueEncoder; 018import org.apache.tapestry5.internal.InternalConstants; 019import org.apache.tapestry5.internal.jpa.*; 020import org.apache.tapestry5.internal.services.PersistentFieldManager; 021import org.apache.tapestry5.ioc.*; 022import org.apache.tapestry5.ioc.annotations.*; 023import org.apache.tapestry5.ioc.services.*; 024import org.apache.tapestry5.jpa.*; 025import org.apache.tapestry5.services.*; 026import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; 027import org.slf4j.Logger; 028 029import javax.persistence.EntityManagerFactory; 030import javax.persistence.metamodel.EntityType; 031import javax.persistence.metamodel.Metamodel; 032import javax.persistence.spi.PersistenceUnitInfo; 033import java.util.Collection; 034 035/** 036 * Defines core services for JPA support. 037 * 038 * @since 5.3 039 */ 040public 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 @Override 054 public Collection<String> getPackageNames() 055 { 056 return packageNames; 057 } 058 }; 059 } 060 061 @Scope(ScopeConstants.PERTHREAD) 062 public static EntityManagerManager buildEntityManagerManager(final EntityManagerSource entityManagerSource, 063 final PerthreadManager perthreadManager, final Logger logger) 064 { 065 final EntityManagerManagerImpl service = new EntityManagerManagerImpl(entityManagerSource, logger); 066 067 perthreadManager.addThreadCleanupListener(service); 068 069 return service; 070 } 071 072 @Contribute(JpaEntityPackageManager.class) 073 public static void provideEntityPackages(Configuration<String> configuration, 074 075 @Symbol(InternalConstants.TAPESTRY_APP_PACKAGE_PARAM) 076 String appRootPackage) 077 { 078 configuration.add(appRootPackage + ".entities"); 079 } 080 081 @Contribute(PersistentFieldManager.class) 082 public static void provideEntityPersistentFieldStrategies( 083 final MappedConfiguration<String, PersistentFieldStrategy> configuration) 084 { 085 configuration.addInstance(JpaPersistenceConstants.ENTITY, EntityPersistentFieldStrategy.class); 086 } 087 088 @Contribute(ApplicationStatePersistenceStrategySource.class) 089 public void provideApplicationStatePersistenceStrategies( 090 final MappedConfiguration<String, ApplicationStatePersistenceStrategy> configuration) 091 { 092 configuration.addInstance(JpaPersistenceConstants.ENTITY, EntityApplicationStatePersistenceStrategy.class); 093 } 094 095 @Contribute(ComponentClassTransformWorker2.class) 096 @Primary 097 public static void provideClassTransformWorkers(OrderedConfiguration<ComponentClassTransformWorker2> configuration) 098 { 099 configuration.addInstance("PersistenceContext", PersistenceContextWorker.class, "after:Property"); 100 configuration.addInstance("JPACommitAfter", CommitAfterWorker.class, "after:Log"); 101 } 102 103 @Contribute(MasterObjectProvider.class) 104 public static void provideObjectProviders(final OrderedConfiguration<ObjectProvider> configuration) 105 { 106 configuration.addInstance("EntityManager", EntityManagerObjectProvider.class, 107 "before:AnnotationBasedContributions"); 108 } 109 110 @Contribute(SymbolProvider.class) 111 @FactoryDefaults 112 public static void provideFactoryDefaults(final MappedConfiguration<String, String> configuration) 113 { 114 configuration.add(JpaSymbols.PROVIDE_ENTITY_VALUE_ENCODERS, "true"); 115 configuration.add(JpaSymbols.EARLY_START_UP, "true"); 116 configuration.add(JpaSymbols.ENTITY_SESSION_STATE_PERSISTENCE_STRATEGY_ENABLED, "true"); 117 configuration.add(JpaSymbols.PERSISTENCE_DESCRIPTOR, "/META-INF/persistence.xml"); 118 } 119 120 @Contribute(ValueEncoderSource.class) 121 public static void provideValueEncoders(final MappedConfiguration<Class, ValueEncoderFactory> configuration, 122 @Symbol(JpaSymbols.PROVIDE_ENTITY_VALUE_ENCODERS) 123 final boolean provideEncoders, final EntityManagerSource entityManagerSource, 124 final EntityManagerManager entityManagerManager, final TypeCoercer typeCoercer, 125 final PropertyAccess propertyAccess, final LoggerSource loggerSource) 126 { 127 128 if (!provideEncoders) 129 return; 130 131 for (final PersistenceUnitInfo info : entityManagerSource.getPersistenceUnitInfos()) 132 { 133 final EntityManagerFactory emf = entityManagerSource.getEntityManagerFactory(info.getPersistenceUnitName()); 134 135 final Metamodel metamodel = emf.getMetamodel(); 136 137 for (final EntityType<?> entity : metamodel.getEntities()) 138 { 139 final Class<?> javaType = entity.getJavaType(); 140 141 final ValueEncoderFactory factory = new ValueEncoderFactory() 142 { 143 @Override 144 public ValueEncoder create(final Class type) 145 { 146 return new JpaValueEncoder(entity, entityManagerManager, info.getPersistenceUnitName(), 147 propertyAccess, typeCoercer, loggerSource.getLogger(javaType)); 148 } 149 }; 150 151 configuration.add(javaType, factory); 152 } 153 } 154 } 155 156 @Contribute(ApplicationStateManager.class) 157 public static void provideApplicationStateContributions( 158 final MappedConfiguration<Class, ApplicationStateContribution> configuration, 159 final EntityManagerSource entityManagerSource, 160 @Symbol(JpaSymbols.ENTITY_SESSION_STATE_PERSISTENCE_STRATEGY_ENABLED) 161 final boolean entitySessionStatePersistenceStrategyEnabled) 162 { 163 164 if (!entitySessionStatePersistenceStrategyEnabled) 165 return; 166 167 for (final PersistenceUnitInfo info : entityManagerSource.getPersistenceUnitInfos()) 168 { 169 final EntityManagerFactory emf = entityManagerSource.getEntityManagerFactory(info.getPersistenceUnitName()); 170 171 final Metamodel metamodel = emf.getMetamodel(); 172 173 for (EntityType<?> entity : metamodel.getEntities()) 174 { 175 configuration.add(entity.getJavaType(), new ApplicationStateContribution(JpaPersistenceConstants.ENTITY)); 176 } 177 178 } 179 } 180 181 @Startup 182 public static void startupEarly(final EntityManagerManager entityManagerManager, @Symbol(JpaSymbols.EARLY_START_UP) 183 final boolean earlyStartup) 184 { 185 if (earlyStartup) 186 { 187 entityManagerManager.getEntityManagers(); 188 } 189 } 190}