/**
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jbpm.process.audit;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import org.jbpm.process.audit.strategy.PersistenceStrategy;
import org.jbpm.process.audit.strategy.PersistenceStrategyType;
import org.jbpm.process.audit.strategy.StandaloneJtaStrategy;
import org.jbpm.process.audit.strategy.StandaloneLocalStrategy;
import org.kie.api.runtime.Environment;
import org.kie.api.runtime.EnvironmentName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* </p>
* The idea here is that we have a entity manager factory (similar to a session
* factory) that we repeatedly use to generate an entity manager (which is a
* persistence context) for the specific service command.
* </p>
* To start with, not all of our entities contain LOB's ("Large Objects" see
* https://en.wikibooks.org/wiki/Java_Persistence/Basic_Attributes#LOBs.2C_BLOBs
* .2C_CLOBs_and_Serialization) which sometimes necessitate the use of tx's even
* in <i>read</i> situations.
* </p>
* However, we use transactions here none-the-less, just to be safe. Obviously,
* if there is already a running transaction present, we don't do anything to
* it.
* </p>
* At the end of every command or operation, make sure to close the entity
* manager you've been using -- which also means that you should detach any
* entities that might be associated with the entity manager/persistence
* context.
* </p>
* After all, this is a <i>service</i> which means our philosophy here is to
* provide a real interface, and not a leaky absraction.
* (https://en.wikipedia.org/wiki/Leaky_abstraction)
*/
public class JPAService {
private static final Logger logger = LoggerFactory.getLogger(JPAService.class);
protected PersistenceStrategy persistenceStrategy;
protected String persistenceUnitName;
public JPAService(String persistenceUnitName) {
this.persistenceUnitName = persistenceUnitName;
EntityManagerFactory emf = null;
try {
emf = Persistence.createEntityManagerFactory(persistenceUnitName);
} catch (Exception e) {
logger.info("The '" + persistenceUnitName
+ "' peristence unit is not available, no persistence strategy set for "
+ this.getClass().getSimpleName());
}
if (emf != null) {
persistenceStrategy = new StandaloneJtaStrategy(emf);
}
}
public JPAService(Environment env, PersistenceStrategyType type) {
persistenceStrategy = PersistenceStrategyType.getPersistenceStrategy(type, env);
}
public JPAService(Environment env, String persistenceUnitName) {
EntityManagerFactory emf = (EntityManagerFactory) env.get(EnvironmentName.ENTITY_MANAGER_FACTORY);
String localTransactions = (String) env.get(EnvironmentName.USE_LOCAL_TRANSACTIONS);
if (emf != null) {
if (localTransactions != null) {
if (localTransactions.equals("true")) {
persistenceStrategy = new StandaloneLocalStrategy(emf);
}
} else {
persistenceStrategy = new StandaloneJtaStrategy(emf);
}
} else {
if (localTransactions != null) {
if (localTransactions.equals("true")) {
persistenceStrategy = new StandaloneLocalStrategy(
Persistence.createEntityManagerFactory(persistenceUnitName));
}
} else {
persistenceStrategy = new StandaloneJtaStrategy(
Persistence.createEntityManagerFactory(persistenceUnitName));
}
}
}
public JPAService(EntityManagerFactory emf) {
persistenceStrategy = new StandaloneJtaStrategy(emf);
}
public JPAService(EntityManagerFactory emf, PersistenceStrategyType type) {
persistenceStrategy = PersistenceStrategyType.getPersistenceStrategy(type, emf);
}
public void setPersistenceUnitName(String persistenceUnitName) {
persistenceStrategy = new StandaloneJtaStrategy(Persistence.createEntityManagerFactory(persistenceUnitName));
this.persistenceUnitName = persistenceUnitName;
}
public String getPersistenceUnitName() {
return persistenceUnitName;
}
public void dispose() {
persistenceStrategy.dispose();
}
// DO NOT MAKE THIS METHOD PUBLIC!
// This is an internal method, and we do NOT want to expose the entity
// manager to users or other logic!
protected EntityManager getEntityManager() {
return persistenceStrategy.getEntityManager();
}
// DO NOT MAKE THIS METHOD PUBLIC!
// This is an internal method, and we do NOT want to expose the entity
// manager to users or other logic!
protected Object joinTransaction(EntityManager em) {
return persistenceStrategy.joinTransaction(em);
}
// DO NOT MAKE THIS METHOD PUBLIC!
// This is an internal method, and we do NOT want to expose the entity
// manager to users or other logic!
protected void closeEntityManager(EntityManager em, Object transaction) {
persistenceStrategy.leaveTransaction(em, transaction);
}
public <T> List<T> executeQuery(Query query, EntityManager em, Class<T> type) {
Object newTx = joinTransaction(em);
List<T> result;
try {
result = query.getResultList();
} finally {
closeEntityManager(em, newTx);
}
return result;
}
}