Senin, 09 Juli 2007

MySQL System Architecture

In this article, we're going to take a look at MySQL internals. It will be a fun, informative examination of how all the different pieces and parts of the MySQL server operate together. MySQL's implementation is a fascinating mix of technology that is truly a remarkable achievement—an achievement born from the sweat and inspiration of numerous developers over many years.

One of the joys of open-source technology is just that: it's open source! On a system as large as MySQL,1 taking a look at the source code gives you a true understanding of the dilemmas faced by the developers over the course of the software evolution. In this article, we'll investigate the source code of the server itself, so put on your hard hat. We encourage you to take a look at the source code, even if you have no intention of making any changes. You will gain an appreciation of the enormity of the tasks undertaken by the development team at MySQL AB, as well as gain a much deeper understanding of how the software works, and thus how you can optimize your programs to best utilize MySQL's strengths and avoid its weaknesses.

The information presented in this article comes from an analysis of both the internal system documentation and the actual source code for the MySQL database server system. Because MySQL is an evolving code repository, since press time, some of the design features explained here have likely changed and will continue to do so over time. If you look at the source code from one version to the next, you'll notice variations in the implementations of subsystems and how they interrelate; however, much of the way in which the system generally functions has persisted over the evolution of the software.

Even if you're not a C programming guru, you should be able to follow most of what we'll cover here. The focus will be less on the code itself and more on the structure and flow of operations within the server, and how the different code libraries interact with each other. Our intention is to provide a basic road map from which you can navigate the source code and documentation yourself. However, there are a few sections of this article that require a significant knowledge of C and C++ programming, and are meant for more advanced readers. If you don't have a whole lot of experience in C programming, just do your best to follow along, and don't worry about it too much!

The MySQL Source Code and Documentation

Since we're going to be looking at the MySQL server source code, you'll want to download a copy of the latest MySQL source code so that you can follow along, as well as embark on your own code review adventures. The source code used in this article comes from a copy of the source code for version 5.0.2. To download a copy of the source code, head over to MySQL's download site (http://dev.mysql.com/downloads/mysql/5.0.html) and download the version of interest to you.

Caution: The source distribution we used for this article's analysis came from the 5.0.2-alpha source tree. Bear in mind that MySQL is an evolving piece of software, and as such, various implementation details discussed in this article may change over time. Always obtain the proper source versions of development documentation before you assume anything is the case for a particular version of MySQL.

The Source Code

The source code is organized into a shallow directory tree containing the major libraries of the MySQL server and its different extensions.

Top-Level Directories

Table 1 shows all the major top-level directories, with a brief description of the files contained in each directory and the general purpose of those files. As we progress through the article, we'll break down the information in this table into smaller groups that relate to each subsystem, but you may use this larger table as a reference.

Table 1. Top-Level Directories in the Source Tree

Directory Contents
/bdb The Berkeley DB storage engine handler implementation files
/BUILD Program compilation files
/client The mysql command tool (client program) implementation files
/data The mysql database (system database) schema, data, and index files
/dbug Debugging utility code
/Docs The documentation, both internal developer documents and the MySQL online manual
/heap The MEMORY storage engine handler implementation files
/include Core system header files and type definitions
/innobase The InnoDB storage engine handler implementation files
/isam The old ISAM storage engine handler implementation files
/libmysql The MySQL C client API (all C source and header files)
/libmysqld The MySQL server core library (C, C++, and some header files)
/libmysqltest A simple program to test MySQL
/merge The old Merge storage engine handler implementation files
/myisam The MyISAM storage engine handler implementation files
/myisammrg The MyISAM Merge storage engine handler implementation files
/mysys The core function library, with basic low-level functions
/regex The regular expression function library
/scripts Shell scripts for common utilities
/share Internationalized error messages
/sql The meat of the server's implementation, with core classes and implementations for all major server and client activity
/sql- bench MySQL benchmarking shell scripts
/strings Lower-level string-handling functions
/support-files Preconfigured MySQL configuration files (such as my-huge. cnf)
/tests Test programs and scripts
/vio Network/socket utility functions, virtual I/O, SSL, and so on
/zlib Compression function source files

You can take some time now to dig through the source code a bit, for fun, but you will most likely find yourself quickly lost in the maze of classes, structs, and C functions that com-pose the source distribution. The first place you will want to go is the documentation for the distribution, located in the /Docs directory. Then follow along with us as we discuss the key subsystems and where you can discover the core files that correspond to the different system functionality.


NetBeans: Introductions to the Open-Source Project, More Than an IDE

NetBeans is more than an IDE. It is also an open-source project, community, and a rich client application platform. There is certainly more to NetBeans than just a free IDE. In this new series of articles about NetBeans I hope to introduce you to not only the NetBeans IDE but also the project as a whole.



Click here for a larger image.

Figure 1: NetBeans IDE

The NetBeans Integrated Development Environment

The NetBeans IDE is an open-source IDE supporting Java Mobile, Standard, and Enterprise editions. It also supports development of NetBeans Rich Client Platform, HTML, XML, JavaScript, and other scripting languages and technologies. The IDE itself is a NetBeans RCP application.

Other standards and APIs are supported "out of the box" including but not limited to JavaBeans, Struts, Java Server Faces, JUnit, and ANT projects. Others are supported by add-on plug-ins such as Apache Maven and Maven2 and UML. UML along with some other features including Ruby applications will be available after install starting with NetBeans version 6. In my next article I hope to specifically address new features you will find in NetBeans 6.0.

The IDE also includes features that are common to Java IDEs. These features include an integrated editor with source code refactoring support, visual designers for certain technologies including Swing user interfaces, web applications and web services support, and projects which can be built from the command line without the IDE. There are too many features to address in a single article, but I will attempt to address many of them in the coming months.

