Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Web Application Development with JSP and XML-- Part IV: Using J2EE Services from JSP

 
 

Articles Index

and XML

By Qusay H. Mahmoud
October 2001

The Java 2 Enterprise Edition (J2EE) is a standard that defines an environment for the development and deployment of enterprise applications. It reduces the cost and complexity of developing multitier enterprise applications as it provides a multitier distributed application model. In other words, it is inherently distributed and therefore the various parts of an application can run on different devices.

Web applications developed using JavaServer Pages (JSP) may require some interaction with J2EE services. For example, a web-based inventory control system may need to access J2EE's directory services to gain access to a database. Or you may want to use Enterprise JavaBeans (EJB) in your application.

This article presents a brief overview of J2EE, then it shows how to:

  • Describe J2EE services in a Web Deployment Descriptor (web.xml)
  • Reference J2EE services
  • Access and use J2EE services from JSPs

Overview of J2EE

The J2EE is a standard platform for the development and deployment of enterprise applications. The architecture of J2EE, which is component-based, makes developing enterprise applications easy because business logic is organized into reusable components and the underlying service is provided by J2EE in the form of a container for every component type. Think of a container as the interface between the component and the low-level functionality that supports the component. Therefore, before an application client component can be executed, it must be configured as a J2EE service and deployed into its container.

The standard services included in version 1.3 of the J2EE specification and a brief description of each is shown in Table 1.

Table 1: J2EE Standard Services
Standard Service Description
HTTP Defines HTTP service where the client-side API is defined by the java.net package, and the server-side API is defined by the Servlet API (including JSP). HTTPS, or the use of HTTP over Secure Socket Layer (SSL), is supported by the same client and server APIs as HTTP.
Enterprise JavaBeans (EJBs) A component model for enterprise development in Java.
Java Transaction API (JTA) An interface for J2EE application components for handling transactions.
RMI-IIOP Defines APIs that allow for the use of RMI-style programming that is independent of the underlying protocol. J2EE applications are required to use RMI-IIOP when accessing EJB components.
Java IDL Allows J2EE applications to invoke CORBA objects using the IIOP protocol.
JDBC API for accessing databases.
Java Message Service (JMS) API for messaging that supports point-to-point and publish-subscribe models.
Java Naming and Directory Interface (JNDI) API for naming and directory access to J2EE resources.
JavaMail A standard API for sending email.
JavaBeans Activation Framework (JAF) A standard API used by JavaMail.
Java API for XML Parsing (JAXP) A standard API for parsing XML documents. It includes support for both SAX and DOM. See Parsing XML for more info.
J2EE Connector Architecture A standard API for allowing connectivity to legacy systems and non-Java enterprise applications.
Java Authentication and Authorization Service (JAAS) A standard API for enabling J2EE services to authenticate and enforce access controls upon users.

J2EE promotes the development of multitier applications in which the web container hosts web components that are dedicated to handling a given application's presentation logic, and responds to requests from the client (such as the web browser). The EJB container, on the other hand, hosts application components that respond to requests from the web tier as shown in Figure 1.


Figure 1: Multitier Applications

Applications that use this architecture are implicitly scalable. This architecture decouples the accessing of data from end-user interactions, and encourages component-based code reusability. At the web tier, J2EE promotes the use of JSPs for the creation of dynamic content for Web clients.

Custom Tags and J2EE

J2EE has a lot to offer to Web application developers and the JSP custom tag developer. As you can see from Table 1 above, it has a rich set of standard APIs for sending email, accessing databases, parsing XML documents, and so on. Your Web applications can benefit greatly from these APIs. For example, you can write a JSP custom tag for sending email that can be used easily by Web content developers who are not familiar with Java. If you are not familiar with JSP custom tags, their benefits, and how to create them, please refer to Developing JSP Custom Tags.

EJBs

An EJB is a server-side component that encapsulates the business logic of an application. In any application, the enterprise beans implement the business logic in methods, which can be invoked by remote clients to access the relevant services provided by the application.

Benefits

EJBs simplify the development of large, secure, distributed enterprise applications for the following reasons:

  • Developers can concentrate on solving business logic: the EJB container provides system-level services such as transaction management and security authorization. Therefore, developers do not have to worry about these issues.
  • Thin clients: developers do not have to develop code for business rules or database access; they can concentrate on the presentation of the client. The end result is that clients are thin, and this is especially important for clients that run on small devices with constrained resources.
  • Faster development: EJBs are portable components, and therefore application assemblers can build new applications from existing beans. The resulting applications can run on any J2EE-compliant
  • server.

