/**
* Copyright (C) 2015 Orange
* 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 com.francetelecom.clara.cloud;
import com.francetelecom.clara.cloud.commons.ValidatorUtil;
import com.francetelecom.clara.cloud.commons.xstream.XStreamUtils;
import com.francetelecom.clara.cloud.logicalmodel.LogicalDeployment;
import com.thoughtworks.xstream.XStream;
import org.apache.commons.io.output.NullWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
/**
* Utility to add persistence to tests that don't have some. This is designed so be instanciated by Junit tests that already have a persistence context declared
* (None is provided as part of cloud-commons module test jar)
*/
public class PersistenceTestUtil {
private static Logger logger = LoggerFactory.getLogger(PersistenceTestUtil.class.getName());
@PersistenceContext
EntityManager em;
/**
* Executes the given Runnable on the current thread within a new Transational context
*/
@Transactional
public void executeWithinTransaction(Runnable runnable) {
runnable.run();
}
@Transactional
public void persistObject(Object object) {
persistObject(object, false);
}
@Transactional
public void mergeObject(Object o) {
em.merge(o);
}
private void persistObject(Object object, boolean skipFlush) {
// //First force its JSR 303 model validation to have meaningful exceptions if invalid
ValidatorUtil.validate(object);
// Then persist with JPA.
try {
em.persist(object);
if (!skipFlush) {
em.flush();
}
} catch (ConstraintViolationException e) {
for (ConstraintViolation<?> constraintViolation : e.getConstraintViolations()) {
logger.error(constraintViolation.getRootBeanClass() + " " + constraintViolation.getPropertyPath() + " " + constraintViolation.getMessage()
+ " " + constraintViolation.getRootBean() + ", invalid value: [" + constraintViolation.getInvalidValue() + "]");
}
throw e;
}
}
/**
* Generic persistent eager loading of an object
*/
@Transactional
public <T> T reloadEntity(Class<T> classType, Object objectId) {
T reloadedEntity = em.find(classType, objectId);
if (reloadedEntity != null) {
forceEagerFetching(reloadedEntity);
}
return reloadedEntity;
}
@Transactional
public LogicalDeployment reloadLogicalDeployment(LogicalDeployment logicalDeployment) {
return reloadEntity(LogicalDeployment.class, logicalDeployment.getId());
}
private static void forceEagerFetching(Object entity) {
XStream xStream = XStreamUtils.instanciateXstreamForHibernate();
if (logger.isDebugEnabled()) {
String xmlDump = xStream.toXML(entity);
logger.debug("Xml dump:" + xmlDump);
} else {
// dump to equivalent of /dev/null
xStream.toXML(entity, NullWriter.NULL_WRITER);
}
}
/**
* Utility method to delete an object, try to reload it, and return the expected null returned version
*/
@Transactional
public LogicalDeployment deleteObject(LogicalDeployment springooLogicalModel) {
LogicalDeployment reloadedLd = reloadLogicalDeployment(springooLogicalModel);
em.remove(reloadedLd);
reloadedLd = reloadLogicalDeployment(springooLogicalModel);
return reloadedLd;
}
}