/**
* GRANITE DATA SERVICES
* Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S.
*
* This file is part of the Granite Data Services Platform.
*
* Granite Data Services is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Granite Data Services 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 Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA, or see <http://www.gnu.org/licenses/>.
*/
package org.granite.tide.cdi.lazy;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.el.ELResolver;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import org.granite.logging.Logger;
import org.granite.tide.TidePersistenceManager;
import org.granite.tide.cdi.PersistenceConfiguration;
import org.granite.tide.data.DataMergeContext;
import org.granite.tide.data.JPAPersistenceManager;
@ConversationScoped
public class CDIInitializer implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(CDIInitializer.class);
private transient TidePersistenceManager pm = null;
private Set<Object> loadedEntities = new HashSet<Object>();
@Inject
private BeanManager manager;
@Inject @Any
private Instance<TidePersistenceManager> persistenceManagers;
@Inject @Any
private Instance<EntityManager> entityManagers;
@Inject
private PersistenceConfiguration persistenceConfiguration;
/**
* Initiliazes the property for the passed in entity. It is attached to an associated context
* and then the property is accessed.
* @return Returns result from initializing the property.
*/
public Object lazyInitialize(Object entity, String[] propertyNames) {
if (entity instanceof String) {
String expression = "${" + entity + "}";
ELResolver elResolver = manager.getELResolver();
entity = elResolver.getValue(null, expression, null);
}
if (pm == null) {
pm = getPersistenceManager();
if (pm == null)
throw new RuntimeException("TideInitializer is null, Entities with lazy relationships have to be retrieved in a conversation");
}
return pm.attachEntity(entity, propertyNames);
}
/**
* Try to determine what type of persistence the application is using.
* If the EntityManager is stored under entityManager or if the Hibernate session is
* stored under session. Then the context will be found and used. This is only called if a
* ITidePersistenceManager is not found, probably because the query was not run in a conversation.
* @return The appropriate manager for the persistence context being used, if it can be determined
* otherwise a null is returned.
*/
public TidePersistenceManager getPersistenceManager() {
try {
if (persistenceManagers != null && !persistenceManagers.isUnsatisfied()) {
if (persistenceManagers.isAmbiguous()) {
log.error("The application defines more than one TidePersistenceManager, please define only one to be used for Tide lazy loading");
return null;
}
return persistenceManagers.get();
}
InitialContext ic = new InitialContext();
if (persistenceConfiguration.getEntityManagerFactoryJndiName() != null) {
EntityManagerFactory emf = (EntityManagerFactory)ic.lookup(persistenceConfiguration.getEntityManagerFactoryJndiName());
return new JPAPersistenceManager(emf);
}
else if (persistenceConfiguration.getEntityManagerJndiName() != null) {
EntityManager em = (EntityManager)ic.lookup(persistenceConfiguration.getEntityManagerJndiName());
return new JPAPersistenceManager(em);
}
else if (entityManagers != null) {
// Try with injected EntityManager defined as Resource
Iterator<EntityManager> iem = entityManagers.iterator();
EntityManager em = iem.hasNext() ? iem.next() : null;
if (em == null || iem.hasNext()) {
log.warn("The application defines zero or more than one Persistence Unit, please define which one should be used for lazy loading in entity-manager-jndi-name");
return null;
}
return new JPAPersistenceManager(em);
}
}
catch (Exception e) {
log.error(e, "Could not get EntityManager");
}
return null;
}
public void restoreLoadedEntities() {
DataMergeContext.restoreLoadedEntities(loadedEntities);
}
public void saveLoadedEntities() {
for (Object entity : DataMergeContext.getLoadedEntities())
loadedEntities.add(entity);
}
}