001 // Copyright 2008, 2009, 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.hibernate;
016
017 import org.apache.tapestry5.internal.hibernate.*;
018 import org.apache.tapestry5.ioc.MappedConfiguration;
019 import org.apache.tapestry5.ioc.OrderedConfiguration;
020 import org.apache.tapestry5.ioc.ScopeConstants;
021 import org.apache.tapestry5.ioc.ServiceBinder;
022 import org.apache.tapestry5.ioc.annotations.Local;
023 import org.apache.tapestry5.ioc.annotations.Marker;
024 import org.apache.tapestry5.ioc.annotations.Scope;
025 import org.apache.tapestry5.ioc.annotations.Symbol;
026 import org.apache.tapestry5.ioc.services.PerthreadManager;
027 import org.apache.tapestry5.ioc.services.PropertyShadowBuilder;
028 import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
029 import org.hibernate.Session;
030 import org.slf4j.Logger;
031
032 import java.util.Collection;
033 import java.util.List;
034
035 /**
036 * Defines core services that support initialization of Hibernate and access to the Hibernate {@link
037 * org.hibernate.Session}.
038 */
039 @SuppressWarnings({"JavaDoc"})
040 @Marker(HibernateCore.class)
041 public class HibernateCoreModule
042 {
043 public static void bind(ServiceBinder binder)
044 {
045 binder.bind(HibernateTransactionDecorator.class, HibernateTransactionDecoratorImpl.class);
046 binder.bind(HibernateTransactionAdvisor.class, HibernateTransactionAdvisorImpl.class);
047 binder.bind(HibernateConfigurer.class, DefaultHibernateConfigurer.class).withSimpleId();
048 binder.bind(HibernateSessionSource.class, HibernateSessionSourceImpl.class);
049 }
050
051
052 public static void contributeFactoryDefaults(MappedConfiguration<String, String> configuration)
053 {
054 configuration.add(HibernateSymbols.DEFAULT_CONFIGURATION, "true");
055 configuration.add(HibernateSymbols.EARLY_START_UP, "false");
056 }
057
058 public static void contributeRegistryStartup(OrderedConfiguration<Runnable> configuration,
059
060 @Symbol(HibernateSymbols.EARLY_START_UP)
061 final boolean earlyStartup,
062
063 final HibernateSessionSource sessionSource)
064 {
065 configuration.add("HibernateStartup", new Runnable()
066 {
067 public void run()
068 {
069 if (earlyStartup)
070 sessionSource.getConfiguration();
071 }
072 });
073 }
074
075 public static HibernateEntityPackageManager buildHibernateEntityPackageManager(
076 final Collection<String> packageNames)
077 {
078 return new HibernateEntityPackageManager()
079 {
080 public Collection<String> getPackageNames()
081 {
082 return packageNames;
083 }
084 };
085 }
086
087 /**
088 * The session manager manages sessions on a per-thread/per-request basis. Any active transaction will be rolled
089 * back at {@linkplain org.apache.tapestry5.ioc.Registry#cleanupThread() thread cleanup time}. The thread is
090 * cleaned up automatically in a Tapestry web application.
091 */
092 @Scope(ScopeConstants.PERTHREAD)
093 public static HibernateSessionManager buildHibernateSessionManager(HibernateSessionSource sessionSource,
094 PerthreadManager perthreadManager)
095 {
096 HibernateSessionManagerImpl service = new HibernateSessionManagerImpl(sessionSource);
097
098 perthreadManager.addThreadCleanupListener(service);
099
100 return service;
101 }
102
103 public static Session buildSession(HibernateSessionManager sessionManager,
104 PropertyShadowBuilder propertyShadowBuilder)
105 {
106 // Here's the thing: the tapestry.hibernate.Session class doesn't have to be per-thread,
107 // since
108 // it will invoke getSession() on the HibernateSessionManager service (which is per-thread).
109 // On
110 // first invocation per request,
111 // this forces the HSM into existence (which creates the session and begins the
112 // transaction).
113 // Thus we don't actually create
114 // a session until we first try to access it, then the session continues to exist for the
115 // rest
116 // of the request.
117
118 return propertyShadowBuilder.build(sessionManager, "session", Session.class);
119 }
120
121 /**
122 * Adds the following configurers: <dl> <dt>Default <dd> performs default hibernate configuration <dt>PackageName
123 * <dd> loads entities by package name</dl>
124 */
125 public static void contributeHibernateSessionSource(OrderedConfiguration<HibernateConfigurer> config,
126
127 @Local
128 HibernateConfigurer defaultHibernateConfigurer)
129 {
130 config.add("Default", defaultHibernateConfigurer);
131 config.addInstance("PackageName", PackageNameHibernateConfigurer.class);
132 }
133 }