package org.javaee7.jpa.locking.optimistic;
import static java.lang.Thread.sleep;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.enterprise.concurrent.ManagedExecutorService;
import javax.inject.Inject;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.descriptor.api.Descriptors;
import org.jboss.shrinkwrap.descriptor.api.beans10.BeansDescriptor;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* @author Roberto Cortez
*/
@RunWith(Arquillian.class)
public class LockingOptimisticTest {
@Inject
private MovieBean movieBean;
@Resource
private ManagedExecutorService executor;
@Deployment
public static WebArchive createDeployment() {
BeansDescriptor beansXml = Descriptors.create(BeansDescriptor.class);
WebArchive war = ShrinkWrap.create(WebArchive.class)
.addPackage("org.javaee7.jpa.locking.optimistic")
.addAsResource("META-INF/persistence.xml")
.addAsResource("META-INF/load.sql")
.addAsWebInfResource(
new StringAsset(beansXml.getOrCreateAlternatives()
.clazz(MovieBeanAlternative.class.getName()).up().exportAsString()),
beansXml.getDescriptorName());
System.out.println(war.toString(true));
return war;
}
@Test
public void testLockingOptimisticUpdateAndRead() throws Exception {
System.out.println("Enter testLockingOptimisticUpdateAndRead");
resetCountDownLatches();
List<Movie> movies = movieBean.listMovies();
assertFalse(movies.isEmpty());
final CountDownLatch testCountDownLatch = new CountDownLatch(1);
executor.execute(new Runnable() {
@Override
public void run() {
movieBean.updateMovie(3, "INCEPTION UR");
testCountDownLatch.countDown();
}
});
executor.execute(new Runnable() {
@Override
public void run() {
movieBean.findMovie(3);
MovieBeanAlternative.lockCountDownLatch.countDown();
}
});
assertTrue(testCountDownLatch.await(10, SECONDS));
assertEquals("INCEPTION UR", movieBean.findMovie(3).getName());
}
@Test
public void testLockingOptimisticReadAndUpdate() throws Exception {
System.out.println("Enter testLockingOptimisticReadAndUpdate");
resetCountDownLatches();
List<Movie> movies = movieBean.listMovies();
assertFalse(movies.isEmpty());
final CountDownLatch testCountDownLatch = new CountDownLatch(1);
executor.execute(new Runnable() {
@Override
public void run() {
try {
movieBean.readMovie(3);
} catch (RuntimeException e) { // Should throw an javax.persistence.OptimisticLockException? Hibernate is throwing org.hibernate.OptimisticLockException. Investigate!
testCountDownLatch.countDown();
}
}
});
executor.execute(new Runnable() {
@Override
public void run() {
MovieBeanAlternative.lockCountDownLatch.countDown();
movieBean.updateMovie(3, "INCEPTION RU");
MovieBeanAlternative.readCountDownLatch.countDown();
}
});
assertTrue(testCountDownLatch.await(10, TimeUnit.SECONDS));
assertEquals("INCEPTION RU", movieBean.findMovie(3).getName());
}
@Test
public void testLockingOptimisticDelete() throws Exception {
System.out.println("Enter testLockingOptimisticDelete");
resetCountDownLatches();
List<Movie> movies = movieBean.listMovies();
assertFalse(movies.isEmpty());
final CountDownLatch testCountDownLatch1 = new CountDownLatch(1);
final CountDownLatch testCountDownLatch2 = new CountDownLatch(1);
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println("Update thread " + Thread.currentThread().getId() + " at " + System.nanoTime());
try {
testCountDownLatch1.countDown();
movieBean.updateMovie2(3, "INCEPTION");
} catch (RuntimeException e) { // Should throw an javax.persistence.OptimisticLockException? The Exception is wrapped around an javax.ejb.EJBException
testCountDownLatch2.countDown();
}
}
});
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println("Delete thread " + Thread.currentThread().getId() + " at " + System.nanoTime());
try {
testCountDownLatch1.await(10, SECONDS);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
movieBean.deleteMovie(3);
MovieBeanAlternative.lockCountDownLatch.countDown();
}
});
assertTrue(testCountDownLatch2.await(20, SECONDS));
}
private void resetCountDownLatches() {
MovieBeanAlternative.lockCountDownLatch = new CountDownLatch(1);
MovieBeanAlternative.readCountDownLatch = new CountDownLatch(1);
}
}