Components

There are two main types of EJB components: session and entity. A session EJB is used to perform a task for a client, and an entity EJB is domain specific and is used to represent a business entity object that exists in persistent storage. Session and entity beans are, however, different in some ways, as described in Table 2.

Table 2: Session vs. Entity EJB
Session EJB Entity EJB
Transient Persistent
Can be used by a single client Can be used by many clients
Has no identity Has an identity (such as primary key)

Developing EJBs

To develop EJBs, each enterprise bean needs:

  • A remote interface that exposes the methods the enterprise bean supports.
  • A home interface that provides life cycle methods for the enterprise bean.
  • An implementation class, including the business logic it needs.

EJBs vs. Servlets

At first encounter, EJBs and Servlets are similar technologies since they are both distributed server-side components. There is however, a major difference between the two in the type of solution they offer; EJBs cannot accept HTTP requests. In other words, EJBs cannot serve requests coming directly from a Web browser, and servlets can. Servlets and JSPs can be used to implement Web presentation and control but unlike EJBs, they cannot handle distributed transactions. EJBs can be called from any Java-based client.

When to use EJBs

EJBs are a good fit if your application has any of these requirements:

  • Scalability: if you have a growing number of users, EJBs let you distribute your application's components across multiple machines with location transparency to clients.
  • Data integrity: EJBs give you easy to use distributed transactions.
  • Variety of clients: if your application will be accessed by a variety of clients (such as traditional browsers or WAP browsers), EJBs can be used for storing the business model, and a variety of clients can be used to access the same information.

Describing and Referencing J2EE Services

Now that we have seen an overview of J2EE and EJBs, we will now see how to reference, access, and use such services. Fortunately, the J2EE specification defines a standard way for accessing and using such services. J2EE services can be referenced by looking them up according to a unique name in a directory. This functionality is supported by the Java Naming and Directory Interface or JNDI. In order for this to work, each J2EE-compliant system provides a JNDI service called an environment that contains:

  • Environment variables
  • EJB references
  • Resource factory references

Environment Variables

The application component's naming environment allows the application component to be customized without the need to access or change the application component's source code. Each application component defines its own set of environment entries. All instances of an application component within the same container share the same entries. It is important to note that application component instances are not allowed to modify the environment at runtime.

Declaring Environment Variables

The application component provider must declare all the environment entries accessed from the application's component code. They are declared using the <env-entry> tag in the deployment descriptor (web.xml in Tomcat for example). The elements of the <env-entry> tag are:

  • <description>: an optional description of the environment entry.
  • <env-entry-name>: the environment entry name.
  • <env-entry-type>: the expected environment variable type. It can be one of the following Java types: Boolean, Byte, Double, Character, Float, Integer, Long, Short, String.
  • <env-entry-value>: a value for the environment entry that must match the type supplied within the <env-entry-type>. This value can be changed later, but if it is not set then one must be specified during deployment.

The example in Code Sample 1 shows a declaration of two environment entries. To specify a declaration for a new environment, you simply add it to your Web application descriptor (web.xml).

Code Sample 1: Declaring environment variables

<env-entry>
<description>welcome message</description>
<env-entry-name>greetings</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>Welcome to the Inventory Control 
                           System</env-entry-value>
</env-entry>

<env-entry>
<description>maximum number of products</descriptor>
<env-entry-name>inventory/max</env-entry-name>
<env-entry-type>java.lang.Integer</env-entry-type>
<env-entry-value>27</env-entry-value>
</env-entry>

Each <env-entry> tag describes a single environment entry. So, in this example, two environment entries have been defined, the first one is named greetings, which is of type String and has an initial default value of: Welcome to the Inventory Control System. The second entry is named inventory/max, which is of type Integer and has an initial default value of 27.

Now, an application component instance can locate the environment entry using JNDI. It creates a javax.naming.InitialContext object using the constructor with no arguments. It then looks up the naming environment through the InitialContext using the JNDI URL which starts with java:comp/env. Code Sample 2 shows how an application component accesses its environment entries.

Code Sample 2: Accessing environment entries

// obtain the application component's environment
// naming context
javax.naming.Context ctx = 
new javax.naming.InitialContext();
javax.naming.Context env = 
ctx.lookup("java:comp/env");

