/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library 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.
*
* This library 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.
*/
package com.liferay.portal.dao.orm.hibernate.event;
import com.liferay.portal.dao.orm.hibernate.SessionFactoryImpl;
import com.liferay.portal.dao.orm.hibernate.VerifySessionFactoryWrapper;
import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
import com.liferay.portal.kernel.model.CacheModel;
import com.liferay.portal.kernel.model.ClassName;
import com.liferay.portal.kernel.test.ReflectionTestUtil;
import com.liferay.portal.kernel.test.rule.AggregateTestRule;
import com.liferay.portal.kernel.test.rule.DeleteAfterTestRun;
import com.liferay.portal.kernel.test.util.RandomTestUtil;
import com.liferay.portal.model.impl.ClassNameImpl;
import com.liferay.portal.test.rule.LiferayIntegrationTestRule;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.hibernate.EmptyInterceptor;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;
import org.hibernate.event.AutoFlushEventListener;
import org.hibernate.event.EventListeners;
import org.hibernate.event.FlushEventListener;
import org.hibernate.event.def.DefaultAutoFlushEventListener;
import org.hibernate.event.def.DefaultFlushEventListener;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
/**
* @author Matthew Tambara
*/
public class NestableFlushEventListenerTest {
@ClassRule
@Rule
public static final AggregateTestRule aggregateTestRule =
new LiferayIntegrationTestRule();
@BeforeClass
public static void setUpClass() {
SessionFactoryImpl sessionFactoryImpl = null;
Object liferaySessionFactory = PortalBeanLocatorUtil.locate(
"liferaySessionFactory");
if (liferaySessionFactory instanceof VerifySessionFactoryWrapper) {
sessionFactoryImpl = ReflectionTestUtil.getFieldValue(
liferaySessionFactory, "_sessionFactoryImpl");
}
else {
sessionFactoryImpl = (SessionFactoryImpl)liferaySessionFactory;
}
_sessionFactoryImpl =
(org.hibernate.impl.SessionFactoryImpl)
sessionFactoryImpl.getSessionFactoryImplementor();
}
@Before
public void setUp() throws Exception {
Session session = _sessionFactoryImpl.openSession();
Query query = session.createQuery(
"SELECT className FROM ClassName className");
List<ClassName> classNames = query.list();
session.close();
_assignKeys(classNames, _keys);
_assignValues(classNames, _values);
}
@Test
public void testDefaultAutoFlushEventListener() throws Exception {
EventListeners eventListeners = _sessionFactoryImpl.getEventListeners();
AutoFlushEventListener[] autoFlushEventListeners =
eventListeners.getAutoFlushEventListeners();
eventListeners.setAutoFlushEventListeners(
new AutoFlushEventListener[] {new DefaultAutoFlushEventListener()});
try {
testNestableAutoFlushEventListener();
Assert.fail();
}
catch (IndexOutOfBoundsException ioobe) {
}
finally {
eventListeners.setAutoFlushEventListeners(autoFlushEventListeners);
}
}
@Test
public void testDefaultFlushEventListener() throws Exception {
EventListeners eventListeners = _sessionFactoryImpl.getEventListeners();
FlushEventListener[] flushEventListeners =
eventListeners.getFlushEventListeners();
eventListeners.setFlushEventListeners(
new FlushEventListener[] {new DefaultFlushEventListener()});
try {
testNestableFlushEventListener();
Assert.fail();
}
catch (IndexOutOfBoundsException ioobe) {
}
finally {
eventListeners.setFlushEventListeners(flushEventListeners);
}
}
@Test
public void testNestableAutoFlushEventListener() throws Exception {
Session session = _prepareSession();
Transaction transaction = session.beginTransaction();
try {
session.merge(_className1);
session.merge(_className2);
Query query = session.createQuery(
"SELECT className FROM ClassName className");
List<?> results = query.list();
Assert.assertFalse(results.isEmpty());
}
finally {
transaction.commit();
}
session.close();
}
@Test
public void testNestableFlushEventListener() throws Exception {
Session session = _prepareSession();
Transaction transaction = session.beginTransaction();
try {
session.merge(_className1);
session.merge(_className2);
session.flush();
}
finally {
transaction.commit();
}
session.close();
}
private void _assignKeys(List<ClassName> classNames, long[] keys)
throws Exception {
Stream<ClassName> classNameStream = classNames.stream();
Stream<Long> classNameIdStream = classNameStream.map(
ClassName::getClassNameId);
List<Long> classNameIds = classNameIdStream.collect(
Collectors.toList());
for (int i = 0; i < keys.length; i++) {
long key = RandomTestUtil.nextLong();
if (!classNameIds.contains(key)) {
classNameIds.add(key);
keys[i] = key;
}
}
}
private void _assignValues(List<ClassName> classNames, String[] values)
throws Exception {
Stream<ClassName> classNameStream = classNames.stream();
Stream<String> classNameValueStream = classNameStream.map(
ClassName::getValue);
List<String> classNameValues = classNameValueStream.collect(
Collectors.toList());
for (int i = 0; i < values.length; i++) {
String value = RandomTestUtil.randomString();
if (!classNameValues.contains(value)) {
classNameValues.add(value);
values[i] = value;
}
}
}
private Session _prepareSession() throws Exception {
Session session = _sessionFactoryImpl.openSession(
new EmptyInterceptor() {
@Override
public String getEntityName(Object object) {
if (object instanceof TestClassNameImpl) {
return ClassNameImpl.class.getName();
}
return super.getEntityName(object);
}
});
Transaction transaction = session.beginTransaction();
try {
_className1 = new TestClassNameImpl(session);
_className1.setPrimaryKey(_keys[0]);
_className1.setValue(_values[0]);
session.save(_className1);
_className2 = new ClassNameImpl();
_className2.setPrimaryKey(_keys[1]);
_className2.setValue(_values[1]);
session.save(_className2);
}
finally {
transaction.commit();
}
_className1.setValue(_values[2]);
_className1.setMvccVersion(_className1.getMvccVersion() + 1);
_className2.setValue(_values[3]);
_className2.setMvccVersion(_className1.getMvccVersion() + 1);
return session;
}
private static org.hibernate.impl.SessionFactoryImpl _sessionFactoryImpl;
@DeleteAfterTestRun
private ClassName _className1;
@DeleteAfterTestRun
private ClassName _className2;
private final long[] _keys = new long[2];
private final String[] _values = new String[4];
private class TestClassNameImpl extends ClassNameImpl {
@Override
public CacheModel<ClassName> toCacheModel() {
Query query = _session.createQuery(
"SELECT release FROM Release release");
List<?> results = query.list();
Assert.assertFalse(results.isEmpty());
return super.toCacheModel();
}
private TestClassNameImpl(Session session) {
_session = session;
}
private final Session _session;
}
}