CHAPTER 2 EJB SESSION BEANS There are two ways to define an interceptor.You can either add an eAroundInvoke annotation on a particular method,or you can annotate the bean class to designate an interceptor class that will interpose on all(or an explicit subset of)methods on the bean class.An interceptor class is denoted by the eInterceptor annotation on the bean class with which it is associated.In the case of multiple interceptor classes,the eInterceptors annotation is used. Method specific interceptor is denoted by applying the eInterceptors annotation to the business method.Methods that are annotated with @AroundInvoke should have the following signature: Object <METHOD>(InvocationContext)throws Exceptior AroundInvoke hods ted .The package javax eib public interface InvocationContext{ public Object getBean(); public java.lang.reflect.Method getMethod(); public Object[]getParameters(); public void setParameters(Object[]params); public EJBContext getEJBContext(); public java.util.Map getContextData(); public object proceed()throws Exception; The following list describes the methods in the preceding code getBean()returns the instance of the bean on which the method was called getMethod()returns the method on the bean instance that was called. getParameters()returns the parameters for the method call setParameters()modifies the parameters used for the method call getEJBContext()gives the interceptor methods access to the bean's EJBContext getontextData()allows values tobe passed be ween interceptor methods in the same InvocationContext instance using the Map returned proceed()invokes the next interceptor,if there is one,or invokes the target bean method. In the SearchFacad sion bean,we can add an int r that logs the time taken to eecue g me of be tha nd the method name.Before invokin the bu ess method.c ured and deducted from the ystem time after the bu siness method is e Svstem.out.printin. Listing 2-8.The Interceptor Method eAroundInvoke public Object TimerLog (InvocationContext ctx)throws Exception{ String beanclassName =ctx.getclass().g etName() String businessMethodName=ctx.getMethod().getName(); String target beanclassName +"."businessMethodName long startTime =System.currentTimeMillis(); 35
Chapter 2 ■ EJB Session Beans 35 There are two ways to define an interceptor. You can either add an @AroundInvoke annotation on a particular method, or you can annotate the bean class to designate an interceptor class that will interpose on all (or an explicit subset of) methods on the bean class. An interceptor class is denoted by the @Interceptor annotation on the bean class with which it is associated. In the case of multiple interceptor classes, the @Interceptors annotation is used. Method specific interceptor is denoted by applying the @Interceptors annotation to the business method. Methods that are annotated with @AroundInvoke should have the following signature: Object <METHOD>(InvocationContext) throws Exception AroundInvoke methods can have public, private, protected, or package level access. An AroundInvoke method must not be declared as final or static. The definition of InvocationContext is as follows: package javax.ejb; public interface InvocationContext { public Object getBean(); public java.lang.reflect.Method getMethod(); public Object[] getParameters(); public void setParameters(Object[] params); public EJBContext getEJBContext(); public java.util.Map getContextData(); public Object proceed() throws Exception; } The following list describes the methods in the preceding code: • getBean() returns the instance of the bean on which the method was called. • getMethod() returns the method on the bean instance that was called. • getParameters() returns the parameters for the method call. • setParameters() modifies the parameters used for the method call. • getEJBContext() gives the interceptor methods access to the bean’s EJBContext. • getContextData() allows values to be passed between interceptor methods in the same InvocationContext instance using the Map returned. • proceed() invokes the next interceptor, if there is one, or invokes the target bean method. In the SearchFacade session bean, we can add an interceptor that logs the time taken to execute each business method when invoked by the client applications. Listing 2-8 shows a time log method that will print out the time taken to execute a business method. InvocationContext is used to get the name of bean class and the invoked method name. Before invoking the business method, current system time is captured and deducted from the system time after the business method is executed. Finally, the details are printed out to the console log using System.out.println. Listing 2-8. The Interceptor Method @AroundInvoke public Object TimerLog (InvocationContext ctx) throws Exception { String beanClassName = ctx.getClass().getName(); String businessMethodName = ctx.getMethod().getName(); String target = beanClassName + "." + businessMethodName ; long startTime = System.currentTimeMillis();
CHAPTER 2 EJB SESSION BEANS System.out.println ("Invoking "target); try{ return ctx.proceed(); finally System.out.println ("Exiting"+target); long totalTime =System.currentTimeMillis()-startTime; System.out.println ("Business method"+businessMethodName+ "in"beanclassName "takes"+totalTime "ms to execute"); Stateful Session Beans mictadssedoabeanssaibeanscoapieabeandasand.opdoa,oneormoebunes The Bean Class A stateful session bean class is ar standard lava class that has a class-level annotation ofestateful if denlo descript ors are sed instead of annotations.the bean class should be denoted as a stateful sess on bean.In the cas of mixed mode,in which ou are using annotations and depl ment des s,the @Stateful annotation must be To illustrate a stateful session hean we will create a shoppingcart session bean that will keen track of the items added to a user's shopping cart and their respective quantities.In this chapter,we will use hard-coded values for the shopping cart to illustrate the state and conversation maintenance between the client and stateful session bean. Listing 2-9 shows the definition of a ShoppingCart session bean. Listing 2-9.ShoppingCartBean.java package com.apress.ejb.chapter02; import javax.ejb.Stateful; @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart,ShoppingCartLocal{ public Shoppin There will be certainus cases in which the application wants to be notified by the EJB ontainer before or after place and use mn e notificati 59 che.A st ful sessi can receiv This is an nal for erent types of transaction notifications tha a6 e are three a om the EJB container afterBegin:Indicates that a new transaction has begun beforeCompletion:Indicates that the transaction is going to be committed .afterCompletion:Indicates that a transaction has been completed For example,the ShoppingCart session bean could implement the javax.ejb.SessionSynchronization interface to get mpletion notification so that it can clear out the shopping cart cache. 9
Chapter 2 ■ EJB Session Beans 36 System.out.println ("Invoking " + target); try { return ctx.proceed(); } finally { System.out.println ("Exiting" + target); long totalTime = System.currentTimeMillis() - startTime; System.out.println ("Business method" + businessMethodName + "in" + beanClassName + "takes" + totalTime + "ms to execute"); } } Stateful Session Beans Similar to stateless session beans, stateful beans comprise a bean class and, optionally, one or more business interfaces. The Bean Class A stateful session bean class is any standard Java class that has a class-level annotation of @Stateful. If deployment descriptors are used instead of annotations, the bean class should be denoted as a stateful session bean. In the case of mixed mode, in which you are using annotations and deployment descriptors, the @Stateful annotation must be specified if any other class-level or member-level annotations are specified in the class. To illustrate a stateful session bean, we will create a ShoppingCart session bean that will keep track of the items added to a user’s shopping cart and their respective quantities. In this chapter, we will use hard-coded values for the shopping cart to illustrate the state and conversation maintenance between the client and stateful session bean. Listing 2-9 shows the definition of a ShoppingCart session bean. Listing 2-9. ShoppingCartBean.java package com.apress.ejb.chapter02; import javax.ejb.Stateful; @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart, ShoppingCartLocal { public ShoppingCartBean() { } } There will be certain use cases in which the application wants to be notified by the EJB container before or after transactions take place and then use these notifications to manage data and cache. A stateful session bean can receive this kind of notification by the EJB container when it implements the javax.ejb.SessionSynchronization interface. This is an optional feature. There are three different types of transaction notifications that the stateful session bean receives from the EJB container: • afterBegin: Indicates that a new transaction has begun • beforeCompletion: Indicates that the transaction is going to be committed • afterCompletion: Indicates that a transaction has been completed For example, the ShoppingCart session bean could implement the javax.ejb.SessionSynchronization interface to get an afterCompletion notification so that it can clear out the shopping cart cache
CHAPTER 2 EJB SESSION BEANS The Business Interface Business interfacesfor stateful session ns are similar to those used for stateles annotated in ss session beans,and they are on beans ca acces ed without a separ e businesinterthaceTheshoppingCartseson ion bean has both remote and local Fgure 2-6 <Business Interface> <Business Interface> ShoppingCart ShoppingCartLocal <Session Bean> ShoppingCartBean Figure 2-6.Business interfaces for ShoppingCart We will primarily use the local interface from our web application.The remote interface is added to facilitate unit testi of the be in this cha the remote and annotations,respectively. Listing 2-10.ShoppingCartjava public interface ShoppingCart{ Listing 2-11.ShoppingCartLocal.java @Local public interface ShoppingCartLocal{ Alternatively,you can use the coding style shown in Listing 2-12,in which you can specify the eLocal and eRemote annotations before specifying estateful or @Stateless with the name of the business interface. Listing 2-12.ShoppingCartBean.java package com.apress.ejb.chapter02; import javax.ejb.Local; import javax.ejb.Remote; import javax.ejb.Stateful; 37
Chapter 2 ■ EJB Session Beans 37 The Business Interface Business interfaces for stateful session beans are similar to those used for stateless session beans, and they are annotated in the same way, using @Local and @Remote annotations. Local view of stateful session beans can be accessed without a separate local business interface. The ShoppingCart session bean has both remote and local interfaces, as shown in Figure 2-6. We will primarily use the local interface from our web application. The remote interface is added to facilitate unit testing of the bean in this chapter. Listings 2-10 and 2-11 show the remote and local ShoppingCart business interfaces, with @Remote and @Local annotations, respectively. Listing 2-10. ShoppingCart.java package com.apress.ejb.chapter02; import javax.ejb.Remote; @Remote public interface ShoppingCart { } Listing 2-11. ShoppingCartLocal.java package com.apress.ejb.chapter02; import javax.ejb.Local; @Local public interface ShoppingCartLocal { } Alternatively, you can use the coding style shown in Listing 2-12, in which you can specify the @Local and @Remote annotations before specifying @Stateful or @Stateless with the name of the business interface. Listing 2-12. ShoppingCartBean.java package com.apress.ejb.chapter02; import javax.ejb.Local; import javax.ejb.Remote; import javax.ejb.Stateful; Figure 2-6. Business interfaces for ShoppingCart
CHAPTER 2 EJB SESSION BEANS pingCart.class}) @Stateful(na e="Shoppingcart") ubl Shoppirgcan public class ShoppingCartBean implements ShoppingCart,ShoppingCartLocal Note We will follow the earlier convention in this book,in which @Local and eRemote annotations are marked on the business interfaces. Business Methods Business methods in stateful session beans are similar to those in stateless session beans.we will augment the ShoppingCart bean by adding business methods that will add and remove wines from the shopping cart and return a list of cartitems. Listing 2-13 shows the ShoppingCart bean implementing the addWineItem(),removeWineItem(),and getCartItems()methods. Listing 2-13.ShoppingCartBean.java package com.apress.ejb.chapter02; import iava util Arravlist: import javax.ejb.Stateful; @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart,ShoppingCartLocal{ public ShoppingCrte( eItem(String wine){ public void rem public void setCartItems(ArrayList cartItems){ this.cartItems =cartItems; public ArrayList getCartItems(){ return cartItems; 9
Chapter 2 ■ EJB Session Beans 38 @Local({ShoppingCartLocal.class}) @Remote({ShoppingCart.class}) @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart, ShoppingCartLocal { public ShoppingCartBean() { } } ■ Note We will follow the earlier convention in this book, in which @Local and @Remote annotations are marked on the business interfaces. Business Methods Business methods in stateful session beans are similar to those in stateless session beans. We will augment the ShoppingCart bean by adding business methods that will add and remove wines from the shopping cart and return a list of cart items. Listing 2-13 shows the ShoppingCart bean implementing the addWineItem(), removeWineItem(), and getCartItems() methods. Listing 2-13. ShoppingCartBean.java package com.apress.ejb.chapter02; import java.util.ArrayList; import javax.ejb.Stateful; @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart, ShoppingCartLocal { public ShoppingCartBean() { } public ArrayList cartItems; public void addWineItem(String wine) { cartItems.add(wine); } public void removeWineItem(String wine) { cartItems.remove(wine); } public void setCartItems(ArrayList cartItems) { this.cartItems = cartItems; } public ArrayList getCartItems() { return cartItems; } }
CHAPTER 2 EJB SESSION BEANS Lifecycle Callback Methods PostConstruct:Denoted with the @PostConstruct annotation. PreDestroy:Denoted with the @PreDestroy annotation. PreActivate:Denoted with the ePreActivate annotation. PrePassivate:Denoted with the@PrePassivate annotation. The PostConstruct callback happens after a bean instance is instantiated in the EJB container.If the bean is ring rel 6 er obje fter injectior class is called In the case of the ShoppingCart session bean,we could have a business method called initialize()that initializes the cartItems list,a wn in Listing 2-14. Listing 2-14.The PostConstruct Method itosiaritalize0 cartItems =new ArrayList(); The PreDestroy callback happens after any method where an @Remove annotation has been completed. In the case of the ShoppingCart session bean,we could have a business method called exit()that writes the cartItems list into a database.In this chapter,we will just print out a message to the system console to illustrate the callback. Listing 2-15 shows the code for the exit()method,which has the @PreDestroy annotation. Listing 2-15.The PreDestroy Method @PreDestroy public void exit(){ /items list into the database. System.out.println("Saved items list into database"); The eRemove annotat l method for staten sesso bea et poo thod with the ,te co d i executed.isting-16shows the code for the stopsession(method,which has the emove annotaton Listing 2-16.The Remove Metho pSession() can De empty Systen ("From stopSession method with eRemove annotation") The PrePassivate callback kicks in when a stateful session bean instance is idle for too long.During this event, the container might e and store its state to a cache.The method tagged with ePrePassivate is called before the container pa tes the bean instance. 39
Chapter 2 ■ EJB Session Beans 39 Lifecycle Callback Methods Stateful session beans support callback events for construction, destruction, activation, and passivation. Following are the callbacks that map to the preceding events: • PostConstruct: Denoted with the @PostConstruct annotation. • PreDestroy: Denoted with the @PreDestroy annotation. • PreActivate: Denoted with the @PreActivate annotation. • PrePassivate: Denoted with the @PrePassivate annotation. The PostConstruct callback happens after a bean instance is instantiated in the EJB container. If the bean is using any dependency injection mechanism for acquiring references to resources or other objects in its environment, the PostConstruct event happens after injection is performed and before the first business method in the bean class is called. In the case of the ShoppingCart session bean, we could have a business method called initialize() that initializes the cartItems list, as shown in Listing 2-14. Listing 2-14. The PostConstruct Method @PostConstruct public void initialize() { cartItems = new ArrayList(); } The PreDestroy callback happens after any method where an @Remove annotation has been completed. In the case of the ShoppingCart session bean, we could have a business method called exit() that writes the cartItems list into a database. In this chapter, we will just print out a message to the system console to illustrate the callback. Listing 2-15 shows the code for the exit() method, which has the @PreDestroy annotation. Listing 2-15. The PreDestroy Method @PreDestroy public void exit() { // items list into the database. System.out.println("Saved items list into database"); } The @Remove annotation is a useful lifecycle method for stateful session beans. When the method with the @Remove annotation is called, the container will remove the bean instance from the object pool after the method is executed. Listing 2-16 shows the code for the stopSession() method, which has the @Remove annotation. Listing 2-16. The Remove Method @Remove public void stopSession() { // The method body can be empty. System.out.println("From stopSession method with @Remove annotation"); } The PrePassivate callback kicks in when a stateful session bean instance is idle for too long. During this event, the container might passivate and store its state to a cache. The method tagged with @PrePassivate is called before the container passivates the bean instance