// obtain the greetings message 
//configured by the deployer
String str = (String) env.lookup("greetings");

// use the greetings message
System.out.println(greetings);

// obtain the maximum number of products 
//configured by the deployer
Integer maximum = (Integer) env.lookup(
"inventory/max");
//use the entry to customize business logic

Note that the application component may also look up environment entries using the full path names as follows:

javax.naming.Context ctx = 
new javax.naming.InitialContext();
String str = (String) ctx.lookup(
"java:comp/env/greetings");

This snippet of code can be used in a JSP as shown in Code Sample 3:

Code Sample 3: Accessing environment entries from a JSP

<HTML>
<HEAD>
<TITLE>JSP Example</TITLE>
</HEAD>
<BODY BGCOLOR="#ffffcc">
<CENTER>
<H2>Inventory System</H2>
<%
javax.naming.Context ctx = 
new javax.naming.InitialContext();
javax.naming.Context myenv = 
   (javax.naming.Context) t.lookup("java:comp/env");
java.lang.String s = (java.lang.String) 
    myenv.lookup("greetings");
out.println("The value is: "+greetings);
%>
</CENTER>

</BODY>
</HTML>

Ultimately, however, you would want to access the environment entries from a custom tag. So, you would develop a JSP custom tag or a tag library that can be reused without cutting and pasting code. A custom tag library can be easily developed following the guidelines and how-tos described in Developing JSP Custom Tags.

EJB References

The application component's provider can refer to EJB homes using logical names (called EJB references) instead of JNDI registry values. They are special references in the application component's naming environment. These references allow Web applications to access EJBs in a customized fashion.

Declaring EJB References

An EJB reference is an entry in the application component environment. However, <env-entry> must not be used to declare it. Instead, it must be declared using the <ejb-ref> tag of the web deployment descriptor. The elements of the <ejb-ref> tag are:

  • <description>: an optional descriptor of the EJB reference entry.
  • <ejb-ref-name>: a unique EJB reference name.
  • <ejb-ref-type>: specifies the expected type of the EJB. The value must either be Session or Entity.
  • <home>: specifies the full class name of the EJB's home interface.
  • <remote>: specifies the full class name of the EJB's remote interface.

The example in Code Sample 4 shows a declaration of an EJB reference entry. To specify a declaration for a new entry, you simply add it to your Web application descriptor (web.xml).

Code Sample 4: Declaring an EJB reference

<ejb-ref>
  <description>A reference to an entity bean to 
          access employee records</description>
 <ejb-ref-name>ejb/EmployeeRecord</ejb-ref-name>
 <ejb-ref-type>Entity</ejb-ref-type>
 <home>com.company.Employee.EmployeeRecordHome</home>
 <remote>com.company.Employee.
            EmployeeRecordRemote</remote>
</ejb-ref>

Each <ejb-ref> element describes a single EJB reference entry. So, in this example, one entry has been defined, which is named ejb/EmployeeRecord of type Entity specifying the home interface to be com.company.Employee.EmployeeRecordHome and the remote interface to be com.company.Employee.EmployeeRecordRemote.

Now, an application component instance can locate the EJB reference entry using JNDI. It creates a javax.naming.InitialContext object using the constructor with no arguments. It then looks up the naming environment through the InitialContext using the JNDI URL which starts with java:comp/env/ejb. Code Sample 5 shows how an application component gains access to an EJB.

Code Sample 5: Accessing an enterprise bean

// obtain the default JDNI context
javax.naming.Context ctx = 
new javax.naming.InitialContext();

// look up the home interface
Object obj = ctx.lookup(
"java:comp/env/ejb/EmployeeRecord");

// Convert the object to a home interface
EmployeeRecordHome = (EmployeeRecordHome) 
  javax.rmi.PortableRemoteObject.narrow(
  object, EmployeeRecordHome.class);

You can either use similar code directly in your JSPs, or develop a custom tag library for accessing and using EJBs.

Resource Factory References

Resource factory references allow applications to refer to connection factories, or objects that create connections to desired resources, using logical names as we have seen in the previous two sections. The resource connection factory references can be JDBC connections, JMS connections, email connections, and so on. The JNDI URLs start with: java:comp/env/jdbc, java:comp/env/jms, and java:comp/env/mail, respectively.

Declaring Resource Factory References