Aside from Ruby and JavaScript mentioned above, there are other technologies being added to the IDE. These include PHP and operating system scripts such as Bash and Windows Batch files. The new JavaFX scripting language is also being added. This will provide many visual capabilities not previously available to Java developers such as dynamic presentation style effects Flash developers have enjoyed. Many others will come as NetBeans now has a generic language framework, known as Schliemann, for easily adding different language support to the IDE.

Plug-ins (Modules)

Using the NetBeans RCP as its base, the IDE supports plug-ins. These are first class citizens with their own project support accessible in the IDE using File|New Project and category NetBeans Plug-in Modules. This makes it easy to add support for your own custom needs to the IDE. It is also how the NetBeans developers keep adding extra functionality while keeping the existing functionality, and it provides the capabilities to upgrade individual sections or functionality of the IDE.

I currently have two modules listed on the NetBeans Plug-in Portal that do this. One helps clean up large directories, such as copies of large open-source projects, without consuming too much disk and CPU resources, and the other makes working with text embedded in Java sources and external tools, including SQL, XML, and HTML, easier. Many others have done as I, and most of the modules are free. I suggest looking over the plug-in portal as you may find something useful.

The NetBeans Rich Client Platform

The NetBeans RCP, as other RCP packages, is a framework and set of utility APIs which help developers create feature rich applications more easily. It takes care of many features that are common to desktop applications such as context menus, extensions or plug-ins that are called modules in NetBeans lingo, integrated data views, user preferences, and persistence between application sessions.



Click here for a larger image.

Figure 2: Simple NetBeans Rich Client Platform paint application

There are many utilities and packages that applications can build atop. For instance, many 3rd party applications need custom editors, so editors are not unique to IDEs, and the NetBeans RCP provides this. There is a visual library that can be used to develop a wide range of functionality including graphing and reporting and diagramming tools such as UML or Organization Chart designers. There are many others for you to examine.

The RCP also helps integrate your application into the operating system. The RCP project support in the IDE can generate application launchers for Windows, Mac OS X, and general Unix and Linux. The common components and Swing extensions also have UI delegates defined for different look and feels. Coupled with standard Swing look and feel support these are things you as the developer no longer have to worry about.

You can examine the IDE to get a feel of what is available in the Platform. You can install and test it on different operating systems. You can also view the current API documentation. Based on the NetBeans RCP, the IDE sources are a good resource for developing RCP applications. They provide many working examples.

As I mentioned in the IDE section, plug-in development is supported directly in the IDE. This extends to RCP applications. For IDE plug-ins and RCP development there are many wizards and utilities to make things easier. Not that it can't be done, but this is much easier than trying to do it all by hand in something like a text editor or some other development environment. Aside from your specific functionality and code, most things can be added to your application with a few clicks and completing a few text fields in NetBeans.



Click here for a larger image.

The introduction to the NetBeans community begins on the NetBeans home page. This is usually with a download of the IDE. From the home page you can find links to most community information. There is a lot of it and it can be a little overwhelming to new comers.

Mailing Lists

One of the first things you should do is sign-up for the mailing lists or use Nabble to use the mailing lists like a forum. Some have complained about not having a forum or a news server. With Nabble you do not need anything extra. Simply use the mailing list like a forum and search the messages and view them by thread without having to actually download all the messages. The only difference between this and a news server and client is the message headers are not downloaded to your system. Either way, the mailing lists are a good resource for getting help with the different facets of NetBeans and offer good, free support.

Each mailing list has an archive available from the mailing lists page. It is good netiquette to attempt to search the archives for previous answers before posting a new question. The point being many members are community volunteers and just as busy as everyone else, so please respect their time as much as your own. This helps everyone.

Internet Relay Chat (IRC)

Next, there is an Internet Relay Chat (IRC) channel on irc.freenode.org called #netbeans. This has been around for a while, and is now starting to get more users, so if you had previously tried to use it you might want to try again. Some of the Dream Team members try to frequent the channel and help users as they can along with other helpful community members.

Freenode has a neat tool that allows IRC users to connect from behind firewalls. You can also directly access the IRC channel or link to it from your web site. This is a Java Applet that communicates with another server over HTTP and redirects your messages and others to and from the IRC server. This will come in very handy if you cannot use IRC because your company network blocks a port.

Remember, when using IRC, others are usually working too. So, when you ask a question, it may take up to an hour before a reply is made and other times it may take only seconds. If you come in, ask a question, and leave the channel too fast, you may never see the reply, so try to have patience for your own benefit.

Code Samples

You will find the different samples included with the IDE very helpful. They directly demonstrate aspects of the technologies supported by NetBeans. Look in the IDE under File|New Project and category Samples to see what is available. Then, if you cannot find what you are looking for, visit the Sample Catalog on-line. The samples on-line are usually part of a set of plug-ins known as a pack or part of an individual module. Once you find the ones you need, you can install them into the IDE through the update center.

The samples in the IDE create projects that you can use as complete code and resource examples. The good thing about this is they are pre-built so you can dig into them; get a feel for what is capable, and how to do it while being able to run them. This, coupled with specifications, documentation, and possibly a tutorial covering the used technologies, can get you up to speed on something faster than trying to put all the pieces together yourself.



Click here for a larger image.

Figure 4: Project samples

There is also the Java Blueprints Solution Catalog accessible in the IDE through Help|Java Blueprints Solution Catalog. There are many examples of different EE technologies. Along with code samples, there are complete tutorials and documents written by experts to help get you going. This is a sub-set of what is available on the Java Blueprints Solution Catalog project web site.



Click here for a larger image.

Figure 5: Java Blueprints Solution Catalog

Documentation

Beyond the mailing lists, IRC, and samples, there is a lot of on-line documentation. I suggest first accessing Help|Help Contents and Help|Tutorials from inside the IDE. Then, if you cannot find what you need, access the different on-line resources. This may save you some time. Many features of NetBeans are documented in the IDE help including the default keyboard shortcuts through Help|Keyboard Shortcuts.

