EJB 3.1 Cookbook

4 (1 reviews total)
By Richard M. Reese
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. Getting Started With EJBs

About this book

Enterprise Java Beans enable rapid and simplified development of secure and portable applications based on Java technology.Creating and using EJBs can be challenging and rewarding. Among the challenges are learning the EJB technology itself, learning how to use the development environment you have chosen for EJB development, and the testing of the EJBs.

This EJB 3.1 Cookbook addresses all these challenges and covers new 3.1 features, along with explanations of useful retained features from earlier versions. It brings the reader quickly up to speed on how to use EJB 3.1 techniques through the use of step-by-step examples without the need to use multiple incompatible resources. The coverage is concise and to the point, and is organized to allow you to quickly find and learn those features of interest to you.

The book starts with coverage of EJB clients. The reader can choose the chapters and recipes which best address his or her specific needs. The newer EJB technologies presented include singleton beans which support application wide needs and interceptors to permit processing before and after a target method is invoked. Asynchronous invocation of methods and enhancements to the timer service are also covered.

The EJB 3.1 CookBook is a very straightforward and rewarding source of techniques supporting Java EE applications.

Publication date:
June 2011
Publisher
Packt
Pages
436
ISBN
9781849682381

 

Chapter 1. Getting Started With EJBs

In this chapter, we will cover:

  • Creating a simple session EJB

  • Accessing a session bean using dependency injection

  • Accessing the session bean using JNDI

  • Creating a simple message-driven bean

  • Sending a message to a message-driven bean

  • Accessing an EJB from a web service (JAX-WS)

  • Accessing an EJB from a web service (JAX-RS)

  • Accessing an EJB from an Applet

  • Accessing an EJB from JSP

  • Calling an EJB from JSF

  • Accessing an EJB from a Java Application using JNDI

  • Accessing an EJB from a Java Application using an embeddable container

  • Accessing the EJB container

 

Introduction


Creating and using Enterprise Java Beans (EJBs) can be challenging and rewarding. Among the challenges are learning the EJB technology itself, learning how to use the development environment you have chosen for EJB development and the testing of the EJBs. The examples used throughout the book were developed and tested using NetBeans 6.9.1 and GlassFish Server Open Source Edition v3.0.1. NetBeans and GlassFish can be downloaded bundled from http://netbeans.org/downloads/index.html. On this page are several bundle combinations. Use the one title Java. The GlassFish Enterprise Server v3 Prelude also supports EJB 3.1.

In addition, Windows 7 Professional 64 bit edition, service pack 1, was used to develop the applications. The Mozilla Firefox v3.6.15 browser was used to display web pages.

EJBs can be used in many different contexts and called from many different types of applications. In presenting EJBs, a fundamental question is this: how do we go about illustrating the use of an EJB before we know what an EJB is? How do we learn about EJBs unless we know how to call them? The approach taken in this chapter is to first demonstrate how to create simple Session Beans and Message-Driven Beans. Knowing how to create these beans will then allow us to use them from different contexts. The details of session and message bean construction and their use are covered in subsequent chapters. We are concerned with identifying some of the more common clients and then seeing how they call and use EJBs. EJBs can be used within a number of different clients including servlets, JSP, JSF, applets, Java SE type applications, and other EJBs.

From the client perspective, it is accessing an EJB as if the EJB existed in the same Java Virtual Machine (JVM). Depending on the client, this may be true. Regardless, EJBs are managed by an EJB container that provides support not readily available to other objects. This support can be in the form of security, transaction processing or concurrency management.

Using a bean involves declaring a reference to the bean, creating an instance of the bean and then calling the methods of the bean. There are two techniques for gaining access to an EJB: Dependency Injection (DI) and the Java Naming and Directory Service (JNDI). DI is the easiest when we can use it, but JNDI can be used in places where DI is not supported. We will look at both of these approaches. However, EJBs should not be created using the Java new keyword. If the EJB is created using this keyword, then it will no longer be an EJB but rather a regular object. It will not be able to take advantage of the support provided by the EJB container.

When an application is created using NetBeans, it will normally consist of an application-ejb and an application-war module. Other development environments may take a different approach. In addition, Java EE applications are normally deployed as an .ear file.

An important element of Java EE applications is entities which support the persistence of application data. The Java Persistence API (JPA) supports the use of entities in an EE application and the traditional Java application. While they are not introduced here, they are typically called indirectly through a session bean. This topic is covered in Chapter 4, EJB Persistence.

Some of the recipes are dependent on earlier recipes. For example, the session EJB developed in the first recipe is reused in the second recipe. This approach permits the reuse of code which is always a good development practice.

 

Creating a simple session EJB


In this recipe, we will create a simple session bean that returns either a formal or an informal salutation based on a string parameter. In the next recipe we will see how to invoke this EJB from a servlet.

Specifically we will create a stateless session bean. A stateless session bean does not remember its previous invocations. A user will call the bean and the bean will return a result. A stateless bean is not good for maintaining the state of an interactive session such as required to maintain a list of purchases. However, it is useful for one-time calculations. Our bean returns one of two simple greetings.

Getting ready

The creation of a session EJB consists of two steps:

  1. Create the EJB class annotated with a session bean annotation

  2. Add business method to the EJB

These steps have been made easier through the use of annotations.

How to do it...

In this example we will use the @Stateless annotation. Create a Java EE application called SalutationApplication . The application should have both a SalutationApplication-ejb and a SalutationApplication-war module. Add the following Stateless session bean to a package called packt and name the bean Salutation.

Note

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.PacktPub.com. If you purchased this book elsewhere, you can visit http://www.PacktPub.com/support and register to have the files e-mailed directly to you.

In this EJB we will add two simple business methods which return different types of greetings.

package packt;
import javax.ejb.Stateless;

@Stateless
public class Salutation {
  public String getFormalSalutation(String name) {
    return "Dear " + name;
  }
  public String getInformalSalutation(String name) {
    return "Hi " + name;
  }
}

How it works...

The process of creating a stateless session EJB involved defining a class to support the desired functionality of the bean and using the @Stateless annotation to specify the class as a stateless session EJB. In order to use the @Stateless annotation we needed to use an import statement.

The two class methods took a string as an argument and returned the string prefixed with either a formal or informal greeting.

There's more...

Annotation is at the heart of the EJB declaration. Annotations are embedded in the application's source code and allow further processing of the source code either:

  • Before a source code file is compiled

  • During development by a compiler, IDE deployment tool or similar application

  • During the execution of the application

