View Javadoc
1   package ejava.examples.txagent.ejb;
2   
3   import java.rmi.RemoteException;
4   import java.util.Date;
5   
6   import javax.annotation.PostConstruct;
7   import javax.annotation.PreDestroy;
8   import javax.annotation.Resource;
9   import javax.ejb.EJB;
10  import javax.ejb.EJBException;
11  import javax.ejb.Remove;
12  import javax.ejb.SessionContext;
13  import javax.ejb.SessionSynchronization;
14  import javax.ejb.Stateful;
15  import javax.ejb.TransactionAttribute;
16  import javax.ejb.TransactionAttributeType;
17  import javax.persistence.EntityManager;
18  import javax.persistence.PersistenceContext;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  import ejava.examples.txagent.bl.AgentReservationException;
24  import ejava.examples.txagent.bl.AgentReservationSession;
25  import ejava.examples.txagent.blimpl.AgentSessionImpl;
26  import ejava.examples.txagent.bo.Booking;
27  import ejava.examples.txagent.dao.BookingDAO;
28  import ejava.examples.txagent.jpa.JPABookingDAO;
29  import ejava.examples.txhotel.bo.Person;
30  import ejava.examples.txhotel.ejb.HotelReservationSessionRemote;
31  
32  /**
33   * This class provides an example of a Stateful session bean that will try to
34   * coordinate its local transaction with the tranaction of a remote session
35   * bean. The actual configuration may not really proove anything since the
36   * two applications will probably be deployed to the same server. We would
37   * need to break them apart into separate servers and separate server 
38   * implementations to show anything really significant.<p/>
39   * 
40   * Note too that this session bean declares its transaction properties using
41   * class annotations. By default, this stateful session bean runs without
42   * a tranaction while caching reservations for the user. A transaction is 
43   * required only for the commit() call, which also signals the removal of
44   * this bean instance.<p/>
45   * 
46   * The bean also implements the javax.ejb.SessionSynchronization interface.
47   * This allows it to be called at the start and end of a transaction so that
48   * it has a chance to update its cached values appropriately. This bean,
49   * however, just prints some debug.
50   *
51   * @author jcstaff
52   */
53  @Stateful
54  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
55  public class AgentReservationSessionEJB
56      implements AgentReservationSessionLocal, AgentReservationSessionRemote,
57      SessionSynchronization {
58      private static final Log log = 
59          LogFactory.getLog(AgentReservationSessionEJB.class);
60      
61      @Resource
62      private SessionContext ctx;
63      
64      @PersistenceContext(unitName="txagent")
65      private EntityManager em;
66      
67      @EJB(name="ejb/HotelReservationSession")
68      private HotelReservationSessionRemote reservationSession;
69  
70      private AgentReservationSession agentSession;
71      
72      /**
73       * This method is called immediately after dependency injection and 
74       * before any business method because of the @PostConstruct annotation. 
75       * It provides a chance to do any manual construction of the overall bean. 
76       * In this case, we need to instantiate out business logic implementation, 
77       * provide it a DAO, and register the EntityManager for the DAO(s) to use.
78       */
79      @PostConstruct
80      public void init() {
81          log.info("*** AgentReservationSessionEJB ***");
82          
83          //these objects were injected using only annotations within class
84          log.debug("ctx=" + ctx);
85          log.debug("em=" + em);
86          //this object was injected using a ejb-ref in ejb-jar.xml
87          log.debug("reservationSession=" + reservationSession);
88          
89          BookingDAO dao = new JPABookingDAO();
90          ((JPABookingDAO)dao).setEntityManager(em);
91          agentSession = new AgentSessionImpl();
92          ((AgentSessionImpl)agentSession).setBookingDAO(dao);
93          ((AgentSessionImpl)agentSession).setReservationist(reservationSession);
94      }
95      
96      /**
97       * This method should be called when the bean is destroyed because of 
98       * the @PreDestory annotation.
99       */
100     @PreDestroy
101     public void closing() {
102         log.info("*** AgentReservationSessionEJB closing ***");
103     }
104 
105     public void createBooking() throws AgentReservationException {
106         agentSession.createBooking();        
107     }       
108 
109     public void addReservation(Person person, Date startDate, Date endDate) 
110         throws AgentReservationException {
111         agentSession.addReservation(person, startDate, endDate);        
112     }
113 
114     public void cancelBooking() throws AgentReservationException {
115         agentSession.cancelBooking();        
116     }
117     
118     /**
119      * This method implements the big-bang. All information, up to this
120      * point is being cached in the business logic instance and remote
121      * hotel reservation session; all owned by this specific instance.
122      * This method causes a transaction to be started, the remote reservations
123      * to be commited by the hotel, and the booking to be stored locally
124      * with references to the reservations. If it all works; all should be
125      * stored. If something fails (e.g., an invalid reservation date), then
126      * nothing will be saved.
127      */
128     @TransactionAttribute(TransactionAttributeType.REQUIRED)
129     public Booking commit() throws AgentReservationException {
130         return agentSession.commit();
131     }
132     
133     @Remove(retainIfException=false)
134     public void close() {
135 	    log.info("*** AgentReservationSessionEJB close ***");
136 	    agentSession.close();
137 	}
138     
139     /**
140      * This method is called at the beginning of a transaction because of
141      * the implements SessionSynchronization interface.
142      */
143     public void afterBegin()  {
144         log.debug("*** Transaction Started ***");        
145     }
146     /**
147      * This method is called just before the transaction has committed to 
148      * give the bean a chance to complain.
149      */
150     public void beforeCompletion() throws EJBException, RemoteException {
151         log.debug("*** Transaction about to complete, rollback:" + 
152                 ctx.getRollbackOnly() + " ***");
153     }       
154     /**
155      * This method is called just after the transaction has committed to 
156      * tell us what happened.
157      */
158     public void afterCompletion(boolean status)  {
159         log.debug("*** Transaction Completed:" + status + " ***");        
160     }
161 }