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.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
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 * @author jcstaff
58 */
59 //@Stateful - will be supplied in ejb-jar.xml due to multi deploy
60 @StatefulTimeout(value=3, unit=TimeUnit.MINUTES)
61 public class HotelReservationSessionEJB
62 implements HotelReservationSessionLocal, HotelReservationSessionRemote,
63 SessionSynchronization {
64 private static final Log log =
65 LogFactory.getLog(HotelReservationSessionEJB.class);
66 private HotelReservationSession impl;
67
68 @Resource
69 private SessionContext ctx;
70
71 //injected through deployment descriptor
72 private HotelRegistrationLocal reservationist;
73
74 /**
75 * This method is called when the bean is instantiated to perform manual
76 * initialization. It creates the business logic implementation class,
77 * instantiates and assigns a DAO, and assigns the EntityManager from the
78 * DAO(s) to use. This should map the the ejb-jar.xml post-construct
79 * element.
80 */
81 @PostConstruct
82 public void init() {
83 log.info("*** HotelReservationSessionEJB ***");
84
85 //these are injected by container
86 log.debug("ctx=" + ctx);
87 log.debug("reservationist=" + reservationist);
88
89 //we manually create these objects
90 impl = new HotelReservationSessionImpl();
91 ((HotelReservationSessionImpl)impl).setReservationist(reservationist);
92 }
93
94 /**
95 * This method is called just prior to the bean being destroyed. This
96 * should map to the ejb-jar.xml pre-destroy element.
97 */
98 @PreDestroy
99 public void closing() {
100 log.info("*** HotelReservationSessionEJB closing ***");
101 }
102
103 /**
104 * This method will destroy the stateful instance.
105 */
106 @Remove
107 public void close() {
108 log.info("*** HotelReservationSessionEJB close ***");
109 impl.close();
110 }
111
112 public void createReservation(Person person, Date startDate, Date endDate)
113 throws HotelReservationException {
114 impl.createReservation(person, startDate, endDate);
115 }
116
117 public void cancelReservations() throws HotelReservationException {
118 impl.cancelReservations();
119 }
120
121 public List<Reservation> commit() throws HotelReservationException {
122 return impl.commit();
123 }
124
125 /**
126 * This is called to tell us the transaction has started because we
127 * implement SessionSynchronization interface.
128 */
129 public void afterBegin() {
130 log.debug("*** Transaction Started ***");
131 }
132 /**
133 * This is called to give us a chance to complain before the
134 * transaction really commits.
135 */
136 public void beforeCompletion() throws EJBException, RemoteException {
137 log.debug("*** Transaction about to complete, rollback:" +
138 ctx.getRollbackOnly() + " ***");
139 }
140 /**
141 * This is called to tell us how the transaction did.
142 */
143 public void afterCompletion(boolean status) {
144 log.debug("*** Transaction Completed:" + status + " ***");
145 }
146 }