An annotation can be applied to many different program elements including but not limited to classes, methods, parameters, fields, and packages. In essence, annotations are used to provide metadata about an element. Metadata is usually defined as data about data. We may have a program element, such as a method, requiring in some circumstances additional information about how it is used.

For example, we might want a particular method to correctly override a base class method. The @Override annotation does exactly this. This annotation is useful should we accidentally mistype the method name and fail to actually override the annotation. We may think we are overriding it but we are not. If we use the @Override annotation and fail to actually override the method a syntax error is issued by the compiler.

The @Stateless annotation provides information to configure the environment and treat the class as an EJB. The annotation is used at runtime and has attributes affecting its visibility. In particular, the mappedName attribute is used in the generation of the bean's JNDI name.

@Stateless(mappedName="salutationBean")
public class Salutation {

The bean can now be referenced in certain contexts using the name: salutationBean. An alias can also be defined for an EJB in the project's ejb-jar.xml file.

Session beans are not limited to a stateless form. The use of the @Stateful annotation declares a bean to be stateful. This means field variables can maintain their values as a user interacts with the application over a period of time called a session. In addition, session beans frequently interact with entities to persist data to a database.

A session bean can also have a local, remote and no-interface client view. The interface used determines the intent and scope of the bean. The no-interface view is new to EJB 3.1. This approach allows the developer to use EJB without having to declare a business interface. In later recipes we will see how these aspects of session beans are used.

See also

The next recipe illustrates how we can use the session bean in other parts of our application.

 

Accessing a session bean using dependency injection


A session bean has limited value by itself. To be useful it needs to be used by a client such as a servlet or JSF page. In this recipe we will see how to use dependency injection to use a session bean in a servlet.

Getting ready

The essential steps to access a session EJB using dependency injection include:

  1. Inject the EJB using the @EJB annotation

  2. Access its methods as needed

First we need a session bean. To keep things simple, we will use the Salutation session EJB developed in the previous recipe. We will add our servlet to the SalutationApplication.

How to do it...

We will be developing a HyperText Transfer Protocol (HTTP) based servlet named SalutationServlet. This servlet will use the Salutation EJB's methods and display their return value. Create a package in the WAR module called servlet. Add the servlet to this package.

The servlet consists of a class declaration and three methods:

  • doGet —A standard servlet method

  • doPostA standard servlet method

  • processRequest —Is invoked by both the doGet and doPost methods

The servlet begins with the @WebServlet annotation then declares an instance of the Servlet EJB and uses it in the processRequest method.

package servlet;
import javax.ejb.EJB;
import packt.Salutation;

@WebServlet(urlPatterns = {"/SalutationServlet"})
public class SalutationServlet extends HttpServlet {
  @EJB
  private Salutation salutation;

  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 SalutationServlet</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>" + salutation.getFormalSalutation("Sherlock Holmes") + "</h1>");
        out.println("</body>");
        out.println("</html>");
      } finally {
      out.flush();
      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);
    }
}

Enter the URL as shown in the following screenshot into a browser. When executed, the salutation Dear Sherlock Holmes will be displayed in the browser.

How it works...

To provide a reference to an EJB in a servlet we used the @EJB annotation to inject the bean. However, before we could use the annotation two import statements were required. The first one was for the annotation and the second one is for the Salutation EJB.

import javax.ejb.EJB;
import packt.Salutation;

The declaration of the servlet began with @WebServlet annotation. The @WebServlet is a class level annotation marking the class as an HTTP servlet. The urlPatterns parameter specifies the URL pattern which maps to this servlet. This pattern is important because this is how a user of the servlet is able to locate it on the server.

@WebServlet(urlPatterns = {"/SalutationServlet"})
public class SalutationServlet extends HttpServlet {

The salutation variable was declared as a field of the servlet. The @EJB annotation immediately preceded the variable declaration and effected dependency injection. This allows the EJB container to support the EJB.

   @EJB
   private Salutation salutation;

HTTP Servlets typically respond to doGet and doPost HTTP commands. The doGet and doPost methods are invoked depending on whether a GET or POST HTTP command is issued. In this example, both of these methods called the processRequest method using the common servlet logic in the processRequest method.

The processRequest method used standard servlet code to generate the HTML response sent back to the browser. Of particular interest to us was the use of the salutation object. The getFormalSalutation method was invoked and its return value was sent forward to the browser.

...
out.println("<h1>" + salutation.getFormalSalutation("Sherlock Holmes") + "</h1>");
...

See also

The next recipe illustrates the use of JNDI to access an EJB.

 

Accessing the session bean using JNDI


JNDI can also be used to access an EJB but using this technique is not as easy as DI. The Salutation EJB from the first recipe and the servlet from the second recipe are used to illustrate this technique.

Getting ready

To use JNDI in a client:

  1. Obtain an InitialContext object

  2. Use the context to look up the EJB

Familiarize yourself with the Salutation session bean and its two methods as developed in the Creating a Simple Session EJB recipe. We will also modify the SalutationServlet from the second recipe to use JNDI instead of DI.

How to do it...

A portable JNDI name syntax has been added to EJB 3.1. We will use this syntax as it makes the use of JNDI less dependent on the deployment server.

The modification of the SalutationServlet involves removing the @EJB annotation and adding code to perform the JNDI look up. This code is placed immediately before the servlet's try block.

...
  Context context = null;
  try {
    context = new InitialContext();
    salutation = (Salutation) context.lookup("java:global/SalutationApplication/SalutationApplication-ejb/Salutation");
  } catch (Exception e) {
      e.printStackTrace();
  }
...

How it works...

In order to initialize and assign an instance of the bean to the salutation variable, the bean needed to be looked up using an object implementing the Context interface. The Context interface provided the information necessary to locate the server and to create a reference to a Salutation object. First, we needed to create an InitialContext object. This class implemented the Context interface. Exceptions resulting from the creation of the InitialContext object and the subsequent lookup method were caught.

Once the Context has been established, the Context object's lookup method was invoked and a reference to the Salutation EJB was provided. The lookup method used a portable JNDI name to identify the EJB. In this case, a global name was used.

The syntax starts with one of three different prefixes. In this example the prefix was java:global specifying a global name. Following the prefix is a series of names separated by forward slashes. The first name was the name of the application, SalutationApplication. The second name was the name of the JAR file where the bean is held, SalutationApplication-ejb. The name of the bean was the last name. Names are automatically generated for EJBs.

Prior to EJB 3.1, a JNDI name was server-specific and limited the portability of EJBS. With EJB 3.1 this problem goes away and we can create more portable and maintainable applications.

There's more...

There are two features of JNDI needing further scrutiny.

