1 package ejava.examples.txhotel.ejb;
2
3 import java.rmi.RemoteException;
4
5 import java.util.Date;
6 import java.util.List;
7 import java.util.concurrent.TimeUnit;
8
9 import javax.annotation.PostConstruct;
10 import javax.annotation.PreDestroy;
11 import javax.annotation.Resource;
12 import javax.ejb.EJBException;
13 import javax.ejb.Remove;
14 import javax.ejb.SessionContext;
15 import javax.ejb.SessionSynchronization;
16 import javax.ejb.StatefulTimeout;
17
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
20
21 import ejava.examples.txhotel.bl.HotelReservationException;
22 import ejava.examples.txhotel.bl.HotelReservationSession;
23 import ejava.examples.txhotel.blimpl.HotelReservationSessionImpl;
24 import ejava.examples.txhotel.bo.Person;
25 import ejava.examples.txhotel.bo.Reservation;
26
27 /**
28 * This class provides an example of a stateful session bean wrapper around
29 * stateless server calls. In this example case, the user wishes to make
30 * several reservations. However, the stateless session bean will commit
31 * them to the database one at a time. This wrapper shows how someone could
32 * temporarily store them on the server while the entire set is being
33 * sanity checked. Once they are good to go, a single transaction is started
34 * by the commit() method to invoke the stateless session bean for each
35 * transaction. We can easily find tons of fault and areas for improvement with
36 * the actual business logic. However, the basic concept is that the stateful
37 * session bean can perform some of the actions of the stateless session bean
38 * outside of a transaction and then commit the changes as one unit when ready.
39 * The instance is thrown away no matter what happens. We could just as easily
40 * keep it around and add some edit functions to fix the erroneous information
41 * that caused the rollback.<p/>
42 *
43 * This bean is deployed 3 times; default configuration, using a transaction
44 * Required stateless session bean, and using a tranaction RequiresNew
45 * stateless session bean. The test client will try all 3. You'll notice
46 * that the one with RequiresNew, will not be able to rollback successful
47 * reservations because it operates in a separate transaction. The one with
48 * tranaction Required allows all to be rolled back because it joins this
49 * tranaction.<p/>
50 *
51 * This bean is also configured quite a bit from the ejb-jar.xml file;
52 * using less annotations then the other stateless session bean example.<p/>
53 *
54 * It implements the javax.ejb.SessionSynchronization interface so that it
55 * can listen, impact, or react to the state of the active transaction.
56 *
57 */
58 //@Stateful - will be supplied in ejb-jar.xml due to multi deploy
59 @StatefulTimeout(value=3, unit=TimeUnit.MINUTES)
60 public class HotelReservationSessionEJB
61 implements HotelReservationSessionLocal, HotelReservationSessionRemote,
62 SessionSynchronization {
63 private static final Logger log = LoggerFactory.getLogger(HotelReservationSessionEJB.class);
64 private HotelReservationSession impl;
65
66 @Resource
67 private SessionContext ctx;
68
69 //injected through deployment descriptor
70 private HotelRegistrationLocal reservationist;
71
72 /**
73 * This method is called when the bean is instantiated to perform manual
74 * initialization. It creates the business logic implementation class,
75 * instantiates and assigns a DAO, and assigns the EntityManager from the
76 * DAO(s) to use. This should map the the ejb-jar.xml post-construct
77 * element.
78 */
79 @PostConstruct
80 public void init() {
81 log.info("*** HotelReservationSessionEJB ***");
82
83 //these are injected by container
84 log.debug("ctx=" + ctx);
85 log.debug("reservationist=" + reservationist);
86
87 //we manually create these objects
88 impl = new HotelReservationSessionImpl();
89 ((HotelReservationSessionImpl)impl).setReservationist(reservationist);
90 }
91
92 /**
93 * This method is called just prior to the bean being destroyed. This
94 * should map to the ejb-jar.xml pre-destroy element.
95 */
96 @PreDestroy
97 public void closing() {
98 log.info("*** HotelReservationSessionEJB closing ***");
99 }
100
101 /**
102 * This method will destroy the stateful instance.
103 */
104 @Remove
105 public void close() {
106 log.info("*** HotelReservationSessionEJB close ***");
107 impl.close();
108 }
109
110 public void createReservation(Person person, Date startDate, Date endDate)
111 throws HotelReservationException {
112 impl.createReservation(person, startDate, endDate);
113 }
114
115 public void cancelReservations() throws HotelReservationException {
116 impl.cancelReservations();
117 }
118
119 public List<Reservation> commit() throws HotelReservationException {
120 return impl.commit();
121 }
122
123 /**
124 * This is called to tell us the transaction has started because we
125 * implement SessionSynchronization interface.
126 */
127 public void afterBegin() {
128 log.debug("*** Transaction Started ***");
129 }
130 /**
131 * This is called to give us a chance to complain before the
132 * transaction really commits.
133 */
134 public void beforeCompletion() throws EJBException, RemoteException {
135 log.debug("*** Transaction about to complete, rollback:" +
136 ctx.getRollbackOnly() + " ***");
137 }
138 /**
139 * This is called to tell us how the transaction did.
140 */
141 public void afterCompletion(boolean status) {
142 log.debug("*** Transaction Completed:" + status + " ***");
143 }
144 }