// $HeadURL$
// $Id$
//
// Copyright © 2010 by the President and Fellows of Harvard College.
//
// Screensaver is an open-source project developed by the ICCB-L and NSRB labs
// at Harvard Medical School. This software is distributed under the terms of
// the GNU General Public License.
package org.hibernate.ejb;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceUnitInfo;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.hibernate.event.EventListeners;
import org.hibernate.event.MergeEventListener;
import org.hibernate.event.PersistEventListener;
import org.hibernate.event.PostLoadEventListener;
import org.hibernate.event.SaveOrUpdateEventListener;
/**
* A replacement for the HibernatePersistence class that allows <i>additional</i> Hibernate event listeners to be
* specified as instantiated objects, allowing the listener objects to be Spring-instantiated beans. This allows the
* specified listeners to take advantage of dependency injection, rather than just being instantiated via default
* constructors, as HibernatePersistence would otherwise do. The default Hibernate listeners will be maintained, and the
* specified listeners will be appended to the list of listeners of the given type.
* <p/>
* To use this class in a Spring context XML configuration file:
*
* <pre>
* <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
* <property name="persistenceProvider">
* <bean class="org.hibernate.ejb.ConfigurableListenerBeansHibernatePersistence">
* <property name="postLoadEventListeners">
* <list>
* <bean class="my.application.MyPostLoadEventListener1" />
* <bean class="my.application.MyPostLoadEventListener2" />
* </list>
* </property>
* </bean>
* </property>
* ...
* <property name="jpaPropertyMap">...</property>
* </bean>
* </pre>
*
* @author atolopko
*/
// TODO: add support for all Hibernate event types
public class ConfigurableListenerBeansHibernatePersistence extends HibernatePersistence
{
@Override
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties)
{
Ejb3Configuration cfg = new Ejb3Configuration();
Ejb3Configuration configured = cfg.configure(info, properties);
if (configured != null) {
configureListeners(configured);
return configured.buildEntityManagerFactory();
}
return null;
}
private List<PostLoadEventListener> _postLoadEventListeners;
private List<SaveOrUpdateEventListener> _saveOrUpdateEventListeners;
private List<PersistEventListener> _persistEventListeners;
private List<MergeEventListener> _mergeEventListeners;
public List<PostLoadEventListener> getPostLoadEventListeners()
{
return _postLoadEventListeners;
}
public void setPostLoadEventListeners(List<PostLoadEventListener> postLoadEventListeners)
{
_postLoadEventListeners = postLoadEventListeners;
}
public List<PersistEventListener> getPersistEventListeners()
{
return _persistEventListeners;
}
public void setPersistEventListeners(List<PersistEventListener> persistEventListeners)
{
_persistEventListeners = persistEventListeners;
}
public List<MergeEventListener> getMergeEventListeners()
{
return _mergeEventListeners;
}
public void setMergeEventListeners(List<MergeEventListener> mergeEventListeners)
{
_mergeEventListeners = mergeEventListeners;
}
public List<SaveOrUpdateEventListener> getSaveOrUpdateEventListeners()
{
return _saveOrUpdateEventListeners;
}
public void setSaveOrUpdateEventListeners(List<SaveOrUpdateEventListener> saveOrUpdateEventListeners)
{
_saveOrUpdateEventListeners = saveOrUpdateEventListeners;
}
private void configureListeners(Ejb3Configuration cfg)
{
EventListeners eventListeners = cfg.getEventListeners();
cfg.setListeners("post-load", concatListeners(PostLoadEventListener.class, _postLoadEventListeners, eventListeners.getPostLoadEventListeners()));
cfg.setListeners("save-update", concatListeners(SaveOrUpdateEventListener.class, _saveOrUpdateEventListeners, eventListeners.getSaveOrUpdateEventListeners()));
cfg.setListeners("merge", concatListeners(MergeEventListener.class, _mergeEventListeners, eventListeners.getMergeEventListeners()));
cfg.setListeners("create", concatListeners(PersistEventListener.class, _persistEventListeners, eventListeners.getPersistEventListeners()));
// TODO: do we also need create-on-flush event?
}
public <L> L[] concatListeners(Class<L> listenerClass, List<L> eventListeners, L[] extantListeners)
{
if (eventListeners == null) {
eventListeners = Lists.newArrayList();
}
if (extantListeners == null) {
return Iterables.toArray(eventListeners, listenerClass);
}
return Iterables.toArray(Iterables.concat(Arrays.asList(extantListeners), eventListeners), listenerClass);
}
}