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.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 }