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    }