The NetBeans Docs & Support page is easily located from the NetBeans home page as a tab. There are documents available for the standards and technologies supported by the NetBeans IDE functionality. These range Mobile, Standard, and Enterprise Java as well as SOA and BPEL technologies among others. They include tutorials/learning trails, references, demos, and sample applications. Here you will also find links to different areas of the NetBeans Wiki though the links are not specifically identified as linking to the Wiki.



Click here for a larger image.

Figure 6: IDE Help

Wiki

The NetBeans Wiki contains much information. It is such a valuable resource it really deserves to have a visible link to it from the Docs & Support page. Something like "NETBEANS WIKI HERE" would work for me. Not only will you find information created by NetBeans developers, but also many community members have created documents based on their experience in areas where documentation is lacking or from a different perspective you may find more useful. You will also find information related to development of the IDE and the RCP.

Beyond Documentation and Help: Digging into NetBeans

If getting into the innards of the project is more your forte, you will find the Community page useful. From here you can access the Release Roadmap for a quick peek at what is on the horizon or the past. You will also find information on the different NetBeans teams, contributing, where to get the sources and how to build them, NetBeans development guidelines and processes, the different projects/modules home pages, and the NetBeans issue tracking system Issuezilla.

Issuezilla is a good resource even if you do not plan on working with the sources yourself. Anyone can create issues or requests. This is how the development team knows what issues you are having with the software or different areas of the project including the NetBeans web site and project infrastructure such as CVS. It is how bugs get fixed and problems are resolved; general usage issues should be resolved in the appropriate mailing lists or IRC however.

Aside from defects, you can file enhancement and feature requests in IZ. The NetBeans teams cannot guarantee that all enhancements and features will be implemented due to a lack of resources and time, but most requests are seriously examined when the developers and module owners have time to review them.

For this, you will need to create an account on NetBeans, and the IZ page has links and information with the details. Setting up an account is quick and easy, and like everything else in NetBeans, it is free.

The UI specifications page is a good place to look if you are interested in the user interface design of NetBeans. Here you will find links to different resources regarding the UI including members whom you may want to get to know at some point if contributing to the UI and improving it is something you feel you would enjoy.

Are you into quality? You can help improve the quality of the project at the QA page. There is a community acceptance program called NetCat. I participated in the NetBeans 5.0 NetCat program, and it was a good way to share and contribute with other community members on an upcoming release. I was able to get to know a few members I had not previously communicated. I even received a T-Shirt as I had submitted so many feature requests and bugs.

There are many ways to contribute. I have found it personally rewarding and have made many community friends. If you find contributing to other open-source communities fun and rewarding, I believe you'll like the NetBeans community the same.

Working With Others

You will find, as with most things, you have different experiences with different module owners and developers. People are different and working with some will certainly be easier than others. If you have problems don't simply become frustrated, throw up your hands, and walk off. Please communicate your issues with other community members and try to resolve them.

Sometimes, detailing and explaining your issue more fully helps. Other times, it helps to communicate or use someone else as a mediator. Diplomacy comes in pretty handy when getting to know different community members and working with them. This is also true for working with employees of Sun Microsystems, the company who open-sourced NetBeans and continues to be the primary sponsor of the project. It basically boils down to people are people.

I have experienced this with different open-source projects, so communication problems are nothing unique to NetBeans. There are X different people with X different personalities and experiences. Sometimes that which one perceives as hostility or harshness is perceived differently from another person and is not always the intent of the person you are communicating. Other times, shortness is just a trait of the person you may be dealing with regardless if it's a good social tool or not. In general, this is good to keep in mind when working with any open-source project, and NetBeans is not different in this aspect.

In the NetBeans Dream Team, we will at some point try to address some community issues with regard to contributors, users, and NetBeans developers and how the relationship can be more symbiotic. Currently, we do not know exactly what this will mean or entail, but we certainly want to look at it. I feel there is something lacking, but I have not myself been able to put my finger on it, and I'm not saying it is bad, but instead some things seem like they could be better.

Either way, improvements can never hurt and certainly if we can collaborate better it will benefit all involved with the project. If you have any experiences, good or bad and from a community point of view, please feel free to share them with me at my comments email address. Let me know the issues and what worked and didn't work for you.

The NetBeans Dream Team

The NetBeans Dream Team, which I am a member, is a group of NetBeans community members who have been deeply involved with the NetBeans project for a while. Members have no affiliation with Sun Microsystems, the NetBeans project owner, other than being involved and supporting the NetBeans open-source project. No Dream Team member can be a Sun employee. This is a requirement.

The Dream Team is planning different things. Some of them involve improving the NetBeans IDE or the Rich Client Platform; others involve improving the community, while others are directed towards promoting NetBeans as one of the members' favorite open-source projects. The team may also be working on documentation for different things a user may want to do inside a NetBeans project which documentation may not be available.

Members have special insider access to the project as they are long standing community members and contributors. They are recognized for this. I may be biased in this regard, but no more than a member of any other community, which they have devoted a number of years. I will not be writing to convince you one way or another about the NetBeans project other than to tell you about it. I will try to be as non-biased as possible for someone as involved and I'm sure my editor will help me address this if I get out of line.

One way the Dream Team can help the community, and be a good resource, is try to communicate concerns between the project owner and the community at large. They can talk to community members and users in detail and try to express those concerns to the NetBeans developers and insiders at Sun. This happens now as members help out on mailing lists and IRC chat and bring community members concerns to the group.

The Dream Team can also work the other way and help the developers request things from the community, which helps them, make the project better for members and users. You can think of the Dream Team as an ear or bridge for the community. Community members and users can feel welcome to share concerns and information with the Dream Team.

Conclusions

I hope I have given you enough information about the NetBeans project to get a feel about what it is and where to find out more information about it. In the coming months, I hope to explain different features and how to use them. If nothing else, I hope you find my information useful.

About the Author