  • Portable JNDI naming syntax

  • EJBS supporting multiple interfaces

Portable JNDI naming syntax

JNDI is used to look up resources such as session beans within an application and across the network. A JNDI server allows resources to be registered and then clients can look up and use these resources. Each EJB is automatically assigned a unique name by the server though it is possible to assign a specific name if desired. This name is then combined with one of three JNDI namespace prefixes to form a complete portable JNDI name.

The following table details the string prefixes and implications.

String prefix

Visibility of the resulting name

"java:global/"

A globally accessible name

"java:app/"

Can only be seen by code in the same application

"java:module/"

Can only be seen by code in the same module

A Java EE application is organized around a series of JAR files. An EJB may be packaged in either an application-ejb.jar or an application-war.war file. The application-ejb.jar can also be packaged within the application.ear file.

Let's look at the syntax for portable global session beans in more detail.

java:global[/<app-name>]/<module-name>/<bean-name>

There are three sections that follow the java:global prefix:

  • <app-name> —This name is optional and is only used if the bean is packaged in an .ear file. The <app-name> is the name of the .ear file minus the file extension. The <app-name> can also be specified in the application.xml file.

  • <module -name>—This is the name of the ejb-jar file or the .war file containing the bean excluding its extension. An explicit name can be specified for the <module-name> using either the ejb-jar.xml or web.xml files.

  • <bean-name>This is the name of the bean. As mentioned earlier, this name is automatically generated but can be given an alias.

The JNDI name used is dependent on the location of the client in relationship to the EJB module. For example, the module namespace can be used for looking up names within the same module.

java:module/<bean-name>

The application namespace can be used for looking up names within the same application.

java:app[/<module-name>]/<bean-name>

Using more than one namespace can make our code more stable and less susceptible to breaking when code changes. For example, we could use a global namespace for a client and a bean within the same module.

java:global/app1/module1/bean1

If the client and bean are moved into a different module then this lookup will fail. However, if we had used the module namespace, the lookup would not fail.

java:module/bean1

EJBs supporting multiple interfaces

Each of the JNDI names may be terminated with [/interface-name] and are only required if the EJB implements more than one business interface. For example, a session bean may implement a local interface and a remote interface.

public class Salutation implements 
  SalutationLocalInterface, 
  SalutationRemoteInterface {

  }

Either of these two names could then be used:

java:global[/<app-name>]/<module-name>/Salutation/ SalutationLocalInterface
java:global[/<app-name>]/<module-name>/Salutation/ SalutationRemoteInterface
 

Creating a simple message-driven bean


Message-Driven Beans (MDB) are used to support asynchronous communication within an application. Typically, they are used in conjunction with a queue. A client will send a message to a queue and the MDB will then process the message in the queue. The client does not call the MDB directly, but instead communicates through messages. The MDB never returns a value to the client.

Java Message Service (JMS) is the basis for communication between a client and the MDB. Fortunately, many of the details needed to use JMS are hidden thus making the job of the EJB developer easier.

In this recipe we show how to create the MDB. In the next recipe, we will modify the SalutationServlet developed in the second recipe to send a message to our MDB.

Getting ready

The creation of an MDB involves three tasks:

  1. Using the @MessageDriven annotation to designate the class as an MDB

  2. Implementing the javax.jms.MessageListener interface

  3. Overriding the onMessage method

Our MDB, which is called SalutationMessageBean, will simply log each time a salutation message is processed.

How to do it...

Open the SalutationApplication and add the SalutationMessageBean to the SalutationApplication-ejb module and the packt package.

@MessageDriven(mappedName = "jms/SalutationQueue", activationConfig =  {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })
public class SalutationMessageBean implements MessageListener {

  public SalutationMessageBean() {
  }

  @Override
  public void onMessage(Message message) {
    try {
      String name = message.getStringProperty("name");
      Logger.getLogger("SalutationLog").log(Level.INFO,
        "Salutation processed", "");
    } catch (JMSException e) {
        throw new RuntimeException(e);
      }
  }

}

The next recipe will demonstrate the use of this MDB.

How it works...

The @MessageDriven annotation is more complex than most annotations but understanding it is by no means insurmountable. The annotation has five possible attributes. For our SalutationMessageBean we used only two of them, mappedName and activationConfig.

The mappedName attribute is the simplest one. It is a vendor-specific name and maps the MDB to a JMS queue. When a message appears in the queue, it is sent to the MDB's onMessage method. We used the name jms/SalutationQueue. This is the name configured by the server and represents the queue we want to use. Most servers provide a way of creating and naming JMS resources, such as a queue.

mappedName = "jms/SalutationQueue",

The activationConfig attribute is concerned with how the MDB works in its environment. This can include issues such as how messages are acknowledged and the type of destination used. We addressed these two issues in our MDB. Nested within the @MessageDriven annotation were two @ActivationConfigProperty annotations. These were used to specify the acknowledgement mode and the destination type.

The @ActivationConfigProperty annotation has a propertyName attribute and a propertyValue attribute. These are used together to specify the name and value of a property. For our MDB the acknowledgement mode was set to "Auto-acknowledge" and the destination type was the javax.jms.Queue interface.

@MessageDriven(mappedName = "jms/SalutationQueue", activationConfig =  {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
    })

When a message arrives at the message queue it is sent to the onMessage method of the MDB. This method has a single parameter, a javax.jms.Message object. Depending on the type of message sent, various methods can be applied against this object to return information needed by the bean. In the earlier code sequence, the value of a name property was returned and used as part of the logging operation.

There's more...

There is a lot more to MDBs than what we have seen here. But let's not spoil the fun; many useful MDB recipes are found in Chapter 3, Message-Driven Beans.

See also

The next recipe shows how to send a message to this MDB.

 

Sending a message to a message-driven bean


Message-Driven Beans (MDB) are used in an asynchronous fashion. A client will create a message and then send it to a queue for processing. The MDB will effectively remove the message from the queue and act on it.

In this recipe, we will use the SalutationServlet to send a message to the queue each time a salutation is processed.

Getting ready

The process consists of two steps:

  1. Adding declarations for a queue factory and a message

  2. Adding code to actually send the message

Review the SalutationApplication project as developed in the Accessing a session bean using dependency injection recipe. We will be modifying the SalutationServlet.

How to do it...

Start by adding declarations for a queue factory and a message queue as instance variables in the SalutationServlet.

