View Javadoc
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 }