Wade Chandler has been developing software for over ten years. He has worked with different languages including C, C++, Java, Perl, different Basic and Pascal flavors, Assembler, .NET languages, and scripting tools including different scripting pages as JSP, PHP, and Cold Fusion along with JavaScript, HTML, XML, and other technologies such as Flash and Director (Shockwave). He has also worked with different operating systems, server applications, networking, DBMS, and protocol and PDA development. He is currently working for Decision Dynamics, Inc. of South Carolina.

He has been a member of the NetBeans community since NetBeans was called Forte for Java and is a member of the NetBeans Dream Team. He has contributed to different open-source projects in different capacities including but not limited to Apache Tomcat, AXIS, and other Apache projects, the visual JasperReport designer iReport, and different Linux distros (currently OpenSuSE being his favorite). Wade is also a member of the SwingLabs.org community. He has been devoting most of his open-source time to NetBeans and some day wishes to again devote time to other projects.

EJB 3 Session Beans

This article will discuss EJB 3 session beans, the core business service objects used by EJB client applications. You'll gain an understanding of the new and simplified EJB 3 session bean model, with insight into the following topics:

  • Types of session beans, both stateful and stateless, and when to use which
  • The bean class, business interfaces, and business methods
  • Callback methods
  • Interceptors
  • Exception handling
  • Client view
  • Dependency injection with annotations related to session beans

Introduction to Session Beans

Session beans are Java components that run in either stand-alone EJB containers or EJB containers that are part of standard Java Platform, Enterprise Edition (Java EE) application servers. These Java components are typically used to model a particular user task or use case, such as entering customer information or implementing a process that maintains a conversation state with a client application. Session beans can hold the business logic for many types of applications, such as human resources, order entry, and expense reporting applications.

Types of Session Beans

Session beans are of two types, as follows:

  • Stateless: This type of bean does not maintain any conversational state on behalf of a client application.
  • Stateful: This type of bean maintains state, and a particular instance of the bean is associated with a specific client request. Stateful beans can be seen as extensions to client programs that are running on the server.

You will drill down into more specifics of stateless and stateful beans in the following sections.

When Do You Use Session Beans?

Session beans are used to write business logic, maintain a conversation state for the client, and model back-end processes or user tasks that perform one or more business operations. Typical examples include the following:

  • A session bean in a human resources application that creates a new employee and assigns the employee to a particular department
  • A session bean in an expense reporting application that creates a new expense report
  • A session bean in an order entry application that creates a new order for a particular customer
  • A session bean that manages the contents of a shopping cart in an e-commerce application
  • A session bean that leverages transaction services in an EJB 3 container (removing the need for an application developer to write the transaction support)
  • A session bean used to address deployment requirements when the client applications are not colocated on the same server
  • A session bean that leverages the security support provided by the container on the component or method level

Session beans can be used in traditional 2-tier or 3-tier architectures with professional/ rich client applications, or in 3-tier web-based applications. These applications can be deployed in different logical and physical tier combinations. In the next section, you will investigate some of the possible combinations.

3-Tier Architecture with Rich Client

Figure 1 shows a typical architecture for a session bean in 3 tiers, with a rich client front-end application that has some data entry screens used by end users like customer service representatives, bank tellers, and so on. These client applications can be developed using Java Swing technology with the Java Platform, Standard Edition (Java SE), or they can be plain old Java objects (POJOs) that are run from the command line. Generally, the end user launches the client application from his desktop, enters some data, and triggers an event by pressing some user interface component such as a Submit button. The general workflow may look something like this:

  1. User action establishes a connection to the session bean running in the EJB container using remote method invocation (RMI).
  2. The client application invokes one or more business methods in the session bean.
  3. The session bean processes the request and validates data—by interacting with databases, enterprise applications, legacy systems, and so on—to perform a certain business operation or task.
  4. The session bean finally sends a response back to the client application, either through data collections or simple objects that contain acknowledgment messages.



Click here for a larger image.

Figure 1. Session beans in a 3-tier architecture

3-Tier Architecture for a Web Application

This architecture, as shown in Figure 2, is typically front-ended by a web application running in the browser of a desktop or laptop machine. These days, other types of client devices, such as PDAs, cell phones, and telnet devices, are also being used to run these applications. The web application running in a browser or mobile device renders the user interface (data entry screens, Submit buttons, etc.) using web technologies such as JavaServer Pages (JSP), JavaServer Faces (JSF), or Java Servlets. Typical user actions, such as entering search criteria or adding certain items to the web application shopping cart, will invoke/call session beans running in an EJB container via one of the aforementioned web technologies. Once the session bean gets invoked, it processes the request and sends a response back to the web application, which formats the response as required, and then sends the response on to the requesting client device (browser, PDA, telnet, etc.).



Click here for a larger image.

Figure 2. Session beans in a 3-tier architecture with a web application

In the 3-tier architecture just discussed, the client application (which is the web application) and the session beans can be run within the same instance of an application server (colocated) or from different instances running on the same machine. They can also be run in physically separate machines that have an instance of an application server.

Stateless Session Beans

Stateless session beans are comprised of the following elements:

  • Business interfaces, which contain the declaration of business methods that are going to be visible to client applications
  • A bean class, which contains the business method implementation to be executed

The Bean Class

A stateless session bean class is any standard Java class that has a class-level annotation of @Stateless. If deployment descriptors are used instead of annotations, then the bean class should be denoted as a stateless session bean. If you use both annotations and deployment descriptors (mixed mode), then the @Stateless annotation must be specified if any other class-level or member-level annotations are specified in the bean class. If both annotations and deployment descriptors are used, then the settings or values in the deployment descriptor will override the annotations in the classes during the deployment process.

To illustrate the use of stateless session beans, you will create a SearchFacade session bean that provides various search facilities to client applications regarding available wines. The workflow is as follows:

  1. Users of the application will type in or choose one or more search criteria, which will be submitted to the SearchFacade session bean.
  2. The SearchFacade bean will access back-end databases to retrieve the requested information. To simplify the code examples in this , you will actually retrieve the list of hard-coded values within the bean class.
  3. The bean returns to the client applications the information that satisfied the search criteria.

