Skip to content

Commit 6e27fa2

Browse files
authored
Merge pull request javaee-samples#385 from arjantijms/master
Fixed LockingOptimisticTest
2 parents 7c64966 + 93f4711 commit 6e27fa2

3 files changed

Lines changed: 113 additions & 29 deletions

File tree

jpa/locking-optimistic/src/main/java/org/javaee7/jpa/locking/optimistic/MovieBean.java

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,22 @@
3939
*/
4040
package org.javaee7.jpa.locking.optimistic;
4141

42+
import static javax.ejb.TransactionAttributeType.REQUIRED;
43+
import static javax.persistence.LockModeType.OPTIMISTIC;
44+
45+
import java.util.List;
46+
4247
import javax.ejb.Stateless;
4348
import javax.ejb.TransactionAttribute;
44-
import javax.ejb.TransactionAttributeType;
4549
import javax.persistence.EntityManager;
46-
import javax.persistence.LockModeType;
4750
import javax.persistence.PersistenceContext;
48-
import java.util.List;
4951

5052
/**
5153
* @author Arun Gupta
5254
*/
5355
@Stateless
5456
public class MovieBean {
57+
5558
@PersistenceContext
5659
private EntityManager em;
5760

@@ -63,21 +66,37 @@ public Movie findMovie(Integer id) {
6366
return em.find(Movie.class, id);
6467
}
6568

66-
@TransactionAttribute(TransactionAttributeType.REQUIRED)
69+
@TransactionAttribute(REQUIRED)
6770
public Movie readMovie(Integer id) {
68-
return em.find(Movie.class, id, LockModeType.OPTIMISTIC);
71+
return em.find(Movie.class, id, OPTIMISTIC);
6972
}
7073

71-
@TransactionAttribute(TransactionAttributeType.REQUIRED)
74+
@TransactionAttribute(REQUIRED)
7275
public void updateMovie(Integer id, String name) {
7376
Movie movie = findMovie(id);
74-
em.lock(movie, LockModeType.OPTIMISTIC);
77+
em.lock(movie, OPTIMISTIC);
78+
movie.setName(name);
79+
em.merge(movie);
80+
em.flush();
81+
}
82+
83+
public void updateMovie2(Integer id, String name) {
84+
Movie movie = findMovie(id);
85+
em.lock(movie, OPTIMISTIC);
86+
movie.setName(name);
87+
em.merge(movie);
88+
em.flush();
89+
}
90+
91+
@TransactionAttribute(REQUIRED)
92+
public void updateMovie(Movie movie, String name) {
93+
em.lock(movie, OPTIMISTIC);
7594
movie.setName(name);
7695
em.merge(movie);
7796
em.flush();
7897
}
7998

80-
@TransactionAttribute(TransactionAttributeType.REQUIRED)
99+
@TransactionAttribute(REQUIRED)
81100
public void deleteMovie(Integer id) {
82101
em.remove(findMovie(id));
83102
}

jpa/locking-optimistic/src/test/java/org/javaee7/jpa/locking/optimistic/LockingOptimisticTest.java

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
package org.javaee7.jpa.locking.optimistic;
22

3+
import static java.lang.Thread.sleep;
4+
import static java.util.concurrent.TimeUnit.SECONDS;
5+
import static org.junit.Assert.assertEquals;
6+
import static org.junit.Assert.assertFalse;
7+
import static org.junit.Assert.assertTrue;
8+
9+
import java.util.List;
10+
import java.util.concurrent.CountDownLatch;
11+
import java.util.concurrent.TimeUnit;
12+
13+
import javax.annotation.Resource;
14+
import javax.enterprise.concurrent.ManagedExecutorService;
15+
import javax.inject.Inject;
16+
317
import org.jboss.arquillian.container.test.api.Deployment;
418
import org.jboss.arquillian.junit.Arquillian;
519
import org.jboss.shrinkwrap.api.ShrinkWrap;
@@ -10,25 +24,17 @@
1024
import org.junit.Test;
1125
import org.junit.runner.RunWith;
1226

13-
import javax.annotation.Resource;
14-
import javax.enterprise.concurrent.ManagedScheduledExecutorService;
15-
import javax.inject.Inject;
16-
import java.util.List;
17-
import java.util.concurrent.CountDownLatch;
18-
import java.util.concurrent.TimeUnit;
19-
20-
import static org.junit.Assert.*;
21-
2227
/**
2328
* @author Roberto Cortez
2429
*/
2530
@RunWith(Arquillian.class)
2631
public class LockingOptimisticTest {
32+
2733
@Inject
2834
private MovieBean movieBean;
2935

3036
@Resource
31-
private ManagedScheduledExecutorService executor;
37+
private ManagedExecutorService executor;
3238

3339
@Deployment
3440
public static WebArchive createDeployment() {
@@ -42,12 +48,17 @@ public static WebArchive createDeployment() {
4248
new StringAsset(beansXml.getOrCreateAlternatives()
4349
.clazz(MovieBeanAlternative.class.getName()).up().exportAsString()),
4450
beansXml.getDescriptorName());
51+
4552
System.out.println(war.toString(true));
53+
4654
return war;
4755
}
4856

4957
@Test
5058
public void testLockingOptimisticUpdateAndRead() throws Exception {
59+
60+
System.out.println("Enter testLockingOptimisticUpdateAndRead");
61+
5162
resetCountDownLatches();
5263
List<Movie> movies = movieBean.listMovies();
5364
assertFalse(movies.isEmpty());
@@ -70,12 +81,15 @@ public void run() {
7081
}
7182
});
7283

73-
assertTrue(testCountDownLatch.await(10, TimeUnit.SECONDS));
84+
assertTrue(testCountDownLatch.await(10, SECONDS));
7485
assertEquals("INCEPTION UR", movieBean.findMovie(3).getName());
7586
}
7687

