    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    }