Listing 1 shows the definition of the SearchFacade bean. In the following sections of this article, you will build the code that will show the preceding workflow in action. SearchFacadeBean is a standard Java class with a class-level annotation of @Stateless.

Listing 1. SearchFacadeBean.java

package com.apress.ejb3.chapter02;

import javax.ejb.Stateless;

@Stateless(name="SearchFacade")

public class SearchFacadeBean implements SearchFacade,
SearchFacadeLocal {
public SearchFacadeBean() {
}
}

The Business Interface

A stateless session business interface is a standard Java interface that does not extend any EJB-specific interfaces. This interface has a list of business method definitions that will be available for the client application. Every session bean must have a business interface that can be implemented by the bean class, generated at design time by tools such as Oracle JDeveloper, NetBeans, or Eclipse; or generated at deployment time by the EJB container.

Business interfaces can use annotations as well, as described in the following list:

  • The @Remote annotation can be used to denote the remote business interface.
  • The @Local annotation can be used to denote the local business interface.

If no annotation is specified in the interface, then it is defaulted to the local interface.

If your architecture has a requirement whereby the client application (web application or rich client) has to run on a different JavaVirtual Machine (JVM) from the one that is used to run the session beans in an EJB container, then you need to use the remote interface. The separate JVMs can be on the same physical machine or on separate machines. If your application architecture is going to use the same JVM for both the client application and the session beans, then use the local interface.

It is possible that your application architecture requires both remote and local interfaces. For example, an enterprise might have an order entry application that is developed using session beans that have business methods for submitting new orders and also addressing administrative tasks, such as data entry for the products. Potentially, you could have two different client applications that access the back-end order entry application, as follows:

  • A web client application (as shown in Figure 3) that can be run in the same JVM as the session bean and used to submit new orders
  • A rich client application (as shown in Figure 4) that runs on an end-user desktop machine and is used by the administrator for data entry purposes

Figure 3. A web client using local interfaces of session beans



Click here for a larger image.

Figure 4. A rich client using remote interfaces of session beans

The SearchFacade session bean has both remote and local interfaces, as shown in Figure 5.



Click here for a larger image.

Figure 5. The business interfaces of the SearchFacade session bean

Listing 2 shows the code snippet for the SearchFacade remote business interface, with an @Remote annotation and a wineSearch() method declaration. The wineSearch() method takes one parameter that represents the type of the wine, and returns a list of wines that match the wine type criteria.

Listing 2. SearchFacade.java

package com.apress.ejb3.chapter02; import java.util.List; import javax.ejb.Remote; @Remote public interface SearchFacade { List wineSearch(String wineType); }

Listing 3 shows the code snippet for the SearchFacade local business interface, with an @Local annotation and a wineSearch() method declaration.

Listing 3. SearchFacadeLocal.java

package com.apress.ejb3.chapter02; import java.util.List; import javax.ejb.Local; @Local public interface SearchFacadeLocal { List wineSearch(String wineType); }

Business Methods

The methods implemented in the bean class must correspond to the business methods declared in the remote or local business interfaces. They are matched up based on the convention that they have the same name and method signature. Other methods in the bean class that do not have the corresponding declaration in the business interfaces will be private to the bean class methods.

The SearchFacade bean implements one method, wineSearch(), which has been declared in both remote and local business interfaces. The wineSearch() method returns a static wines list based on the type of wine. Listing 4 shows the implementation for wineSearch().

Listing 4. SearchFacadeBean.java

package com.apress.ejb3.chapter02; import java.util.ArrayList; import java.util.List; import javax.ejb.Stateless; @Stateless(name="SearchFacade") public class SearchFacadeBean implements SearchFacade, SearchFacadeLocal { public SearchFacadeBean() { } public List wineSearch(String wineType) { List wineList = new ArrayList(); if (wineType.equals("Red")) { wineList.add("Bordeaux"); wineList.add("Merlot"); wineList.add("Pinot Noir"); } else if (wineType.equals("White")) { wineList.add("Chardonnay"); } return wineList; } }

Dependency Injection

In this section, you will look into using dependency injection in stateless session beans.

EJB 3 containers provide the facilities to inject various types of resources into stateless session beans. Typically, in order to perform user tasks or process requests from client applications, the business methods in the session bean require one or more types of resources. These resources can be other session beans, data sources, or message queues.

The resources that the stateless session bean is trying to use can be injected using annotations or deployment descriptors. Resources can be acquired by annotation of instance variables or annotation of the setter methods. Listing 5 shows an example of setter and instance variable.based injection of myDb, which represents the data source.

Listing 5. Data Source Injection

@Resource DataSource myDb;

or

@Resource public void setMyDb(DataSource myDb) { this.myDb = myDb; }

You typically use the setter injections to preconfigure or initialize properties of the injected resource.

Callback Methods

There will be certain instances or use cases in which the application using session beans requires fine-grained control over things like an object's creation, removal, and so on. For example, the SearchFacade session bean might need to perform some database initialization when it is created, or close some database connections when it is destroyed. The application can gain fine-grained control over the various stages of the bean life cycle via methods known as callback methods. A callback method can be any method in the session bean that has callback annotations. The EJB container calls these methods at the appropriate stages of the bean's life cycle (bean creation and destruction).

Following are two such callbacks for stateless session beans:

  • PostConstruct: Denoted with the @PostContruct annotation. Any method in the bean class can be marked with this annotation.
  • PreDestroy: Denoted with the @PreDestroy annotation. Again, any method in the bean class can be marked with this annotation.

PostContruct callbacks happen after a bean instance is instantiated in the EJB container. If the bean is using any dependency injection mechanisms for acquiring references to resources or other objects in its environment, PostConstruct will occur after injection is performed and before the first business method in the bean class is called.

