Java Reference
In-Depth Information
of proper encapsulation mixed with the pass-by-reference semantic (used in local and no-
interface views of EJBs) can lead to hard-to-find concurrency bugs. Using immutable ob-
jects as return values for singletons is a good strategy to solve these kind of problems.
Another strategy would be to return only copies of our objects or switching to the pass-by-
value semantic. The last strategy can be applied by switching to a remote business inter-
face in the singleton.
In the TheatreBox code, you have probably noticed a @AccessTimeout annotation
(with value 5 and unit TimeUnit.MINUTES ). When you execute a query against a
method with @Lock (WRITE) , and if some other thread is already accessing it, then
after 5 seconds of waiting, you will get a timeout exception. In order to change this beha-
vior (for example, by prolonging the allowed wait time), you can specify a
@javax.ejb.AccessTimout annotation at the method or class level.
Using bean-managed concurrency
The other possible option is to use a bean-managed concurrency strategy that can be pur-
sued by applying the @javax.ejb.ConcurrencyManagement annotation with an
argument of ConcurrencyManagementType.BEAN . This annotation will disable the
effect of the @Lock annotation we have used so far, putting the responsibility of ensuring
that the singleton cache does not get corrupted on the developer.
So, in order to ensure that our bookings are preserved, we will need to use a well-known
synchronized keyword on top of the buyTicket method, which is as follows:
@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class TheatreBox {
. . . .
public synchronized void buyTicket(int seatId) {
final Seat seat = getSeat(seatId);
if (seat.isBooked()) {
throw new SeatBookedException("Seat " + seatId + "
already booked!");
}
addSeat(seat.getBookedSeat());
}
Search WWH ::




Custom Search