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.slf4j.Logger;
21  import org.slf4j.LoggerFactory;
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  @Stateful
52  @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
53  public class AgentReservationSessionEJB
54      implements AgentReservationSessionLocal, AgentReservationSessionRemote,
55      SessionSynchronization {
56      private static final Logger log = LoggerFactory.getLogger(AgentReservationSessionEJB.class);
57      
58      @Resource
59      private SessionContext ctx;
60      
61      @PersistenceContext(unitName="txagent")
62      private EntityManager em;
63      
64      @EJB(name="ejb/HotelReservationSession")
65      private HotelReservationSessionRemote reservationSession;
66  
67      private AgentReservationSession agentSession;
68      
69      /**
70       * This method is called immediately after dependency injection and 
71       * before any business method because of the @PostConstruct annotation. 
72       * It provides a chance to do any manual construction of the overall bean. 
73       * In this case, we need to instantiate out business logic implementation, 
74       * provide it a DAO, and register the EntityManager for the DAO(s) to use.
75       */
76      @PostConstruct
77      public void init() {
78          log.info("*** AgentReservationSessionEJB ***");
79          
80          //these objects were injected using only annotations within class
81          log.debug("ctx=" + ctx);
82          log.debug("em=" + em);
83          //this object was injected using a ejb-ref in ejb-jar.xml
84          log.debug("reservationSession=" + reservationSession);
85          
86          BookingDAO dao = new JPABookingDAO();
87          ((JPABookingDAO)dao).setEntityManager(em);
88          agentSession = new AgentSessionImpl();
89          ((AgentSessionImpl)agentSession).setBookingDAO(dao);
90          ((AgentSessionImpl)agentSession).setReservationist(reservationSession);
91      }
92      
93      /**
94       * This method should be called when the bean is destroyed because of 
95       * the @PreDestory annotation.
96       */
97      @PreDestroy
98      public void closing() {
99          log.info("*** AgentReservationSessionEJB closing ***");
100     }
101 
102     public void createBooking() throws AgentReservationException {
103         agentSession.createBooking();        
104     }       
105 
106     public void addReservation(Person person, Date startDate, Date endDate) 
107         throws AgentReservationException {
108         agentSession.addReservation(person, startDate, endDate);        
109     }
110 
111     public void cancelBooking() throws AgentReservationException {
112         agentSession.cancelBooking();        
113     }
114     
115     /**
116      * This method implements the big-bang. All information, up to this
117      * point is being cached in the business logic instance and remote
118      * hotel reservation session; all owned by this specific instance.
119      * This method causes a transaction to be started, the remote reservations
120      * to be commited by the hotel, and the booking to be stored locally
121      * with references to the reservations. If it all works; all should be
122      * stored. If something fails (e.g., an invalid reservation date), then
123      * nothing will be saved.
124      */
125     @TransactionAttribute(TransactionAttributeType.REQUIRED)
126     public Booking commit() throws AgentReservationException {
127         return agentSession.commit();
128     }
129     
130     @Remove(retainIfException=false)
131     public void close() {
132 	    log.info("*** AgentReservationSessionEJB close ***");
133 	    agentSession.close();
134 	}
135     
136     /**
137      * This method is called at the beginning of a transaction because of
138      * the implements SessionSynchronization interface.
139      */
140     public void afterBegin()  {
141         log.debug("*** Transaction Started ***");        
142     }
143     /**
144      * This method is called just before the transaction has committed to 
145      * give the bean a chance to complain.
146      */
147     public void beforeCompletion() throws EJBException, RemoteException {
148         log.debug("*** Transaction about to complete, rollback:" + 
149                 ctx.getRollbackOnly() + " ***");
150     }       
151     /**
152      * This method is called just after the transaction has committed to 
153      * tell us what happened.
154      */
155     public void afterCompletion(boolean status)  {
156         log.debug("*** Transaction Completed:" + status + " ***");        
157     }
158 }