In the case of the SearchFacade session bean, you could have a business method, wineSearchByCountry(), that would return the wine list for a particular country, and have a PostConstruct callback method, initializeCountryWineList(), that would initialize the country's wine list whenever the bean gets instantiated. Ideally, you would load the list from a back-end datastore; but in this article, you will just use some hard-coded values that get populated into a HashMap, as shown in Listing 6.

Listing 6. The PostConstruct Method

@PostConstruct

public void initializeCountryWineList()
{
//countryMap is HashMap
countryMap.put("Australia", "Sauvignon Blanc");
countryMap.put("Australia", "Grenache");
countryMap.put("France","Gewurztraminer");
countryMap.put("France","Bordeaux");
}

The PreDestroy callback happens before the container destroys an unused or expired bean instance from its object pool. This callback can be used to close any connection pool that has been created with dependency injection, and also to release any other resources.

In the case of the SearchFacade session bean, you could add a PostConstruct callback method (destroyWineList()) into the SearchFacade bean, which would clear the country wine list whenever the bean gets destroyed. Ideally, during PostContruct, you would close any resources that have been created with dependency injection; but in this article, you will just clear the HashMap that has the countries and wine list. Listing 7 shows the destroyWineList() code.

Listing 7. The PreDestroy Method

@PreDestroy
public void destroyWineList()
{
countryMap.clear();
}

Callback methods defined on a bean class should have the following signature:

public void ()

Callback methods can also be defined on a bean's listener class; these methods should have the following signature:

public void (Object)

where Object may be declared as the actual bean type, which is the argument passed to the callback method at run time.

Interceptors

The EJB 3 specification provides annotations called interceptors, which allow you to intercept a business method invocation. An interceptor method can be defined for session and message-driven beans (MDBs). You will show you the usage of interceptors in the session bean context.