A resource factory reference is an entry in the Web application deployment descriptor. It must be declared using the <resource-ref> tag. The elements of the <resource-ref> tag are:

  • <description>: an optional descriptor of the resource factory reference.
  • <res-ref-name>: contains the name of the environment entry.
  • <res-ref-type>: specifies the resource factory used. Some of the J2EE standard resource factories include: javax.sql.DataSource for JDBC connection factories; javax.jms.QueueConnectionFactory and javax.jms.TopicConnectionFactory for JMS connections; and javax.mail.Session for JavaMail connection factories.
  • <res-auth>: Specifies the resource authentication type and how it should be performed. If it is set to Container for example, then the container does the authentication using properties configured during deployment. On the other hand, if it is set to Application, this instructs the container to let the application authenticate programmatically.

Code Sample 6 shows a declaration of an email resource reference factory. To specify a declaration for a new entry, you simply add it to your Web application descriptor, web.xml.

Code Sample 6: Declaring a resource factory reference

<res-ref>
 <description>email session reference 
                factory</description>
 <res-ref-name>mail/mailsession</res-ref-name>
 <res-type>javax.mail.Session</res-type>
 <res-auth>Container</res-auth>
</res-ref>

Each <res-ref> element describes a single resource factory reference entry. So, in this example, one entry has been defined, which is named mail/session of type javax.mail.Session setting the <res-auth> to Container.

Now, an application component instance can obtain the resource factory reference entry using JNDI. As with other entries, it creates a javax.naming.InitialContext object using the constructor with no arguments. It then looks up the naming environment through the InitialContext using the JNDI URL for email which starts with java:comp/env/mail. Code Sample 7 shows how an application component obtains a reference to a resource factory to send an email message.

Code Sample 7: Obtaining a reference to a resource factory and sending email

// obtain the initial JNDI context
javax.naming.Context ctx = 
new javax.naming.InitialContext();
// perform JNDI lookup to retrieve 
//the session instance
javax.mail.Session session = 
(javax.mail.Session) 
    ctx.lookup(
            "java:comp/env/mail/mailsession");
// create a new message and set the sender,
// receiver, subject, and content of msg
javax.mail.Message msg = new 
     javax.mail.internet.MimeMessage(session);
msg.setFrom("email address goes here");
msg.setRecipient(
Message.RecipientType.TO, "to email address");
msg.setSubject("JavaMail Example");
msg.setContext(
      "write the content here", "text/plain");
// send message
javax.mail.Transport.send(msg);

Again, this code can be used directly in your JSPs, or you can develop a custom tag library for accessing and using various resource factory references.

As another example, Code Sample 8 shows a declaration of a database resource factory.

Code Sample 8: Declaring a database resource factory

<res-ref>
  <description>database reference 
                         factory</description>
  <res-ref-name>jdbc/EmployeeDB</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
</res-ref>

Code Sample 9 shows how an application component obtains a reference to a database connection factory and uses it.

Code Sample 9: Obtaining a reference to a database connection factory and using it

// obtain the initial JNDI context
javax.naming.Context ctx = 
new javax.naming.InitialContext();
// perform JDNI lookup to 
//obtain database connection factory
javax.sql.DataSource ds = 
(javax.sql.DataSource) 
    ctx.lookup("java:comp/env/jdbc/EmployeeDB");
// Invoke factory to obtain a resource
javax.sql.Connectin conn = ds.getConnection();
// use the connection....

Conclusion

J2EE offers many services that are invaluable for Web applications. These services range from opening a connection to a database using JDBC, to sending an email, to accessing and using enterprise beans. This article, along with sample programs, shows how to access J2EE services from within JSPs. Incorporating EJBs into your JSPs can be easily done, creating a reusable solution by developing custom tags.

Why don't we access J2EE services from Servlets? While it is possible to do that, you would end up writing more unreusable code. If you wish to use J2EE services from JSPs, developing custom tag libraries provides reusable solutions that can even be used by content developers who have no Java experience.

For more information

J2EE
Enterprise JavaBeans
Java Naming and Directory Interface
JSP
JSP Tag Libraries
Jakarta Tomcat 4
Jakarta Taglibs Project Description
JSR-52: A Standard Tag Library for JavaServer Pages

About the author

Qusay H. Mahmoud provides Java consulting and training services. He has published dozens of articles on Java, and is the author of Distributed Programming with Java (Manning Publications, 1999).