In this recipe we will create a stateless session bean called SphereBean
. This bean will demonstrate the essential elements of a stateless bean and its life cycle. The servlet SphereServlet
will be used to demonstrate the bean.
Creating a stateless session bean consists of two steps:
Earlier versions of EJB required the use of local and/or remote interfaces. This is no longer necessary.
To use a session bean, inject the EJB into the client using the @EJB annotation followed by the declaration of the bean. In this recipe, we will use a servlet to demonstrate this process. It is important to use the @EJB annotation, otherwise the bean will not be managed by the EJB container and it will not be able to take advantage of the support provided to EJB such as transaction processing and interceptors.
We will start with an initial version of a stateless session bean called SphereBean
. From this we will add capability to incrementally demonstrate various aspects of a stateless bean. Start by creating a Java EE application called StatelessExample
. In the application add a stateless session bean called SphereBean
in the EJB module under a packt
package. Add a HttpServlet
called SphereServlet
in the WAR module in a servlet
package.
@Stateless @LocalBean public class SphereBean { public double computeVolume(double radius) { return (4.0/3.0)*Math.PI*(radius*radius*radius); } }
Notice the use of the @LocalBean annotation. This is the default annotation for a session bean and is normally automatically added by the IDE. However, it is not absolutely required and will often be removed from subsequent examples so as not to distract from the topic at hand.
The SphereServlet
illustrates the use of the stateless bean. The SphereServlet
invokes computeVolume
method and displays the result.
public class SphereServlet extends HttpServlet { @EJB SphereBean sphere; protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); try { out.println("<html>"); out.println("<head>"); out.println("<title>Servlet VolumeServlet</title>"); out.println("</head>"); out.println("<body>"); out.printf("<h3>Volume: %6.2f </h3>", sphere.computeVolume(3.0)); out.println("</body>"); out.println("</html>"); out.flush(); } finally { out.close(); } } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } }
The SphereBean
possesses a computeVolume
method that accepts a radius and returns the volume of a sphere with this radius. The session bean is declared as a stateless session bean by using the @Stateless annotation. The SphereBean
implements the formula for calculating the volume of a sphere: Volume = 4/3*PI*radius3.
Stateless session beans do not retain state information. The SphereBean
typifies this type of session bean. In this EJB there are no instance variables and thus no state can be maintained.
Notice the use of the printf
method used in the SphereServlet
. This method was introduced in Java SE 6. It mimics the printf
statement found in the C language. The first argument is a string that provides a format used to display values. These values are the subsequent parameters of the method. In the format string, place holders are used to indicate the type of value to be displayed and any formatting to be applied to the value.
The printf
statement was used in the servlet to display the volume of the sphere. This statement used a single place holder that corresponds to the second parameter. The place holder was the %6.2f. The %6.2f indicated that a floating point number was to be displayed. In addition, six characters are used to display the number with two digits following the decimal point.
There are two other aspects of stateless session beans that should be considered:
It is possible to add instance variables to the session bean. In this version we add a string to the SphereBean
to specify the measure unit used.
@Stateless public class SphereBean { private String unit; public String getUnit() { return unit; } public void setUnit(String unit) { this.unit = unit; } ... }
These methods can be used in the SphereServlet
to set and retrieve the measurement unit.
try { sphere.setUnit("kilometers"); ... out.printf("<h3>Volume: %6.2f %s</h3>", sphere.computeVolume(3.0), sphere.getUnit()); ... }
Notice the use of two placeholders in this example. The %s field specifies that a string is to be displayed. There is no width specified by the field meaning that the entire string should be displayed.
While the use of these methods is not always desirable, they do illustrate the use of an instance variable within a stateless session bean. However, there is no guarantee that the same bean instance will be used for these methods. The EJB container may choose to use different instances of the SphereBean
for each of these calls resulting in unpredictable behavior. As a result, it is not recommended that stateless session beans be used in this way. Methods of a stateless session bean should be designed to work independently of other method invocations or previous invocations of the same method.
The life cycle of a stateless bean supports two call back methods. After the stateless session bean has been constructed, the @PostConstruct annotation can be used to designate a method that will be executed before any other methods of the bean are invoked. This method is invoked after all of the bean's dependencies have been resolved. Before the bean is destroyed, the @PreDestroy annotated method can likewise be used to designate a method to be executed before the bean goes away.
In this example, the initialize
method sets a unit value and displays a simple message. In the destroy
method another message is displayed to indicate that the bean is going away.
@Stateless public class SphereBean { private String unit; @PostConstruct private void initialize() { unit = "meters"; System.out.println("SphereBean initialized"); } @PreDestroy private void destroy() { System.out.println("Clean up SphereBean"); } ... }
When some sort of initialization or termination action is needed, then these methods can be useful. Normally, most stateless beans do not require such initialization or termination action.
18.216.96.94