View Javadoc
1   package ejava.examples.ejbsessionbank.web;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.util.HashMap;
6   import java.util.List;
7   import java.util.Map;
8   import java.util.Properties;
9   
10  import javax.naming.InitialContext;
11  import javax.naming.NamingException;
12  import javax.servlet.RequestDispatcher;
13  import javax.servlet.ServletConfig;
14  import javax.servlet.ServletException;
15  import javax.servlet.http.HttpServlet;
16  import javax.servlet.http.HttpServletRequest;
17  import javax.servlet.http.HttpServletResponse;
18  
19  import org.slf4j.Logger;
20  import org.slf4j.LoggerFactory;
21  
22  import ejava.examples.ejbsessionbank.bl.Teller;
23  import ejava.examples.ejbsessionbank.bo.Account;
24  import ejava.examples.ejbsessionbank.bo.Ledger;
25  import ejava.examples.ejbsessionbank.ejb.TellerLocal;
26  import ejava.examples.ejbsessionbank.ejb.TellerRemote;
27  import ejava.util.ejb.EJBClient;
28  import ejava.util.jndi.JNDIUtil;
29  
30  @SuppressWarnings("serial")
31  public class TellerHandlerServlet extends HttpServlet {
32      private static final Logger logger = LoggerFactory.getLogger(TellerHandlerServlet.class);
33      public static final String COMMAND_PARAM = "command";
34      public static final String EXCEPTION_PARAM = "javax.servlet.error.exception";
35      public static final String HANDLER_TYPE_KEY = "type";
36      public static final String ADMIN_TYPE = "admin";
37      public static final String CREATE_ACCOUNT_COMMAND = "Create Account";
38      public static final String DEPOSIT_COMMAND = "Deposit";
39      public static final String WITHDRAW_COMMAND = "Withdraw";
40      public static final String GET_ACCOUNT_COMMAND = "Get Account";
41      public static final String CLOSE_ACCOUNT_COMMAND = "Close Account";
42      public static final String GET_ACCOUNTS_COMMAND = "Get Accounts";
43      public static final String CREATE_ACCOUNTS_COMMAND = "Create Accounts";
44      public static final String GET_LEDGER_COMMAND = "Get Ledger";
45      public static final String STEAL_ALL_ACCOUNTS_COMMAND = "Steal All Accounts";
46      public static final String jndiName = 
47           EJBClient.getEJBClientLookupName("ejbsessionBankEAR", "ejbsessionBankEJB", "", "TellerEJB", TellerRemote.class.getName(), false);
48          
49      private static final String UNKNOWN_COMMAND_URL = 
50          "/WEB-INF/content/UnknownCommand.jsp";
51      private static final String ERROR_URL = 
52              "/WEB-INF/content/ErrorPage.jsp";
53      private Map<String, Handler> handlers = new HashMap<String, Handler>();
54      
55      /**
56       * This will get automatically injected when running within the 
57       * application server with the TellerEJB. beanInterface is only
58       * needed to resolve the derived type ambiguity for Local and Remote
59       * caused by the design of our example. 
60       */
61      @javax.ejb.EJB(beanInterface=TellerLocal.class)
62      private Teller injectedTeller;
63      private Teller teller;
64  
65      /**
66       * Init verify the teller reference to the EJB logic is in place and
67       * initializes the proper handler for the assigned role supplied in 
68       * the servlet init parameters.
69       */
70      public void init() throws ServletException {
71          logger.debug("init() called; teller=" + injectedTeller);
72          
73          try {
74              ServletConfig config = getServletConfig();
75              
76              teller = injectedTeller!=null ? injectedTeller : getTeller();
77              if (teller==null) {
78                  throw new Exception("no teller injected or found in JNDI lookup");
79              }
80              
81              //build a list of handlers for individual commands
82              if (ADMIN_TYPE.equals(config.getInitParameter(HANDLER_TYPE_KEY))) {
83                  handlers.put(CREATE_ACCOUNT_COMMAND, new CreateAccount());    
84                  handlers.put(GET_ACCOUNT_COMMAND, new GetAccount());    
85                  handlers.put(CLOSE_ACCOUNT_COMMAND, new CloseAccount());    
86                  handlers.put(DEPOSIT_COMMAND, new DepositAccount());    
87                  handlers.put(WITHDRAW_COMMAND, new WithdrawAccount());    
88                  handlers.put(GET_ACCOUNTS_COMMAND, new GetAccounts());    
89                  handlers.put(CREATE_ACCOUNTS_COMMAND, new CreateAccounts());    
90                  handlers.put(GET_LEDGER_COMMAND, new GetLedger());    
91                  handlers.put(STEAL_ALL_ACCOUNTS_COMMAND, new StealAccounts());    
92              }            
93          }
94          catch (Exception ex) {
95              logger.error("error initializing handler", ex);
96              throw new ServletException("error initializing handler", ex);
97          }
98      }
99      
100     /**
101      * This helper method will return a Teller in development based on a JNDI lookup.
102      * @return teller if found
103      * @throws NamingException
104      * @throws IOException 
105      */
106     protected Teller getTeller() throws NamingException, IOException {
107         Teller teller = null;
108         InputStream is = null;
109         InitialContext jndi = null;
110         try {
111             //manually load the JNDI properties to make sure we don't get a Jetty JNDI tree in dev
112             if ((is=getClass().getResourceAsStream("/jndi.properties"))==null) {
113                 logger.warn("no jndi.properties found, check classpath");
114             } else {
115                 Properties jndiProperties = new Properties();
116                 jndiProperties.load(is);
117                 logger.info("jndiProperties={}", jndiProperties);
118     
119                 jndi = new InitialContext(jndiProperties);
120                 logger.debug("looking up: {}", jndiName);
121                 teller = (Teller)jndi.lookup(jndiName);
122                 logger.debug("found {}", teller);
123             }
124           } finally {
125             if (is!=null) {
126                 try { is.close(); } catch(Exception ex) {}
127             }
128             if (jndi!=null) {
129                 try { jndi.close(); } catch(Exception ex) {}
130             }
131         }
132         return teller;
133     }
134 
135     /**
136      * This is the main dispatch method for the servlet. It expects to
137      * find a command keyed by an argument in the request parameters.
138      */
139     protected void doGet(HttpServletRequest request, 
140                          HttpServletResponse response) 
141         throws ServletException, IOException {
142         logger.debug("doGet() called");
143 
144         String command = request.getParameter(COMMAND_PARAM);
145         logger.debug("command=" + command);
146 
147         try {
148             if (command != null) {
149                 Handler handler = handlers.get(command);
150                 if (handler != null) {
151                     handler.handle(request, response, teller);
152                 }
153                 else {
154                     RequestDispatcher rd = 
155                         getServletContext().getRequestDispatcher(
156                             UNKNOWN_COMMAND_URL);
157                             rd.forward(request, response);
158                 }
159             }
160             else {
161                 throw new Exception("no " + COMMAND_PARAM + " supplied"); 
162             }
163         } catch (NamingException ex) {
164             request.setAttribute(EXCEPTION_PARAM, ex);
165             RequestDispatcher rd = getServletContext().getRequestDispatcher(
166                     ERROR_URL);
167                     rd.forward(request, response);
168         } catch (Exception ex) {
169             request.setAttribute(EXCEPTION_PARAM, ex);
170             RequestDispatcher rd = getServletContext().getRequestDispatcher(
171                     UNKNOWN_COMMAND_URL);
172                     rd.forward(request, response);
173         }
174     }
175 
176     /**
177      * Since this is a toy, we don't really care whether they call get or post.
178      */
179     protected void doPost(HttpServletRequest request, 
180                           HttpServletResponse response) 
181         throws ServletException, IOException {
182         logger.debug("doPost() called, calling doGet()");
183         doGet(request, response);
184     }
185 
186     public void destroy() {
187         logger.debug("destroy() called");
188     }
189     
190     private abstract class Handler {
191         protected static final String MAIN_PAGE = 
192             "/index.jsp";
193         protected static final String DISPLAY_EXCEPTION = 
194             "/WEB-INF/content/DisplayException.jsp";
195         protected static final String ACCT_NUM_PARAM = "accountNumber";
196         protected static final String AMOUNT_PARAM = "amount";
197         protected static final String INDEX_PARAM = "index";
198         protected static final String NEXT_INDEX_PARAM = "nextIndex";
199         protected static final String COUNT_PARAM = "count";
200         protected static final String ACCOUNT_PARAM = "account";
201         protected static final String ACCOUNTS_PARAM = "accounts";
202         protected static final String LEDGER_PARAM = "ledger";
203         protected static final String DISPLAY_ACCOUNT_URL = 
204             "/WEB-INF/content/DisplayAccount.jsp";
205         protected static final String DISPLAY_ACCOUNTS_URL = 
206             "/WEB-INF/content/DisplayAccounts.jsp";
207         protected static final String DISPLAY_LEDGER_URL = 
208             "/WEB-INF/content/DisplayLedger.jsp";
209         public abstract void handle(HttpServletRequest request, 
210                 HttpServletResponse response, Teller t) 
211                 throws ServletException, IOException;
212     }
213     
214     private class CreateAccount extends Handler {
215         public void handle(HttpServletRequest request, 
216                 HttpServletResponse response, Teller t) 
217                 throws ServletException, IOException {
218             try {
219                 String acctNum = (String)request.getParameter(ACCT_NUM_PARAM);                
220                 Account account = t.createAccount(acctNum);
221                 
222                 request.setAttribute(ACCOUNT_PARAM, account);                
223                 RequestDispatcher rd = 
224                   getServletContext().getRequestDispatcher(DISPLAY_ACCOUNT_URL);
225                 rd.forward(request, response);                
226             }
227             catch (Exception ex) {
228                 logger.error("error creating account:" + ex, ex);
229                 request.setAttribute(EXCEPTION_PARAM, ex);
230                 RequestDispatcher rd = 
231                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
232                 rd.forward(request, response);                
233             }
234         }
235     }
236 
237     private class GetAccount extends Handler {
238         public void handle(HttpServletRequest request, 
239                 HttpServletResponse response, Teller t) 
240                 throws ServletException, IOException {
241             try {
242                 String acctNum = (String)request.getParameter(ACCT_NUM_PARAM);                
243                 Account account = t.getAccount(acctNum);
244                 
245                 request.setAttribute(ACCOUNT_PARAM, account);                
246                 RequestDispatcher rd = 
247                   getServletContext().getRequestDispatcher(DISPLAY_ACCOUNT_URL);
248                 rd.forward(request, response);                
249             }
250             catch (Exception ex) {
251                 logger.error("error creating account:" + ex, ex);
252                 request.setAttribute(EXCEPTION_PARAM, ex);
253                 RequestDispatcher rd = 
254                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
255                 rd.forward(request, response);                
256             }
257         }
258     }
259 
260     private class DepositAccount extends Handler {
261         public void handle(HttpServletRequest request, 
262                 HttpServletResponse response, Teller t) 
263                 throws ServletException, IOException {
264             try {
265                 String acctNum = (String)request.getParameter(ACCT_NUM_PARAM);                
266                 String amountStr = (String)request.getParameter(AMOUNT_PARAM);
267                 double amount = Double.parseDouble(amountStr);
268                 
269                 Account account = t.getAccount(acctNum);
270                 account.deposit(amount);
271                 t.updateAccount(account);
272                 
273                 request.setAttribute(ACCOUNT_PARAM, account);                
274                 RequestDispatcher rd = 
275                   getServletContext().getRequestDispatcher(DISPLAY_ACCOUNT_URL);
276                 rd.forward(request, response);                
277             }
278             catch (Exception ex) {
279                 logger.error("error depositing to account:" + ex, ex);
280                 request.setAttribute(EXCEPTION_PARAM, ex);
281                 RequestDispatcher rd = 
282                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
283                 rd.forward(request, response);                
284             }
285         }
286     }
287 
288     private class WithdrawAccount extends Handler {
289         public void handle(HttpServletRequest request, 
290                 HttpServletResponse response, Teller t) 
291                 throws ServletException, IOException {
292             try {
293                 String acctNum = (String)request.getParameter(ACCT_NUM_PARAM);                
294                 String amountStr = (String)request.getParameter(AMOUNT_PARAM);
295                 double amount = Double.parseDouble(amountStr);
296                 
297                 Account account = t.getAccount(acctNum);
298                 account.withdraw(amount);
299                 t.updateAccount(account);
300                 
301                 request.setAttribute(ACCOUNT_PARAM, account);                
302                 RequestDispatcher rd = 
303                   getServletContext().getRequestDispatcher(DISPLAY_ACCOUNT_URL);
304                 rd.forward(request, response);                
305             }
306             catch (Exception ex) {
307                 logger.error("error withdrawing from account:" + ex, ex);
308                 request.setAttribute(EXCEPTION_PARAM, ex);
309                 RequestDispatcher rd = 
310                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
311                 rd.forward(request, response);                
312             }
313         }
314     }
315 
316     private class CloseAccount extends Handler {
317         public void handle(HttpServletRequest request, 
318                 HttpServletResponse response, Teller t) 
319                 throws ServletException, IOException {
320             try {
321                 String acctNum = (String)request.getParameter(ACCT_NUM_PARAM);                
322                 
323                 t.closeAccount(acctNum);
324                 
325                 response.sendRedirect(request.getContextPath() + MAIN_PAGE);
326             }
327             catch (Exception ex) {
328                 logger.error("error closing account:" + ex, ex);
329                 request.setAttribute(EXCEPTION_PARAM, ex);
330                 RequestDispatcher rd = 
331                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
332                 rd.forward(request, response);                
333             }
334         }
335     }
336 
337     private class CreateAccounts extends Handler {
338         public void handle(HttpServletRequest request, 
339                 HttpServletResponse response, Teller t) 
340                 throws ServletException, IOException {
341             try {
342                 String countStr = (String)request.getParameter(COUNT_PARAM);
343                 int count = Integer.parseInt(countStr);
344                 
345                 long seed = System.currentTimeMillis();
346                 for(int i=0; i<count; i++) {
347                     Account account = t.createAccount("" + seed + "-" + i);
348                     account.deposit(i);
349                     t.updateAccount(account);                    
350                 }
351                 
352                 response.sendRedirect(request.getContextPath() + MAIN_PAGE);
353             }
354             catch (Exception ex) {
355                 logger.error("error closing account:" + ex, ex);
356                 request.setAttribute(EXCEPTION_PARAM, ex);
357                 RequestDispatcher rd = 
358                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
359                 rd.forward(request, response);                
360             }
361         }
362     }
363 
364     private class GetAccounts extends Handler {
365         public void handle(HttpServletRequest request, 
366                 HttpServletResponse response, Teller t) 
367                 throws ServletException, IOException {
368             try {
369                 String indexStr = (String)request.getParameter(INDEX_PARAM);
370                 String countStr = (String)request.getParameter(COUNT_PARAM);
371                 int index = Integer.parseInt(indexStr);
372                 int count = Integer.parseInt(countStr);
373                 
374                 List<Account> accounts = t.getAccounts(index, count);
375                 
376                 int nextIndex = (accounts.size()==0) ? 
377                         index : index + accounts.size();
378                 
379                 request.setAttribute(ACCOUNTS_PARAM, accounts);
380                 request.setAttribute(INDEX_PARAM, index);
381                 request.setAttribute(COUNT_PARAM, count);
382                 request.setAttribute(NEXT_INDEX_PARAM, nextIndex);
383                 
384                 RequestDispatcher rd = 
385                  getServletContext().getRequestDispatcher(DISPLAY_ACCOUNTS_URL);
386                 rd.forward(request, response);                
387             }
388             catch (Exception ex) {
389                 logger.error("error getting accounts:" + ex, ex);
390                 request.setAttribute(EXCEPTION_PARAM, ex);
391                 RequestDispatcher rd = 
392                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
393                 rd.forward(request, response);                
394             }
395         }
396     }
397 
398     private class GetLedger extends Handler {
399         public void handle(HttpServletRequest request, 
400                 HttpServletResponse response, Teller t) 
401                 throws ServletException, IOException {
402             try {
403                 Ledger ledger = t.getLedger();
404                 
405                 request.setAttribute(LEDGER_PARAM, ledger);
406                 
407                 RequestDispatcher rd = 
408                    getServletContext().getRequestDispatcher(DISPLAY_LEDGER_URL);
409                 rd.forward(request, response);                
410             }
411             catch (Exception ex) {
412                 logger.error("error getting ledger:" + ex, ex);
413                 request.setAttribute(EXCEPTION_PARAM, ex);
414                 RequestDispatcher rd = 
415                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
416                 rd.forward(request, response);                
417             }
418         }
419     }
420 
421     private class StealAccounts extends Handler {
422         public void handle(HttpServletRequest request, 
423                 HttpServletResponse response, Teller t) 
424                 throws ServletException, IOException {
425             try {
426                 List<Account> accounts = t.getAccounts(0, 100);
427                 while (accounts.size() > 0) {
428                     logger.debug("closing " + accounts.size() + " accounts");
429                     for (Account account : accounts) {
430                         if (account.getBalance() > 0) {
431                             account.withdraw(account.getBalance());
432                             t.updateAccount(account);
433                         }
434                         else if (account.getBalance() < 0) {
435                             account.deposit(account.getBalance() * -1);
436                             t.updateAccount(account);
437                         }
438                         t.closeAccount(account.getAccountNumber());
439                     }
440                     accounts = t.getAccounts(0, 100);
441                 }
442                 
443                 response.sendRedirect(request.getContextPath() + MAIN_PAGE);
444             }
445             catch (Exception ex) {
446                 logger.error("error getting ledger:" + ex, ex);
447                 request.setAttribute(EXCEPTION_PARAM, ex);
448                 RequestDispatcher rd = 
449                     getServletContext().getRequestDispatcher(DISPLAY_EXCEPTION);
450                 rd.forward(request, response);                
451             }
452         }
453     }
454 }