package org.activityinfo.server.database.hibernate; /* * #%L * ActivityInfo Server * %% * Copyright (C) 2009 - 2013 UNICEF * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.google.common.collect.Maps; import com.google.inject.Key; import com.google.inject.OutOfScopeException; import com.google.inject.Provider; import com.google.inject.Scope; import javax.persistence.EntityManager; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import static com.google.common.base.Preconditions.checkState; /** * Custom scope for the Hibernate session. * <p/> * <p/> * This scope is used to ensure that each request gets its own EntityManager * (see {@link HibernateSessionFilter}. However, it is provided separately from @RequestScope * because EntityManger's are also needed during batch processing. */ public class HibernateSessionScope implements Scope { private static final Logger LOGGER = Logger.getLogger(HibernateSessionScope.class.getName()); private final ThreadLocal<Map<Key<?>, Object>> values = new ThreadLocal<Map<Key<?>, Object>>(); public void enter() { checkState(values.get() == null, "A hibernate session block is already in progress"); values.set(Maps.<Key<?>, Object>newHashMap()); } public void exit() { checkState(values.get() != null, "No hibernate session block in progress"); // close session try { if (values.get().containsKey(Key.get(EntityManager.class))) { EntityManager em = (EntityManager) values.get().get(Key.get(EntityManager.class)); em.close(); } } catch (Exception caught) { LOGGER.log(Level.SEVERE, "Error closing connection", caught); } finally { values.remove(); } } @Override public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) { return new Provider<T>() { @Override public T get() { Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key); @SuppressWarnings("unchecked") T current = (T) scopedObjects.get(key); if (current == null && !scopedObjects.containsKey(key)) { current = unscoped.get(); scopedObjects.put(key, current); } return current; } }; } private <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) { Map<Key<?>, Object> scopedObjects = values.get(); if (scopedObjects == null) { throw new OutOfScopeException("Cannot access " + key + " outside of a hibernate session block"); } return scopedObjects; } }