There are number of use cases for interceptors in a typical application, in which you would find a need to perform a certain task before or after the business method is invoked. For example, you may wish to do one of the following:[

  • Perform additional security checks before a critical business method that transfers more than $100,000 dollars
  • Do some performance analysis to compute the time it takes to perform the task
  • Do additional logging before or after the method invocation

You can either add an @AroundInvoke annotation on a particular method, or you can define an interceptor class whose methods are invoked before a business method is invoked in the bean class. An interceptor class is denoted by the @Interceptor annotation on the bean class with which it is associated. In the case of multiple interceptor classes, the @Interceptors annotation is used. Methods that are annotated with @AroundInvoke should have the following signature:

public Object (InvocationContext) throws Exception

The definition of InvocationContext is as follows:

package javax.ejb;

public interface InvocationContext {
public Object getBean();
public java.lang.reflect.Method getMethod();
public Object[] getParameters();
public void setParameters(Object[] params);
public EJBContext getEJBContext();
public java.util.Map getContextData();
public Object proceed() throws Exception;
}

The following list describes the methods in the preceding code:

  • getBean() returns the instance of the bean on which the method was called.
  • getMethod() returns the method on the bean instance that was called.
  • getParameters() returns the parameters for the method call.
  • setParameters() modifies the parameters used for the method call.
  • getEJBContext() gives the interceptor methods access to the bean's EJBContext.
  • getContextData() allows values to be passed between interceptor methods in the same InvocationContext instance using the Map returned.
  • proceed() invokes the next interceptor, if there is one, or invokes the target bean method.

In the SearchFacade session bean, you can add an interceptor that logs the time taken to execute each business method when invoked by the client applications. Listing 8 shows a time log method that will print out the time taken to execute a business method. InvocationContext is used to get the name of bean class and the invoked method name. Before invoking the business method, current system time is captured and deducted from the system time after the business method is executed. Finally, the details are printed out to the console log using System.out.println.

Listing 8. The Interceptor Method

@AroundInvoke

public Object TimerLog (InvocationContext ctx) throws Exception
{
String beanClassName = ctx.getClass().getName();
String businessMethodName = ctx.getMethod().getName();
String target = beanClassName + "." + businessMethodName ;
long startTime = System.currentTimeMillis();
System.out.println ("Invoking " + target);
try {
return ctx.proceed();
}
finally {
System.out.println("Exiting " + target);
long totalTime = System.currentTimeMillis() - startTime;
System.out.println("Business method " + businessMethodName +
"in " + beanClassName + "takes " + totalTime + "ms to execute");
}

}

Stateful Session Beans

Similar to stateless session beans, stateful beans comprise a bean class and a business interface.

The Bean Class

A stateful session bean class is any standard Java class that has a class-level annotation of @Stateful. If deployment descriptors are used instead of annotations, the bean class should be denoted as a stateful session bean. In the case of mixed mode, in which you are using annotations and deployment descriptors, the @Stateful annotation must be specified if any other class-level or member-level annotations are specified in the class.

To illustrate a stateful session bean, you will create a ShoppingCart session bean that will keep track of the items added to a user's shopping cart and their respective quantities. In this article, you will use hard-coded values for the shopping cart to illustrate the state and conversation maintenance between the client and stateful session bean. Listing 9 shows the definition of a ShoppingCart session bean.

Listing 9. ShoppingCartBean.java

package com.apress.ejb3.chapter02;

import javax.ejb.Stateful;

@Stateful(name="ShoppingCart")

public class ShoppingCartBean implements ShoppingCart,
ShoppingCartLocal {
public ShoppingCartBean() {
}

The Business Interface

Business interfaces for stateful session beans are similar to those for stateless session beans, and are annotated in the same way, using @Local and @Remote annotations. The ShoppingCart session bean has both remote and local interfaces, as shown in Figure 6.



Click here for a larger image.

Figure 6. Business interfaces for ShoppingCart

You will primarily use the local interface from our web application. The remote interface is added to facilitate unit testing of the bean in this article.

Listings 10 and 11 show the remote and local ShoppingCart business interfaces, with @Remote and @Local annotations, respectively.

Listing 10. ShoppingCart.java

package com.apress.ejb3.chapter02; import javax.ejb.Remote; @Remote public interface ShoppingCart { }

Listing 11. ShoppingCartLocal.java

package com.apress.ejb3.chapter02; import javax.ejb.Local; @Local public interface ShoppingCartLocal { }

Alternatively, you can use the coding style shown in Listing 2-12, in which you can specify the @Local and @Remote annotations before specifying @Stateful or @Stateless with the name of the business interface.

Listing 12. ShoppingCartBean.java

package com.apress.ejb3.chapter02; import javax.ejb.Local; import javax.ejb.Remote; import javax.ejb.Stateful; @Local({ShoppingCartLocal.class}) @Remote({ShoppingCart.class}) @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart, ShoppingCartLocal { public ShoppingCartBean() { } }
Note: In this article, you will follow the earlier convention, in which @Local and @Remote annotations are marked on the business interfaces.

Business Methods

Business methods in stateful session beans are similar to those in stateless session beans. You will augment the ShoppingCart bean by adding business methods that will add and remove wines from the shopping cart, and return a list of cart items.

Listing 13 shows the ShoppingCart bean implementing the addWineItem(), removeWineItem(), and getCartItems() methods.

Listing 13. ShoppingCartBean.java

package com.apress.ejb3.chapter02; import java.util.ArrayList; import javax.ejb.Stateful; @Stateful(name="ShoppingCart") public class ShoppingCartBean implements ShoppingCart, ShoppingCartLocal { public ShoppingCartBean() { } public ArrayList cartItems; public void addWineItem(String wine) { cartItems.add(wine); } public void removeWineItem(String wine) { cartItems.remove(wine); } public void setCartItems(ArrayList cartItems) { this.cartItems = cartItems; } public ArrayList getCartItems() { return cartItems; } }

Callback Methods

Stateful session beans support callback events for construction, destruction, activation, and passivation. Following are the callbacks that map to the preceding events:

  • PostConstruct: Denoted with the @PostConstruct annotation. Any method in the bean class can be marked with this annotation.
  • PreDestroy: Denoted with the @PreDestroy annotation.
  • PreActivate: Denoted with the @PreActivate annotation.
  • PrePassivate: Denoted with the @PrePassivate annotation.

The PostContruct callback happens after a bean instance is instantiated in the EJB container. If the bean is using any dependency injection mechanism for acquiring references to resources or other objects in its environment, the PostConstruct event happens after injection is performed and before the first business method in the bean class is called.

In the case of the ShoppingCart session bean, you could have a business method called initialize() that initializes the cartItems list, as show in Listing 14.

Listing 14. The PostConstruct Method

@PostConstruct public void initialize() { cartItems = new ArrayList(); }

The PreDestroy callback happens after any method with an @Remove annotation has been completed. In the case of the ShoppingCart session bean, you could have a business method called exit() that writes the cartItems list into a database. In this article, you will just print out a message to the system console to illustrate the callback. Listing 15 shows the code for the exit() method, which has the @PreDestroy annotation.

Listing 15. The PreDestroy Method

@PreDestroy public void exit() { // items list into the database. System.out.println("Saved items list into database"); }

The @Remove annotation is a useful life cycle method for stateful session beans. When the method with the @Remove annotation is called, the container will remove the bean instance from the object pool after the method is executed. Listing 16 shows the code for the stopSession() method, which has the @Remove annotation.

Listing 16. The Remove Method

@Remove public void stopSession() { // The method body can be empty. System.out.println("From stopSession method with @Remove annotation"); }

The PrePassivate callback kicks in when a stateful session bean instance is idle for too long. During this event, the container might passivate and store its state to a cache. The method tagged with @PrePassivate is called before the container passivates the bean instance.

The PostActivate event gets raised when the client application uses a passivated stateful session bean again. A new instance with restored state is created. The method with the @PostActivate annotation is called when the bean instance is ready.

Interceptors

There are some minor differences between interceptors for stateless and stateful session beans. AroundInvoke methods can be used with stateful session beans. For stateful session beans that implement SessionSynchronization, afterBegin occurs before any methods that have AroundInvoke annotations, and before the beforeCompletion() callback method.

Exception Handling

The EJB 3 specification outlines two types of exceptions:

  • Application exceptions
  • System exceptions

Application exceptions are exceptions related to execution of business logic that the client should handle. For example, an application exception might be raised if the client application passes an invalid argument, such as the wrong credit card number.

System exceptions, on the other hand, are caused by system-level faults, such as Java Naming and Directory Interface (JNDI) errors, or failure to acquire a database connection. A system exception must be a subclass of a java.rmi.RemoteException, or a subclass of a java.lang.RuntimeException that is not an application exception.

From the EJB application point of view, application exceptions are done by writing application-specific exception classes that subclass the java.lang.Exception class.

In the case of a system exception, the application catches particular exceptions—such as a NamingException that results from a JNDI failure—and throws an EJBException. In this particular article, our examples aren't using any resources as such.

Client View for Session Beans

A session bean can be seen as a logical extension of a client program or application, where much of the logic and data processing for that application happens. A client application typically accesses the session object through the session bean's client view interfaces, which are the business interfaces that you're discussed in the earlier sections.

A client application that accesses session beans can be one of three types:

  • Remote: Remote clients run in a separate JVM from the session beans that they access, as shown in Figure 4. A remote client accesses a session bean through the bean's remote business interface. A remote client can be another EJB, a Java client program, or a Java servlet. Remote clients have location independence, meaning that they can use the same API as the clients running in the same JVM.
  • Local: Local clients run in the same JVM, as shown in Figure 3, and access the session bean through the local business interface. A local client can be another EJB, or a web application using Java Servlets, JavaServer Pages (JSP), or JavaServer Faces (JSF). Local clients are location dependent. Remote and local clients are compared in Table 1.
  • Web Services: You can publish stateless session beans as web services that can be invoked by Web Services clients.

Table 1. Considerations for Choosing Between Local and Remote Clients

Remote Local
Loose coupling between the bean and the client Lightweight access to a component
Location independence Location dependence
Expensive remote calls Must be colocated with the bean
Objects must be serialized Not required
Objects are passed by value Objects are passed by reference

In some cases, the session beans need to have both local and remote business interfaces to support different types of client applications. A client can obtain a session bean's business interface via dependency injection or JNDI lookup. Before invoking the methods in the session bean, the client needs to obtain a stub object of the bean via JNDI. Once the client has a handle to the stub object, it can call the business methods in the session bean. In the case of a stateless session bean, a new stub can be obtained on every invocation. In the case of a stateful session bean, the stub needs to be cached on the client side so that the container knows which instance of the bean to return on subsequent calls. Using dependency injection, you can obtain the business interface of the SearchFacade session bean with the following code:

@EJB SearchFacade searchFacade;

If the client accessing the session bean is remote, the client can use JNDI lookup once the context interface has been obtained with the right environment properties. Local clients can use JNDI lookup as well, but dependency injection results in simpler code. Listing 17 shows the SearchFacadeTest client program's JNDI code, which looks up the SearchFacade bean, invokes the wineSearch() business method, and prints out the returned list of wines.

Note If the remote client is a Java application or command-line program, an application client container can be used to invoke the session beans. Application client containers support dependency injection for remote clients.

Listing 17. SearchFacadeClient.java

package com.apress.ejb3.chapter02.client;

import com.apress.ejb3.chapter02.SearchFacade;
import java.util.List;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class SearchFacadeTest {
public SearchFacadeTest() {
}

public static void main(String[] args) {
SearchFacadeTest searchFacadeTest = new SearchFacadeTest();
searchFacadeTest.doTest();
}

@EJB
static SearchFacade searchFacade;

void doTest(){
InitialContext ic;

try {
ic = new InitialContext();
System.out.println("SearchFacade Lookup");
System.out.println("Searching wines");
List winesList = searchFacade.wineSearch("Red");
System.out.println("Printing wines list");
for (String wine:(List)winesList ){
System.out.println(wine);
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}

Listing 18 shows the ShoppingCartTest client program, which looks up the stateful ShoppingCart session bean, calls the addWineItem() business method to add a wine to the shopping cart, calls the getCartItems() business method to get the items in the cart, and finally prints the list of wines in the shopping cart.

Listing 18. ShoppingCartTest.java

package com.apress.ejb3.chapter02.client;

import com.apress.ejb3.chapter02.ShoppingCart;

import java.util.ArrayList;

import java.util.List;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class ShoppingCartTest {
public ShoppingCartTest() {
}

public static void main(String[] args) {
ShoppingCartTest shoppingCartTest = new ShoppingCartTest();
shoppingCartTest.doTest();
}

@EJB
static ShoppingCart shoppingCart;

void doTest(){
InitialContext ic;

try {
ic = new InitialContext();
System.out.println("ShoppingCart Lookup");
System.out.println("Adding Wine Item");
shoppingCart.addWineItem("Zinfandel");
System.out.println("Printing Cart Items");
ArrayList cartItems = shoppingCart.getCartItems();
for (String wine:(List)cartItems ){
System.out.println(wine);
}
} catch (NamingException e) {
e.printStackTrace();
}
}
}

Conclusion

This article has covered EJB 3 session bean details using a specific set of examples. You looked at the new and simplified EJB 3 model for developing session beans using standard Java language artifacts, such as Java classes and interfaces. You looked at session beans, and some typical use cases in which session beans can be used for developing applications. You discussed two different types of session beans (stateless and stateful), including the differences between them and some general use cases for each. You covered session bean usage in 2-tier and 3-tier application architectures. You discussed the usage of dependency injection in stateless and stateful beans. You considered ways to gain fine-grained control over application flow, including the use of callback methods and interceptors in stateless and stateful beans, as well as the use of annotations like @PostContruct and @PreDestroy.

About the Authors

Raghu R. Kodali is a consulting product manager and SOA evangelist for Oracle Application Server. He has worked in the software industry for over 10 years as a developer, consultant, and presales engineer in emerging technologies. He is responsible for J2EE features with expertise in SOA technologies like EJB, Web Services, and application development frameworks. Raghu has been the lead product manager for EJB design-time features in Oracle JDeveloper since the EJB 1.1 specification. His current area of focus is evangelizing service-oriented infrastructure and implementing service-oriented applications.

Jonathan Wetherbee is a consulting engineer and tech lead for EJB development tools on Oracle’s JDeveloper IDE. He has over 10 years of experience in development at Oracle, working on a variety of O/R mapping tools and holding responsibility for Oracle’s core EJB toolset since EJB 1.1.

Peter Zadrozny brings over 20 years of experience to StrongMail Systems, where he serves as chief technology officer. Peter joined StrongMail Systems from Oracle, where he was vice president and chief evangelist for Oracle Application Server. Previously, Peter served as chief technologist of BEA Systems for Europe, the Middle East, and Africa—a role he held since launching WebLogic’s operations in Europe in 1998. Prior to BEA, Peter held executive and technical positions in many countries around the world for companies such as Macromedia, McKesson, Electronic Data Systems, PetrĂ³leos de Venezuela, and Sun Microsystems, for whom he started operations in Mexico.


}

There will be certain use cases in which the application wants to be notified by the EJB container before or after transactions take place, and then use these notifications to manage data and cache. A stateful session bean can receive this kind of notification by the EJB container when it implements the javax.ejb.SessionSynchronization interface. This is an optional feature. There are three different types of transaction notifications that the stateful session bean receives from the EJB container, as follows:

  • afterBegin: Indicates that a new transaction has begun
  • beforeCompletion: Indicates that the transaction is going to be committed
  • afterCompletion: Indicates that a transaction has been completed

For example, the ShoppingCart session bean could implement the javax.ejb.SessionSynchronization interface to get an afterCompletion notification, so that it can clear out the shopping cart cache.