  @Resource(mappedName = "jms/SalutationQueueFactory")
  private QueueConnectionFactory queueConnectionFactory;
  @Resource(mappedName = "jms/SalutationQueue")
  private Queue queue;

Next, we need to add code to send the message. This code is placed in front of the servlet's try block. This code can be used regardless of whether the salutation object is instantiated using DI or JNDI. In this code we will create a connection to a server-based queue. Once we have a connection we create a session which serves to facilitate communication. The session creates a message producer which sends the message. And of course, we need to handle exceptions.

This might sound kind of involved but don't worry; most of the individual steps are simple.

  try {
    String message = "Salutation generated";

    Connection connection = queueConnectionFactory.createConnection();
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    MessageProducer messageProducer = (MessageProducer) session.createProducer(queue);
    TextMessage textMessage = session.createTextMessage();
    textMessage.setText(message);
    messageProducer.send(textMessage);
    Logger.getLogger("SalutationLog").log(Level.WARNING,
      "Message sent successfully", "Message sent successfully2");
  } catch (JMSException ex) {
      Logger.getLogger("SalutationLog").log(Level.WARNING,"JMSException in SalutationServlet", "JMSException in SalutationServlet");
    }

How it works...

First, we needed to create a connection to the queue. This step used a connection factory. As you are probably aware, the software factory pattern is used to, among other things, hide the details of how an object is created.

In addition to a connection factory, a destination queue was created. Most IDEs will assist in the creation of these resources. However, it may be necessary to use the server's administration console to create these resources. The connection factory was created by the server, GlassFish in this case, with the name jms/SalutationQueueFactory which is of type QueueConnectionFactory. The @Resource annotation was used to inject it into the servlet.

  
  @Resource(mappedName = "jms/SalutationQueueFactory")
  private QueueConnectionFactory queueConnectionFactory;

The queue is of type javax.jms.Queue and used the name jms/SalutationQueue as defined within the server. The @Resource annotation was used again to inject this resource.

 
  Resource(mappedName = "jms/SalutationQueue")
  private Queue queue;

A try block was needed to catch and handle any JMS exception thrown. Within the try block a message string was defined. This string was sent to the queue. Next, the QueueConnectionFactory object is used to create a QueueConnection. The QueueConnection represents a connection between two point-to-point JMS elements. Any exceptions were handled in the catch block.

  try {
    String message = "Salutation generated";
    Connection connection = queueConnectionFactory.createConnection();
...
  } catch (JMSException ex) {
      Logger.getLogger("SalutationLog").log(Level.WARNING,"JMSException in SalutationServlet", "JMSException in SalutationServlet");
    } 

The next step created a Session object used for sending and receiving messages. The Connection object's createSession method uses two parameters. The first one indicates that the session is part of a transaction. The second argument specifies the type of acknowledgment to be made. Using Session.AUTO_ACKNOWLEDGE meant the session automatically acknowledged the receipt of the message.

Session session = connection.createSession(false, 
Session.AUTO_ACKNOWLEDGE);

The Session object was used to create a MessageProducer. The MessageProducer object was used later in this code sequence to send a message to the destination queue. The queue was used as the argument in the createProducer method.

  MessageProducer messageProducer = (MessageProducer)
    session.createProducer(queue);

Next, a TextMessage was created using the createTextMessage method. A TextMessage is one of several interfaces derived from the Message interface. These JMS interfaces represent different types of messages used within JMS. The setText method assigned a string to be sent.

TextMessage textMessage = session.createTextMessage();
textMessage.setText(message);

The messageProducer then sent the message.

messageProducer.send(textMessage);

The output was displayed in the log file used by the SalutationMessageBean.

INFO: Salutation processed

See also

The previous recipe explains the MDB used in this recipe.

 

Accessing an EJB from a web service (JAX-WS)


Java EE 6 supports Java API for XML Web Services (JAX-WS) based web applications. These are frequently referred to as "big" web services because they use Simple Object Access Protocol (SOAP) XML messages. This protocol provides a standard approach for accessing remote objects. The functionality supported by the service is provided in a Web Services Description Language (WSDL) file. This file is a standard way of describing an application's services.

In this example, we will create a TimeOfDay class with a single method. The method will return a string representing the current date and time. We will use a singleton session bean to support the time service. A singleton is a session bean for which there is one and only one instance ever present in the application.

Getting ready

To create a web service:

  1. Create a supporting EJB for the functionality of the service

  2. Create a class annotated with the @WebService annotation to provide the service

Creating the EJB and web service are both straightforward.

How to do it...

Create a new web application called TODService . Within the application we will create a web service and a stateless EJB. Next, create the singleton EJB in a package called ejb . Add an EJB called TimeOfDay using the @Singleton annotation.

package ejb;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.ejb.Singleton;

@Singleton
public class TimeOfDay {

  private static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss";

  public String timeOfDay() {
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_TIME);
    return simpleDateFormat.format(calendar.getTime());
  }
}

The next step is to create the Web Service. The JAX-WS Web Service is defined using the @WebService annotation. We will use the @EJB annotation to inject the TimeOfDay EJB and then create a single @WebMethod , called timeOfDay .

package service;

import ejb.TimeOfDay;
import javax.ejb.EJB;
import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public class Time {
  @EJB
  private TimeOfDay timeOfDay;

  @WebMethod(operationName = "timeOfDay")
  public String timeOfDay() {
    return timeOfDay.timeOfDay();
  }

}

The easiest way to demonstrate service is to use the testing service available as part of the server. Enter the following URL into a browser to observe the behavior of the service:

http://Localhost:8080/Todservice/Timeservice?Tester

The following screenshot shows the TimeService Web Service Tester. This page is automatically generated and provides a way of testing web services. Since this type of application uses the SOAP protocol to invoke a service, the service tester provides an easier to use graphical technique to test the service. Without this capability the developer would have to develop a more convoluted SOAP message.

Click on the timeOfDay button. The following screenshot displays the string returned. The SOAP request and response used for the service are not shown in the screenshot but can be seen in the window by scrolling down.

How it works...

The TimeOfDay class used a single method, called timeOfDay, which returns a string representing the time. To support the formatting of the string we created another string, DATE_TIME to hold the string's format pattern. This pattern was used with the format method to yield a properly formatted return string.

    private static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss";

The timeOfDay method obtained an instance of the Calendar class. Its getTime method was used to get the current day and time. The SimpleDateFormat class along with the format method were used to format the string. The string is then returned.