7788
@Test
7889
public void testLockingOptimisticReadAndUpdate() throws Exception {
90+
91+
System.out.println("Enter testLockingOptimisticReadAndUpdate");
92+
7993
resetCountDownLatches();
8094
List<Movie> movies = movieBean.listMovies();
8195
assertFalse(movies.isEmpty());
@@ -108,32 +122,47 @@ public void run() {
108122

109123
@Test
110124
public void testLockingOptimisticDelete() throws Exception {
125+
126+
System.out.println("Enter testLockingOptimisticDelete");
127+
111128
resetCountDownLatches();
112129
List<Movie> movies = movieBean.listMovies();
113130
assertFalse(movies.isEmpty());
114131

115-
final CountDownLatch testCountDownLatch = new CountDownLatch(1);
132+
final CountDownLatch testCountDownLatch1 = new CountDownLatch(1);
133+
final CountDownLatch testCountDownLatch2 = new CountDownLatch(1);
116134

117135
executor.execute(new Runnable() {
118136
@Override
119137
public void run() {
138+
139+
System.out.println("Update thread " + Thread.currentThread().getId() + " at " + System.nanoTime());
140+
120141
try {
121-
movieBean.updateMovie(3, "INCEPTION");
142+
testCountDownLatch1.countDown();
143+
movieBean.updateMovie2(3, "INCEPTION");
122144
} catch (RuntimeException e) { // Should throw an javax.persistence.OptimisticLockException? The Exception is wrapped around an javax.ejb.EJBException
123-
testCountDownLatch.countDown();
145+
testCountDownLatch2.countDown();
124146
}
125147
}
126148
});
127149

128150
executor.execute(new Runnable() {
129151
@Override
130152
public void run() {
153+
System.out.println("Delete thread " + Thread.currentThread().getId() + " at " + System.nanoTime());
154+
try {
155+
testCountDownLatch1.await(10, SECONDS);
156+
sleep(1000);
157+
} catch (InterruptedException e) {
158+
e.printStackTrace();
159+
}
131160
movieBean.deleteMovie(3);
132161
MovieBeanAlternative.lockCountDownLatch.countDown();
133162
}
134163
});
135164

136-
assertTrue(testCountDownLatch.await(10, TimeUnit.SECONDS));
165+
assertTrue(testCountDownLatch2.await(20, SECONDS));
137166
}
138167

139168
private void resetCountDownLatches() {
Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
package org.javaee7.jpa.locking.optimistic;
22

3+
import static java.util.concurrent.TimeUnit.SECONDS;
4+
import static javax.ejb.TransactionAttributeType.REQUIRED;
5+
6+
import java.util.concurrent.CountDownLatch;
7+
38
import javax.ejb.Stateless;
49
import javax.ejb.TransactionAttribute;
5-
import javax.ejb.TransactionAttributeType;
610
import javax.enterprise.inject.Alternative;
7-
import java.util.concurrent.CountDownLatch;
8-
9-
import static java.util.concurrent.TimeUnit.SECONDS;
1011

1112
/**
1213
* @author Roberto Cortez
1314
*/
1415
@Alternative
1516
@Stateless
1617
public class MovieBeanAlternative extends MovieBean {
18+
1719
public static CountDownLatch lockCountDownLatch = new CountDownLatch(1);
1820
public static CountDownLatch readCountDownLatch = new CountDownLatch(1);
1921

2022
@Override
21-
@TransactionAttribute(TransactionAttributeType.REQUIRED)
23+
@TransactionAttribute(REQUIRED)
2224
public Movie readMovie(Integer id) {
2325
System.out.println("MovieBeanAlternative.readMovie");
2426
Movie movie = super.readMovie(id);
@@ -27,18 +29,52 @@ public Movie readMovie(Integer id) {
2729
} catch (InterruptedException e) {
2830
e.printStackTrace();
2931
}
32+
3033
return movie;
3134
}
3235

3336
@Override
34-
@TransactionAttribute(TransactionAttributeType.REQUIRED)
37+
@TransactionAttribute(REQUIRED)
3538
public void updateMovie(Integer id, String name) {
3639
System.out.println("MovieBeanAlternative.updateMovie");
3740
super.updateMovie(id, name);
3841
try {
42+
System.out.println("MovieBeanAlternative.updateMovie waiting for lockCountDownLatch");
3943
lockCountDownLatch.await(10, SECONDS);
44+
System.out.println("MovieBeanAlternative.updateMovie done waiting for lockCountDownLatch");
4045
} catch (InterruptedException e) {
4146
e.printStackTrace();
4247
}
4348
}
49+
50+
@Override
51+
@TransactionAttribute(REQUIRED)
52+
public void updateMovie2(Integer id, String name) {
53+
System.out.println("MovieBeanAlternative.updateMovie2");
54+
55+
System.out.println("MovieBeanAlternative.updateMovie2 Reading entity");
56+
// We're reading the movie first, with the attention for this movie to become "stale"
57+
Movie movie = super.readMovie(id);
58+
59+
try {
60+
// Now wait for the movie to be deleted by the other thread
61+
System.out.println("MovieBeanAlternative.updateMovie2 waiting for lockCountDownLatch");
62+
boolean gotLock = lockCountDownLatch.await(10, SECONDS);
63+
System.out.println("MovieBeanAlternative.updateMovie2 done waiting for lockCountDownLatch. Got lock:" + gotLock);
64+
} catch (InterruptedException e) {
65+
e.printStackTrace();
66+
}
67+
68+
// If we got the lock from the lockCountDownLatch, then it means the movie has been deleted.
69+
// If we try to update the movie now it has to throw an OptimisticLockException
70+
// (if we didn't got the lock the test will just fail)
71+
super.updateMovie(movie, name);
72+
}
73+
74+
@Override
75+
@TransactionAttribute(REQUIRED)
76+
public void deleteMovie(Integer id) {
77+
System.out.println("MovieBeanAlternative.deleteMovie");
78+
super.deleteMovie(id);
79+
}
4480
}

0 commit comments

Comments
 (0)