The @WebService annotation identifies as a web service provided by the application. This is followed by the class declaration. The TimeOfDay object was injected using the @EJB annotation. Notice that we used the no-interface view of the TimeOfDay EJB. That is, there was no explicit interface defined for the EJB.

The method immediately following the @WebMethod annotation is available for use by the client. The operationName attribute specified the method name as seen by the client.

The timeOfDay method is simple enough. It used the timeOfDay method of the TimeOfDay object.

There's more...

Notice the URL used to test the application TODService contains the context root of the application.

http://localhost:8080/TODService/TimeService?Tester

This value is configured in the application's sun-web.xml file.

...
<sun-web-app error-url="">
<context-root>/TODService</context-root>
...
</sun-web-app>
 

Accessing an EJB from a web service (JAX-RS)


Java EE 6 supports Java API for RESTful Web Services (JAX-RS), a Representational State Transfer (RESTful) web service. This type of service does not require WDSL or XML messages. In this recipe we will create a simple RESTful application, RESTApplication, which returns a random tip of the day message.

The beauty of this application is its simplicity and ease of development. We will create two EJBs: one for the application's functionality and a second one to represent the Web Service.

Getting ready

To create a JAX-RS application we need to:

  1. Create an EJB to support the functionality of the web service

  2. Create a web service EJB annotated with the @Path annotation

The use of annotations makes both of these steps easy to do.

How to do it...

Create a new Web Service called RESTApplication. In this application we will be adding two stateless session beans: TipSessionBean and TipOfTheDay.

Next, create a packt package for the two stateless EJBs. Follow this by creating a stateless session bean, TipSessionBean, to support an application returning a random tip of the day message. Next, we will create the Web Service to access and use the bean.

The TipSessionBean is straight forward. The EJB uses an array of strings to hold the tips. The getTip method randomly returns a tip from the array.

package packt;
import javax.ejb.Stateless;

@Stateless
public class TipSessionBean {
  private final static String tips[] = {
    "I hear and I forget. I see and I remember. I do and I understand", "Study the past if you would define the future", " Life is simple, it's just not easy."};

  public String getTip() {
    return tips[(int)(Math.random()*tips.length)];
  }

}

Now let's turn our attention to the RESTful application. A stateless session bean, called TipOfTheDay, is used to represent the service.

@Path("tipoftheday")
@Stateless
public class TipOfTheDay {
  @EJB
  TipSessionBean tips;

  @GET
  @Produces("text/html")
  public String processGet() {
    return getTip();
  }

  @POST
  @Produces("text/html")
  public String processPost() {
    return getTip();
  }

  private String getTip() {
    return tips.getTip();
  }

}

The service can be tested using an IDE tester or by typing the URL of the service into a browser as illustrated in the following screenshot:

How it works...

At the heart of the TipSessionBean is the getTip method. This method used the Math class' random method to return a double number greater than or equal to 0.0 but is less than 1.0. The return value was multiplied by the length of the array, three in this case. This returned a number between 0 and 2.999997. The result was cast to an integer (between 0 and 2 inclusive) and then used to select the tip.

  public String getTip() {
    return tips[(int)(Math.random()*tips.length)];
  }

In the TipOfTheDay class, the @Path annotation used a string to specify the name of the service. This name is part of the URL used by a client. The class itself used the @EJB annotation to inject the TipSessionBean for the field tips.

The @GET annotation configured the processGet method as the method to use when a HTTP GET request is made. The @Produces annotation specified the type of output as text/html. While we did not actually generate any HTML tags, we could if needed.

Most web applications will support both the GET and POST operations. However, from a Java EE perspective there is little difference between them. This allows us to create one method which handles both requests in the same way.

The processGet method calls a private getTip method of the service. A third method, processPost, was added to POST requests and also called the servlet's getTip method. The getTip method then used the Tip's object to return a tip.

The service can be tested using an IDE tester or typing in the URL of the service into a browser.

There's more...

The actual URL is dependent on the configuration of the application. Consider the URL:

http://localhost:8080/RESTApplication/resources/tipoftheday

The context path for the application is http://localhost:8080/RESTApplication where RESTApplication is the name of the project. The relative URL is /resources as specified in the @ApplicationPath annotation discussed next. The last part, tipoftheday, is specified in the @Path annotation.

When a RESTLess application is created in an IDE such as NetBeans, an ApplicationConfig class is automatically generated. You may be prompted to choose between various options. Normally, the default option will suffice.

This class, shown below, defines the components used in the application and supplies any metadata needed for the application. The ApplicationConfig used for the tip of the day application uses the @ApplicationPath annotation to specify the base URI for all of the resources of the application. Notice that annotations can also be written prefixed with the package name as we sometimes do with Java classes.

package org.netbeans.rest.application.config;

@javax.ws.rs.ApplicationPath("resources")
public class ApplicationConfig extends javax.ws.rs.core.Application {
}

Notice in this example the application path is given as resources. This is why the URL used to test the application uses this string in front of the resource name.

 

Accessing an EJB from an Applet


EJBs can be accessed from a number of different application clients. Here we will see how an EJB can be accessed from an Applet. Applets are still used extensively to provide a richer browser interface than that provided using standard HTML. This includes the use of graphics and animations. Knowing how to access an EJB from an applet gives the applet developer even more opportunities.

Getting ready

Accessing an EJB from an applet uses three steps:

  1. Creating an EJB for the actual functionality

  2. Creating a remote interface

  3. Using JNDI in the applet to obtain a reference to the EJB

The remote interface determines which methods are available to the Applet.

How to do it...

Create two different applications. The first application will be called CapitalApplication, packaged as EJB-JAR, and contains an EJB called CapitalBean. It possesses a method which, when passed the name of a country, returns its capital. The second is a stand-alone JApplet application which uses the CapitalBean.

For this recipe, we will create three classes:

  • CapitalBean containing the desired functionality

  • CapitalBeanRemote exposing the interface used by a client

  • EJBApplet using the CapitalBean

EJBs used outside of a Java EE application normally need to implement a remote interface. This interface specifies the methods available to a client. The CapitalBean EJB implements CapitalBeanRemote interface. This interface has a single method called getCapital.

package packt;
import javax.ejb.Remote;

@Remote
public interface CapitalBeanRemote {
  public String getCapital(String state);
}

The CapitalBean implements the getCapital method using a HashMap initialized with countries and their capitals.

@Stateless
public class CapitalBean implements CapitalBeanRemote {
  private HashMap<String, String> capitals = new HashMap<String, String>();

  public CapitalBean() {
    capitals.put("United Kingdom", "London");
    capitals.put("Japan", "Tokyo");
    capitals.put("India", "New Delhi");
  }

  @Override
  public String getCapital(String country) {
    return capitals.get(country);
  }
}

Create a separate application called CapitalApplet. Add a JApplet called EJBApplet. The applet includes a JButton that when pressed will populate a JTextField with the capital of Japan.

The applet as shown below includes the following methods:

  • initExecutes when the applet starts and calls the initComponents method

  • initComponents Sets up the user interface and enables the JButton

  • invokeEJBUses JNDI to access and use the getCaptial method of the CapitalBean

    public class EJBApplet extends JApplet {
      private JButton invokeButton = new JButton("Invoke EJB");
      private JTextField messageTextField = new JTextField("Waiting for results");
    
      public void init() {
        try {
          java.awt.EventQueue.invokeAndWait(new Runnable() {
            public void run() {
              initComponents();
            }
          });
        } catch (Exception ex) {
            ex.printStackTrace();
          }
      }
    
      private void initComponents() {
        Container container = this.getContentPane();
        container.setLayout(new FlowLayout());
        container.add(invokeButton);
        container.add(messageTextField);
    
        invokeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
            invokeEJB();
          }
        });
      }                    
    
      public void invokeEJB() {
        try {
          InitialContext context =new InitialContext();
          CapitalBeanRemote bean = (CapitalBeanRemote)
          context.lookup(
            "java:global/CapitalApplication/CapitalBean");
          messageTextField.setText(bean.getCapital("Japan"));
          context.close();
                
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    
    }

When setting up the project add libraries for the CapitalApplication (CapitalApplication.jar) and for the server (appserv-rt.jar). These files can be added using the properties tab of the CapitalApplet.

Most IDEs provide a way of executing an applet without actually creating an HTML page for the applet. Use the IDE to execute the EJBApplet. The applet will appear as shown in the following screenshot.

How it works...

The CapitalBean EJB used a HashMap to maintain a list of countries and their capitals. This HashMap was initialized in the constructor. The getCapital method was passed the name of the country and returned the corresponding capital name.

In a HashMap, the first string represents a key (which for us is the name of a country), and a value (which is the country's capital). The put method adds the pair to the HashMap. The get method returns a value based on a key.

The applet InitialContext object bears further explanation. When the applet is created there are at least two JAR files placed on the application's classpath: the CapitalBean EJB JAR and an appserv-rt.jar file.

The EJB JAR contains the class declarations needed for the references to the EJB to be used correctly within the applet. Without this file, the compiler will be unable to know whether we are using the CapitalBean correctly.

The appserv-rt.jar file contains a manifest.mf file. This file contains the information needed to configure the client side of JNDI enabling it to successfully locate a resource and return a reference to it. In our case, the client side was our applet. Unless this JNDI information is configured properly, the InitialContext object may not be constructed correctly. This often results in an annoying naming exception message.

The declarations for the JApplet consisted of a JButton and a JTextField. The init method used a standard Swing technique of creating a thread which works gracefully with the AWTEvent thread to call the initComponents method. The initComponents method created a simple user interface. The invokeButton used an anonymous inner class to call the invokeEJB method when the button is selected.

The invokeEJB method is the interesting part of the applet. An InitialContext object was created and used with a global JNDI name to locate and return a reference to the CapitalBean EJB.

There's more...

It is sometimes useful to examine the applet JNDI context in more detail. The InitialContext object's getEnvironment method returns a Hashtable we can use to list the environmental properties.

The Hashtable consists of key/value pairs which we can iterate through using an Enumeration object. The keys method of the Hashtable returns the Enumeration.

  Hashtable table = context.getEnvironment();
  Enumeration<String> enumeration = table.keys();
  while (enumeration.hasMoreElements()) {
    String key = enumeration.nextElement();
    System.out.println(key + " - " + table.get(key));
  }

One possible list may include the following properties and values:

java.naming.factory.initial - com.sun.enterprise.naming.impl.SerialInitContextFactory
java.naming.factory.url.pkgs - com.sun.enterprise.naming
java.naming.factory.state - com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl

See also

The Accessing the session bean using JNDI recipe, discusses the use of JNDI in more detail.

 

Accessing an EJB from JSP


Yet another way of accessing an EJB is from a JavaServer Pages (JSP) page. While JSP has largely been supplemented by newer technologies such as Ja vaServer Faces (JSF), it is still useful to understand how to incorporate an EJB into a JSP page since you may find yourself maintaining JSP code.

Getting ready

To use an EJB from a JSP client:

  1. Create the supporting EJB

  2. Use JNDI in the JSP client

JNDI is required because JSP does not support DI.

How to do it...

Create a Java EE application called JSPExample. It should contain both a JSPExample-ejb and a JSPExample-war module. In the JSPExample-ejb module, we will create a remote session bean called ConstantsBean with methods returning common math constants. We will place it in the packt package. The JSPExample-war module has an index.jsp from which we will invoke the EJB.

The ConstantsBean is a remote stateless session bean. The bean extends a remote interface, ConstantsBeanRemote, which defines the methods of the bean. These methods include getPI and getGoldenRatio both returning a double value.

@Remote
public interface ConstantsBeanRemote {
  public double getPI();
  public double getGoldenRatio();
}

The ConstantsBean implements this interface and is declared as a stateless session bean. The methods return the Math class PI constant and in the case of the golden ratio the actual golden ratio value.

@Stateless
public class ConstantsBean implements ConstantsBeanRemote {

  public double getPI() {
    return Math.PI;
  }

  public double getGoldenRatio() {
    return 1.6180339887;
  }
}

Create an index.jsp page in the JSPExample-war module. Next, modify the page to invoke and display the result of the EJB's methods.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<%@ page import="packt.ConstantsBeanRemote" %>
<%@ page import="javax.naming.InitialContext" %>
<%@ page import="javax.naming.Context" %>
<html>
<head><title>Constants</title></head>
<body>
<%!
ConstantsBeanRemote constantsBean;
%>
<%
Context context = null;
try {
  context = new InitialContext();
  constantsBean = (ConstantsBeanRemote) context.lookup("java:global/JSPExample/JSPExample-ejb/ConstantsBean");
}
catch(Exception e) {
  e.printStackTrace();
}
%><p>
<h1>Constants</h1>
PI: <%= constantsBean.getPI() %><br>
Golden Rule: <%= constantsBean.getGoldenRatio() %>
</body>
</html>

Execute the application. Its output should be similar to the following screenshot:

How it works...

The ConstantsBean is straight forward; however, the index.jsp page requires more explanation. It invoked and displayed the result of the EJB's methods.

There are three sections of the JSP page referencing and using the bean. The first section declared the reference variable constantsBean.

<%!
ConstantsBeanRemote constantsBean;
%>

The second created the initial context and returned a reference to the bean. Notice the global JNDI name was used to locate the bean.

<%
Context context = null;
try {
  context = new InitialContext();
  constantsBean = (ConstantsBeanRemote) context.lookup(
    "java:global/JSPExample/JSPExample-ejb/ConstantsBean");
}
catch(Exception e) {
  e.printStackTrace();
}
%>

The last section used both methods of the ConstantsBean.

<h1>Constants</h1>
PI: <%= constantsBean.getPI() %><br>
Golden Rule: <%= constantsBean.getGoldenRatio() %>

See also

The Accessing the session bean using JND I recipe, discusses the use of JNDI in more detail.

 

Calling an EJB from JSF


Java Server Faces (JSF) and Facelets have largely supplemented JSP and permit the use of DI. This simplifies access to the EJB but JNDI can be used if desired. JSF uses the concept of a managed bean to hold business logic. In EJB 3.1 it is not necessary to actually use a managed bean. However, both using an EJB directly and using a managed bean to access an EJB will be presented. Knowing how to use the managed bean approach can be useful especially when reviewing older code.

Getting ready

To access an EJB from a JSF page:

  1. Create a supporting EJB

  2. Annotate the EJB with the @Named annotation

In this example we will also package the beans in the .war file to demonstrate this new feature of EJB 3.1. Packaging in .war file makes it easier to access EJBs from a web page.

How to do it...

Create a Java EE application called JSFExample and include only the JSFExample-war module. Be sure to enable contexts and dependency injection when creating the Java EE application. If you don't, you cannot use DI.

We will reuse the ConstantsBean from the JSPExample application detailed in the Accessing an EJB from JSP recipe in this chapter. Create a new package called packt and recreate the ConstantsBean inside of it. However, do not implement the ConstantsBeanRemote interface. Add the following annotation after the @Stateless annotation in the Constantsbean class. This will make the EJB visible to the JSF client.

@Named("constants")

Next, create a JSF managed bean called ConstantsManagedBean. This class will use DI to create and use the ConstantsBean.

@ManagedBean
public class ConstantsManagedBean {

  @EJB
  ConstantsBean constants;
  public ConstantsManagedBean() {
  }

  public double getGoldenRatio() {
    return constants.getGoldenRatio();
  }

  public double getPI() {
    return constants.getPI();
  }

}

To demonstrate the use of both the EJB and the JSF-managed bean, create a JSF page titled index.xhtml.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core">
  <h:head>
    <title>Constants</title>
  </h:head>
  <h:body>
    <f:view>
      <h:form>
        <h:outputLabel for="name">
          <h:panelGrid columns="1">
            <h:outputText value="Managed Bean Length: #{constantsManagedBean.PI}" />
            <h:outputText value="Managed Bean Status: #{constantsManagedBean.goldenRatio}" />
            <h:outputText value="EJB Bean Length: #{constants.PI}" />
            <h:outputText value="EJB Bean Status: #{constants.goldenRatio}" />
          </h:panelGrid>
        </h:outputLabel>
      </h:form>
    </f:view>

  </h:body>
</html>

Execute the application. The following screenshot illustrates its output.

How it works...

The ConstantsBean was explained in the previous Accessing an EJB from JSP recipe. The JSF managed bean, ConstantsManagedBean, was declared as such using the @ManagedBean annotation. DI was used to create and use the ConstantsBean. The managed bean has two methods, getGoldenRatio and getPI, which called the corresponding methods of the ConstantsBean.

The JSF page used both the ConstantsBean directly and the managed bean with h:outputText elements. As a developer you can choose to use either technique though the managed bean approach is no longer necessary.

<h:outputText value=
  "Managed Bean Length: #{constantsManagedBean.PI}" />
<h:outputText value=
  "Managed Bean Status: #{constantsManagedBean.goldenRatio}" />
<h:outputText value="EJB Bean Length: #{constants.PI}" />
<h:outputText value=
  "EJB Bean Status: #{constants.goldenRatio}" />
 

Accessing an EJB from a Java Application using JNDI


It would be nice if we could use dependency injection outside of a server container. However, this is not possible from a Java SE application unless we use an embeddable container. Using an embeddable container is covered in the next recipe. Here we need to use JNDI. Accessing an EJB from a Java SE application using JNDI is similar to using JNDI in other types of applications.

Getting ready

To use this approach we need:

  1. A supporting EJB

  2. JNDI code to obtain a reference to the EJB

We will be using the CapitalApplication developed in the Accessing an EJB from an Applet recipe found in this chapter. This recipe uses a CapitalBean to return the name of the capital given a state. Make sure the server and this application are executing before testing the Java application.

How to do it...

The EJB used here is the CapitalBean. Create a Java SE application using an IDE of your choice. It does not have to be the same one you used to develop the CapitalApplication. In the main method add:

  try {
    InitialContext context = new InitialContext();
    String name = "java:global/CapitalApplication/CapitalBean";
    CapitalBeanRemote bean = (CapitalBeanRemote)context.lookup(name);
    System.out.println(bean.getCapital("India"));
  } 
  catch(javax.naming.NoInitialContextException e) {
    e.printStackTrace();
  }
  catch (NamingException e) {
    e.printStackTrace();
  }

Make sure the application's classpath contains .jar files for the CapitalBean and the appserv-rt.jar file.

When executed, the output should appear as:

New Delhi

How it works...

The application JAR file was needed to resolve the class names and the appserv-rt.jar file was needed so JNDI could function properly. This file provided the necessary information for JNDI to locate the server and look up the name correctly.

See also

The Accessing the session bean using JNDI recipe provides more detail on the use of JNDI.

 

Accessing an EJB from a Java Application using an embeddable container


The embeddable EJB container allows EJBs to be executed outside of a Java EE environment. Standalone Java SE applications can use the embeddable container to execute EJBs. In addition, it can be used for unit testing of EJBs.

The embeddable container does not require the installation of a server. As a result it has a smaller footprint and will start faster. However, MDBs and inbound RMI over IIOP (RMI/IIOP) (Remote Method Invocation (RMI) (Internet Inter-Orb Protocol (IIOP)) calls are not supported. Efficiency features found in the Java EE environment, like clustering, are not available.

How to do it...

Create a standard Java SE application with the following main method.

public class Main {

  public static void main(String[] args) {
    try {
      Map properties = new HashMap();
      properties.put(EJBContainer.MODULES, new java.io.File("E:\\Packt\\Projects\\CapitalApplication\\build\\classes"));
      properties.put(EJBContainer.APP_NAME,"CapitalApplication");
      EJBContainer ejbC = EJBContainer.createEJBContainer(properties);
      Context context = ejbC.getContext();
      String name = "java:global/CapitalApplication/CapitalBean";
      CapitalBeanRemote bean = (CapitalBeanRemote)context.lookup(name);
      System.out.println(bean.getCapital("Japan"));

    } catch (NamingException e) {
        e.printStackTrace();
      }
  }

}

The Java SE application requires a few JAR files be included in its classpath. These include:

  • The embedded EJB container supplied by the server. In the case of GlassFish it is the glassfish-embedded-static-shell.jar file.

  • The javax.ejb.jar file also provided by the server.

  • The JAR file containing the CapitalBean class.

Use the property window of the application to add these files before executing the application.

How it works...

We declared a Map variable called properties and assigned to it a new HashMap. The variable was used to initialize the EJBContainer. This container has a property, MODULES, specifying the modules to be used by the container. The Map object's put method was used to assign the location of the directory containing the CapitalApplication's classes.

The EJBContainer.APP_NAME field was used to specify the name of the application. Next, the EJBContainer class's static method, createEJBContainer, was called with the properties variable as an argument. The createEJBContainer method returns an EJBContainer object. This class's getContext method was used to get a Context object. The Context object represents the environment needed to find and use the CapitalBean.

Next, a portable JNDI name for CapitalBean was used as an argument to the lookup method. This returned an effective reference to the CapitalBean.

The bean variable was used to invoke the getCapital method and to display the results. The last step caught any exceptions thrown.

The output should appear as:

Tokyo

Note

The embeddable container is a new EJB 3.1 feature. Not all development environments or servers support this feature. Using NetBeans 6.91 with GlassFish 3.0.1 may not work consistently. However, NetBeans 7 Beta does provide better support.

See also

The previous Accessing an EJB from a Java Application using JNDI recipe, provides an alternative technique for accessing EJBs.

 

Accessing the EJB container


An EJB will always reside inside of an EJB. Normally, this container is part of the server. There are times when it is desirable for the EJB to gain access to this container. This access is provided through an instance of the EJBContext interface, which represents the container holding the current bean. The object provides methods to access various aspects of the container including:

  • Security issues

  • Transactions

  • Access to the timer service of the bean

  • References to objects available in the JNDI registry

  • An object allowing the methods of the bean to be invoked

In this recipe we will obtain a SessionContext object for the Salutation EJB developed in the Creating a Simple Session Bean recipe.

How to do it...

The Salutation bean developed in the first recipe will be modified. First, we start to modify the bean by adding a SessionContext object. The easiest way of obtaining a SessionContext object is to use dependency injection. In order to inject a SessionContext object we will need to use the @Resource annotation. Both the annotation and the SessionContext declaration require imports.

import javax.annotation.Resource;
import javax.ejb.SessionContext;

Next we add the @Resource annotation and declare our SessionContext variable context as a field of the class.

@Stateless
public class Salutation {
...
  @Resource
  private SessionContext context;
...

Next, create a getContextInformation method returning a string. We can use the StringBuilder class to build a string containing context information. There are several SessionContext methods available. The result of these methods is appended to contextInformation variable.

  public String getContextInformation() {
    StringBuilder contextInformation = new StringBuilder();
    contextInformation.append(context.toString() + "<br/>");
    try {
      contextInformation.append(context.getInvokedBusinessInterface().toString() + "<br/>");
    } catch (IllegalStateException e) {
      contextInformation.append(e);
      }
    return contextInformation.toString();
  }

The simplest way to demonstrate the use of the method is to modify the SalutationServlet. Add the getContextInformation method call after the statement where the getFormalGreeting method is used.

  out.println("<h1>" + salutation.getFormalSalutation("Sherlock Holmes") + "</h1>");
  out.println("<h2>" + salutation.getContextInformation() + "</h2>");

Execute the servlet using the URL http://localhost:8080/SalutationApplication-war/SalutationServlet as illustrated in the following screenshot:

How it works...

The stateless session bean, as we used it, limits the amount of useful context information available. In the example, we only displayed a string to represent the SessionContext object and the business interface used by the client, neither of which are terribly exciting. Since the Salutation EJB used a no-interface view, we get back the class name. An EJB not implementing an interface is said to have a no-interface view.

There's more...

The EJBContext is the super class for SessionContext. It possesses methods common to the three sub-interfaces of the EBJContext interface:

  • SessionContext for Session Beans

  • MessageDrivenContext for MDB

  • EntityContext for an Entity

Always choose the corresponding context interface for the EJB or entity in use. The EJBContext can be obtained using either dependency inject or JNDI. We have already seen how dependency injection can be used. If we need to use JNDI instead, we need to follow the standard JNDI look up process:

  1. Establish an initial context

  2. Use the lookup method to locate the object

  3. Use the methods of the object

      public String getContextInformationJNDI() {
        SessionContext sctxLookup;
        try {
          InitialContext ic = new InitialContext();
          sctxLookup = (SessionContext) ic.lookup("java:comp/EJBContext");
        } catch (NamingException ex) {
            return "NamingException: " + ex.toString();
          }
        return sctxLookup.toString() + "<br/>" +
        sctxLookup.getInvokedBusinessInterface().toString() + "<br/>";
      }

Notice the structure of the JNDI look up string, java:comp/EJBContext. It is different from the previous JNDI names we have seen. The java:comp prefix is used to allow applications to expose their components. In this case, it specifies the standard name for a SessionContext.

About the Author

  • Richard M. Reese

    Richard M. Reese has worked in both industry and academia. For 17 years, he worked in the telephone and aerospace industries, serving in several capacities, including research and development, software development, supervision, and training. He currently teaches at Tarleton State University, where he has the opportunity to apply his years of industry experience to enhance his teaching. Richard has written several Java books and a C pointer book. He uses a concise and easy-to-follow approach to the topics at hand. His Java books have addressed EJB 3.1, updates to Java 7 and 8, certification, jMonkeyEngine, natural language processing, functional programming, networks, and data science.

    Browse publications by this author

Latest Reviews

(1 reviews total)
Good
Book Title
Access this book, plus 7,500 other titles for FREE
Access now