Hubbry Logo
Jakarta Enterprise BeansJakarta Enterprise BeansMain
Open search
Jakarta Enterprise Beans
Community hub
Jakarta Enterprise Beans
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
Jakarta Enterprise Beans
Jakarta Enterprise Beans
from Wikipedia

Jakarta Enterprise Beans (EJB; formerly Enterprise JavaBeans) is one of several Java APIs for modular construction of enterprise software. EJB is a server-side software component that encapsulates business logic of an application. An EJB web container provides a runtime environment for web related software components, including computer security, Java servlet lifecycle management, transaction processing, and other web services. The EJB specification is a subset of the Jakarta EE specification.[1]

Specification

[edit]

The EJB specification was originally developed in 1997 by IBM and later adopted by Sun Microsystems (EJB 1.0 and 1.1) in 1999[2] and enhanced under the Java Community Process as JSR 19 (EJB 2.0), JSR 153 (EJB 2.1), JSR 220 (EJB 3.0), JSR 318 (EJB 3.1) and JSR 345 (EJB 3.2).

The EJB specification provides a standard way to implement the server-side (also called "back-end") 'business' software typically found in enterprise applications (as opposed to 'front-end' user interface software). Such software addresses the same types of problem, and solutions to these problems are often repeatedly re-implemented by programmers. Jakarta Enterprise Beans is intended to handle such common concerns as persistence, transactional integrity and security in a standard way, leaving programmers free to concentrate on the particular parts of the enterprise software at hand.

General responsibilities

[edit]

The EJB specification details how an application server provides the following responsibilities:

Additionally, the Jakarta Enterprise Beans specification defines the roles played by the EJB container and the EJBs as well as how to deploy the EJBs in a container. Note that the EJB specification does not detail how an application server provides persistence (a task delegated to the JPA specification), but instead details how business logic can easily integrate with the persistence services offered by the application server.

History

[edit]

Businesses found that using EJBs to encapsulate business logic brought a performance penalty. This is because the original specification allowed only for remote method invocation through CORBA (and optionally other protocols), even though the large majority of business applications actually do not require this distributed computing functionality. The EJB 2.0 specification addressed this concern by adding the concept of local interfaces which could be called directly without performance penalties by applications that were not distributed over multiple servers.[3]

The EJB 3.0 specification (JSR 220) was a departure from its predecessors, following a new light-weight paradigm. EJB 3.0 shows an influence from Spring in its use of plain Java objects, and its support for dependency injection to simplify configuration and integration of heterogeneous systems. EJB 3.0 along with the other version of the EJB can be integrated with MuleSoft-v4 using MuleSoft certified PlektonLabs EJB Connector. Gavin King, the creator of Hibernate, participated in the EJB 3.0 process and is an outspoken advocate of the technology. Many features originally in Hibernate were incorporated in the Java Persistence API, the replacement for entity beans in EJB 3.0. The EJB 3.0 specification relies heavily on the use of annotations (a feature added to the Java language with its 5.0 release) and convention over configuration to enable a much less verbose coding style. Accordingly, in practical terms EJB 3.0 is much more lightweight and nearly a completely new API, bearing little resemblance to the previous EJB specifications. [citation needed]

Example

[edit]

The following shows a basic example of what an EJB looks like in code:

@Stateless 
public class CustomerService { 

    private EntityManager entityManager; 
   
    public void addCustomer(Customer customer) { 
        entityManager.persist(customer); 
    } 
}

The above defines a service class for persisting a Customer object (via O/R mapping). The EJB takes care of managing the persistence context and the addCustomer() method is transactional and thread-safe by default. As demonstrated, the EJB focuses only on business logic and persistence and knows nothing about any particular presentation.

Such an EJB can be used by a class in e.g. the web layer as follows:

@Named	
@RequestScoped
public class CustomerBacking {
    @EJB 
    private CustomerService customerService;

    public String addCustomer(Customer customer) {
        customerService.addCustomer(customer);
        context.addMessage(...); // abbreviated for brevity
        return "customer_overview";
    }
}

The above defines a JavaServer Faces (JSF) backing bean in which the EJB is injected by means of the @EJB annotation. Its addCustomer method is typically bound to some UI component, such as a button. Contrary to the EJB, the backing bean does not contain any business logic or persistence code, but delegates such concerns to the EJB. The backing bean does know about a particular presentation, of which the EJB had no knowledge.

Types of Enterprise Beans

[edit]

An EJB container holds two major types of beans:

  • Session Beans[4] that can be either "Stateful", "Stateless" or "Singleton" and can be accessed via either a Local (same JVM) or Remote (different JVM) interface or directly without an interface,[5] in which case local semantics apply. All session beans support asynchronous execution[6] for all views (local/remote/no-interface).
  • Message Driven Beans (MDBs, also known as Message Beans). MDBs also support asynchronous execution, but via a messaging paradigm.

Session beans

[edit]

Stateful Session Beans

[edit]

Stateful Session Beans[7] are business objects having state: that is, they keep track of which calling client they are dealing with throughout a session and of the history of its requests, and thus access to the bean instance is strictly limited to only one client during its lifetime.[8] If concurrent access to a single bean is attempted anyway the container serializes those requests, but via the @AccessTimeout annotation the container can instead throw an exception.[9] Stateful session beans' state may be persisted (passivated) automatically by the container to free up memory after the client hasn't accessed the bean for some time. The JPA extended persistence context is explicitly supported by Stateful Session Beans.[10]

Examples
  • Checking out in a web store might be handled by a stateful session bean that would use its state to keep track of where the customer is in the checkout process, possibly holding locks on the items the customer is purchasing (from a system architecture's point of view, it would be less ideal to have the client manage those locks).

Stateless Session Beans

[edit]

Stateless Session Beans[11] are business objects that do not have state associated with them. However, access to a single bean instance is still limited to only one client at a time, concurrent access to the bean is prohibited.[8] If concurrent access to a single bean is attempted, the container simply routes each request to a different instance.[12] This makes a stateless session bean automatically thread-safe. Instance variables can be used during a single method call from a client to the bean, but the contents of those instance variables are not guaranteed to be preserved across different client method calls. Instances of Stateless Session beans are typically pooled. If a second client accesses a specific bean right after a method call on it made by a first client has finished, it might get the same instance. The lack of overhead to maintain a conversation with the calling client makes them less resource-intensive than stateful beans.

Examples
  • Sending an e-mail to customer support might be handled by a stateless bean, since this is a one-off operation and not part of a multi-step process.
  • A user of a website clicking on a "keep me informed of future updates" box may trigger a call to an asynchronous method of the session bean to add the user to a list in the company's database (this call is asynchronous because the user does not need to wait to be informed of its success or failure).
  • Fetching multiple independent pieces of data for a website, like a list of products and the history of the current user might be handled by asynchronous methods of a session bean as well (these calls are asynchronous because they can execute in parallel that way, which potentially increases performance). In this case, the asynchronous method will return a Future instance.

Singleton Session Beans

[edit]

Singleton Session Beans[13][14] are business objects having a global shared state within a JVM. Concurrent access to the one and only bean instance can be controlled by the container (Container-managed concurrency, CMC) or by the bean itself (Bean-managed concurrency, BMC). CMC can be tuned using the @Lock annotation, that designates whether a read lock or a write lock will be used for a method call. Additionally, Singleton Session Beans can explicitly request to be instantiated when the EJB container starts up, using the @Startup annotation.

Examples
  • Loading a global daily price list that will be the same for every user might be done with a singleton session bean, since this will prevent the application having to do the same query to a database over and over again...

Message driven beans

[edit]

Message Driven Beans[15] are business objects whose execution is triggered by messages instead of by method calls. The Message Driven Bean is used among others to provide a high level ease-of-use abstraction for the lower level JMS (Java Message Service) specification. It may subscribe to JMS message queues or message topics, which typically happens via the activationConfig attribute of the @MessageDriven annotation. They were added in EJB to allow event-driven processing. Unlike session beans, an MDB does not have a client view (Local/Remote/No-interface), i. e. clients cannot look-up an MDB instance. An MDB just listens for any incoming message on, for example, a JMS queue or topic and processes them automatically. Only JMS support is required by the Java EE spec,[16] but Message Driven Beans can support other messaging protocols.[17][18] Such protocols may be asynchronous but can also be synchronous. Since session beans can also be synchronous or asynchronous, the prime difference between session- and message driven beans is not the synchronicity, but the difference between (object oriented) method calling and messaging.

Examples
  • Sending a configuration update to multiple nodes might be done by sending a JMS message to a 'message topic' and could be handled by a Message Driven Bean listening to this topic (the message paradigm is used here since the sender does not need to know the number of consumers, their location, or even their exact type).
  • Submitting a job to a work cluster might be done by sending a JMS message to a 'message queue' and could also be handled by a Message Driven Bean, but this time listening to a queue (the message paradigm and the queue is used, since the sender doesn't have to care which worker executes the job, but it does need assurance that a job is only executed once).
  • Processing timing events from the Quartz scheduler can be handled by a Message Driven Bean; when a Quartz trigger fires, the MDB is automatically invoked. Since Java EE doesn't know about Quartz by default, a JCA resource adapter would be needed and the MDB would be annotated with a reference to this.[19]

Execution

[edit]

EJBs are deployed in an EJB container, typically within an application server. The specification describes how an EJB interacts with its container and how client code interacts with the container/EJB combination. The EJB classes used by applications are included in the javax.ejb package. (The javax.ejb.spi package is a service provider interface used only by EJB container implementations.)

Clients of EJBs do not instantiate those beans directly via Java's new operator, but instead have to obtain a reference via the EJB container. This reference is usually not a reference to the implementation bean itself, but to a proxy, which dynamically implements either the local or remote business interface that the client requested or a sub-type of the actual bean. The proxy can then be directly cast to the interface or bean respectively. A client is said to have a 'view' on the EJB, and the local interface, remote interface and bean sub-type itself respectively correspond to the local view, remote view and no-interface view.

This proxy is needed in order to give the EJB container the opportunity to transparently provide cross-cutting (AOP-like) services to a bean like transactions, security, interceptions, injections, and remoting. As an example, a client invokes a method on a proxy, which will first start a transaction with the help of the EJB container and then call the actual bean method. When the bean method returns, the proxy ends the transaction (i.e. by committing it or doing a rollback) and transfers control back to the client.

The EJB Container is responsible for ensuring the client code has sufficient access rights to an EJB.[20] Security aspects can be declaratively applied to an EJB via annotations.[21]

Transactions

[edit]

EJB containers must support both container managed ACID transactions and bean managed transactions.[22]

Container-managed transactions (CMT) are by default active for calls to session beans. That is, no explicit configuration is needed. This behavior may be declaratively tuned by the bean via annotations and if needed such configuration can later be overridden in the deployment descriptor. Tuning includes switching off transactions for the whole bean or specific methods, or requesting alternative strategies for transaction propagation and starting or joining a transaction. Such strategies mainly deal with what should happen if a transaction is or isn't already in progress at the time the bean is called. The following variations are supported:[23][24]

Declarative Transactions Management Types
Type Explanation
MANDATORY If the client has not started a transaction, an exception is thrown. Otherwise the client's transaction is used.
REQUIRED If the client has started a transaction, it is used. Otherwise a new transaction is started. (this is the default when no explicit type has been specified)
REQUIRES_NEW If the client has started a transaction, it is suspended. A new transaction is always started.
SUPPORTS If the client has started a transaction, it is used. Otherwise, no transaction is used.
NOT_SUPPORTED If the client has started a transaction, it is suspended. No new transaction is started.
NEVER If the client has started a transaction, an exception is thrown. No new transaction is started.

Alternatively, the bean can also declare via an annotation that it wants to handle transactions programmatically via the JTA API. This mode of operation is called Bean Managed Transactions (BMT), since the bean itself handles the transaction instead of the container.[25]

Events

[edit]

JMS (Java Message Service) is used to send messages from beans to clients, to let clients receive asynchronous messages from these beans. MDBs can be used to receive messages from clients asynchronously using either a JMS Queue or a Topic.

Naming and directory services

[edit]

As an alternative to injection, clients of an EJB can obtain a reference to the session bean's proxy object (the EJB stub) using Java Naming and Directory Interface (JNDI). This alternative can be used in cases where injection is not available, such as in non-managed code or standalone remote Java SE clients, or when it's necessary to programmatically determine which bean to obtain.

JNDI names for EJB session beans are assigned by the EJB container via the following scheme:[26][27][28]

JNDI names
Scope Name pattern
Global java:global[/<app-name>]/<module-name>/<bean-name>[!<fully-qualified-interface-name>]
Application java:app/<module-name>/<bean-name>[!<fully-qualified-interface-name>]
Module java:module/<bean-name>[!<fully-qualified-interface-name>]

(entries in square brackets denote optional parts)

A single bean can be obtained by any name matching the above patterns, depending on the 'location' of the client. Clients in the same module as the required bean can use the module scope and larger scopes, clients in the same application as the required bean can use the app scope and higher, etc.

E.g. code running in the same module as the CustomerService bean (as given by the example shown earlier in this article) could use the following code to obtain a (local) reference to it:

CustomerServiceLocal customerService =
    (CustomerServiceLocal) new InitialContext().lookup("java:module/CustomerService");

Remoting/distributed execution

[edit]

For communication with a client that's written in the Java programming language a session bean can expose a remote-view via an interface annotated with @Remote.[29] This allows those beans to be called from clients in other JVMs which may be running on other systems (from the point of view of the EJB container, any code in another JVM is remote).

Stateless and Singleton session beans may also expose a "web service client view" for remote communication via WSDL and SOAP or plain XML.[30][31][32] This follows the JAX-RPC and JAX-WS specifications. JAX-RPC support however is proposed for future removal.[33] To support JAX-WS, the session bean is annotated with @WebService, and methods that are to be exposed remotely with @WebMethod.

Although the EJB specification does not mention exposure as RESTful web services in any way and has no explicit support for this form of communication, the JAX-RS specification does explicitly support EJB.[34] Following the JAX-RS spec, Stateless and Singleton session beans can be declared as root resources via the @Path annotation and EJB business methods can be mapped to resource methods via the @GET, @PUT, @POST and @DELETE annotations. This however does not count as a "web service client view", which is used exclusively for JAX-WS and JAX-RPC.

Communication via web services is typical for clients not written in the Java programming language, but is also convenient for Java clients who have trouble reaching the EJB server via a firewall. Additionally, web service based communication can be used by Java clients to circumvent the arcane and ill-defined requirements for the so-called "client-libraries"; a set of jar files that a Java client must have on its class-path in order to communicate with the remote EJB server. These client-libraries potentially conflict with libraries the client may already have (for instance, if the client itself is also a full Java EE server) and such a conflict is deemed to be very hard or impossible to resolve.[35]

Legacy

[edit]

Home interfaces and required business interface

[edit]

With EJB 2.1 and earlier, each EJB had to provide a Java implementation class and two Java interfaces. The EJB container created instances of the Java implementation class to provide the EJB implementation. The Java interfaces were used by client code of the EJB.

Required deployment descriptor

[edit]

With EJB 2.1 and earlier, the EJB specification required a deployment descriptor to be present. This was needed to implement a mechanism that allowed EJBs to be deployed in a consistent manner regardless of the specific EJB platform that was chosen. Information about how the bean should be deployed (such as the name of the home or remote interfaces, whether and how to store the bean in a database, etc.) had to be specified in the deployment descriptor.

The deployment descriptor is an XML document having an entry for each EJB to be deployed. This XML document specifies the following information for each EJB:

  • Name of the Home interface
  • Java class for the Bean (business object)
  • Java interface for the Home interface
  • Java interface for the business object
  • Persistent store (only for Entity Beans)
  • Security roles and permissions
  • Stateful or Stateless (for Session Beans)

Old EJB containers from many vendors required more deployment information than that in the EJB specification. They would require the additional information as separate XML files, or some other configuration file format. An EJB platform vendor generally provided their own tools that would read this deployment descriptor, and possibly generated a set of classes that would implement the now deprecated Home and Remote interfaces.

Since EJB 3.0 (JSR 220), the XML descriptor is replaced by Java annotations set in the Enterprise Bean implementation (at source level), although it is still possible to use an XML descriptor instead of (or in addition to) the annotations. If an XML descriptor and annotations are both applied to the same attribute within an Enterprise Bean, the XML definition overrides the corresponding source-level annotation, although some XML elements can also be additive (e.g., an activation-config-property in XML with a different name than already defined via an @ActivationConfigProperty annotation will be added instead of replacing all existing properties).

Container variations

[edit]

Starting with EJB 3.1, the EJB specification defines two variants of the EJB container; a full version and a limited version. The limited version adheres to a proper subset of the specification called EJB 3.1 Lite [36][37] and is part of Java EE 6's web profile (which is itself a subset of the full Java EE 6 specification).

EJB 3.1 Lite excludes support for the following features:[38]

  • Remote interfaces
  • RMI-IIOP Interoperability
  • JAX-WS Web Service Endpoints
  • EJB Timer Service (@Schedule, @Timeout)
  • Asynchronous session bean invocations (@Asynchronous)
  • Message-driven beans

EJB 3.2 Lite excludes less features. Particularly it no longer excludes @Asynchronous and @Schedule/@Timeout, but for @Schedule it does not support the "persistent" attribute that full EJB 3.2 does support. The complete excluded list for EJB 3.2 Lite is:

  • Remote interfaces
  • RMI-IIOP Interoperability
  • JAX-WS Web Service Endpoints
  • Persistent timers ("persistent" attribute on @Schedule)
  • Message-driven beans

Version history

[edit]

EJB 4.0, final release (2020-05-22)

Jakarta Enterprise Beans 4.0, as a part of Jakarta EE 9, was a tooling release that mainly moved API package names from the top level javax.ejb package to the top level jakarta.ejb package.[39]

Other changes included removal of deprecated APIs that were pointless to move to the new top level package and the removal of features that depended on features that were removed from Java or elsewhere in Jakarta EE 9. The following APIs were removed:

  • methods relying on java.security.Identity which has been removed from Java 14.
  • methods relying on Jakarta XML RPC to reflect the removal of XML RPC from the Jakarta EE 9 Platform.
  • deprecated EJBContext.getEnvironment() method.
  • "Support for Distributed Interoperability" to reflect the removal of CORBA from Java 11 and the Jakarta EE 9 Platform.

Other minor changes include marking the Enterprise Beans 2.x API Group as "Optional" and making the Schedule annotation repeatable.

EJB 3.2.6, final release (2019-08-23)

Jakarta Enterprise Beans 3.2, as a part of Jakarta EE 8, and despite still using "EJB" abbreviation, this set of APIs has been officially renamed to "Jakarta Enterprise Beans" by the Eclipse Foundation so as not to tread on the Oracle "Java" trademark.

EJB 3.2, final release (2013-05-28)

JSR 345. Enterprise JavaBeans 3.2 was a relatively minor release that mainly contained specification clarifications and lifted some restrictions that were imposed by the spec but over time appeared to serve no real purpose. A few existing full EJB features were also demanded to be in EJB 3 lite and functionality that was proposed to be pruned in EJB 3.1 was indeed pruned (made optional).[40][41]

The following features were added:

  • Passivation of a stateful session bean can be deactivated via attribute on @Stateful annotation (passivationCapable = false)
  • TimerService can retrieve all active timers in the same EJB module (could previously only retrieve timers for the bean in which the TimerService was called)
  • Lifecycle methods (e.g. @PostConstruct) can be transactional for stateful session beans using the existing @TransactionAttribute annotation
  • Autocloseable interface implemented by embeddable container

EJB 3.1, final release (2009-12-10)

JSR 318. The purpose of the Enterprise JavaBeans 3.1 specification is to further simplify the EJB architecture by reducing its complexity from the developer's point of view, while also adding new functionality in response to the needs of the community:

  • Local view without interface (No-interface view)
  • .war packaging of EJB components
  • EJB Lite: definition of a subset of EJB
  • Portable EJB Global JNDI Names
  • Singletons (Singleton Session Beans)
  • Application Initialization and Shutdown Events
  • EJB Timer Service Enhancements
  • Simple Asynchrony (@Asynchronous for session beans)

EJB 3.0, final release (2006-05-11)

JSR 220 - Major changes: This release made it much easier to write EJBs, using 'annotations' rather than the complex 'deployment descriptors' used in version 2.x. The use of home and remote interfaces and the ejb-jar.xml file were also no longer required in this release, having been replaced with a business interface and a bean that implements the interface.

EJB 2.1, final release (2003-11-24)

JSR 153 - Major changes:

  • Web service support (new): stateless session beans can be invoked over SOAP/HTTP. Also, an EJB can easily access a Web service using the new service reference.
  • EJB timer service (new): Event-based mechanism for invoking EJBs at specific times.
  • Message-driven beans accepts messages from sources other than JMS.
  • Message destinations (the same idea as EJB references, resource references, etc.) has been added.
  • EJB query language (EJB-QL) additions: ORDER BY, AVG, MIN, MAX, SUM, COUNT, and MOD.
  • XML schema is used to specify deployment descriptors, replaces DTDs

EJB 2.0, final release (2001-08-22)

JSR 19 - Major changes: Overall goals:

  • The standard component architecture for building distributed object-oriented business applications in Java.
  • Make it possible to build distributed applications by combining components developed using tools from different vendors.
  • Make it easy to write (enterprise) applications: Application developers will not have to understand low-level transaction and state management details, multi-threading, connection pooling, and other complex low-level APIs.
  • Will follow the "Write Once, Run Anywhere" philosophy of Java. An enterprise Bean can be developed once, and then deployed on multiple platforms without recompilation or source code modification.
  • Address the development, deployment, and runtime aspects of an enterprise application’s life cycle.
  • Define the contracts that enable tools from multiple vendors to develop and deploy components that can interoperate at runtime.
  • Be compatible with existing server platforms. Vendors will be able to extend their existing products to support EJBs.
  • Be compatible with other Java APIs.
  • Provide interoperability between enterprise Beans and Java EE components as well as non-Java programming language applications.
  • Be compatible with the CORBA protocols (RMI-IIOP).

EJB 1.1, final release (1999-12-17)

Major changes:

  • XML deployment descriptors
  • Default JNDI contexts
  • RMI over IIOP
  • Security - role driven, not method driven
  • Entity Bean support - mandatory, not optional

Goals for Release 1.1:

  • Provide better support for application assembly and deployment.
  • Specify in greater detail the responsibilities of the individual EJB roles.

EJB 1.0 (1998-03-24)

Announced at JavaOne 1998,[42] Sun's third Java developers conference (March 24 through 27) Goals for Release 1.0:

  • Defined the distinct "EJB Roles" that are assumed by the component architecture.
  • Defined the client view of enterprise Beans.
  • Defined the enterprise Bean developer’s view.
  • Defined the responsibilities of an EJB Container provider and server provider; together these make up a system that supports the deployment and execution of enterprise Beans.

References

[edit]
[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
Jakarta Enterprise Beans (EJB) is a server-side software component architecture for modular construction of enterprise software, defining standardized components written in the Java programming language that encapsulate business logic and run within a managed container. As a core specification of the Jakarta EE platform, it enables the development of scalable, distributed applications by providing declarative services for transactions, security, concurrency, and resource management, allowing developers to focus on business functionality rather than infrastructure concerns. Enterprise beans operate in an EJB container, a runtime environment within a Jakarta EE-compliant application server (such as ) that intercepts calls to the beans and supplies essential services like lifecycle management, pooling, and integration with other Jakarta EE technologies. There are two primary categories of enterprise beans: session beans, which handle client interactions and include stateful (maintaining conversational state), stateless (handling multiple clients without state), and singleton (shared across the application) variants; and message-driven beans, which asynchronously process messages from providers, functioning as lightweight message listeners for event-driven architectures. Originally developed as Enterprise JavaBeans under the EE platform through the —starting with version 1.0 in 1998 as a component model for —EJB has evolved through multiple releases to simplify enterprise development, with significant simplifications in version 3.0 (2006) introducing annotations and . In 2017, transferred stewardship of Java EE to the , leading to the rebranding as in 2019 and the renaming of the specification to Jakarta Enterprise Beans, with the current version 4.0 (released in 2020 as part of Jakarta EE 9 and included in subsequent releases, including Jakarta EE 11 in 2025) featuring namespace changes from javax to jakarta and continued support for modern cloud-native deployments.

Overview

Specification

Jakarta Enterprise Beans (EJB) is a server-side component architecture designed for developing modular and distributed business logic within the Jakarta EE platform. It enables the creation of reusable, scalable enterprise applications by encapsulating business processes in components that can be deployed across distributed environments. The key principles of EJB emphasize component-based development, where developers focus on business logic while the container handles infrastructure concerns. This includes container-managed services for persistence via integration with Jakarta Persistence (JPA), transactions through Jakarta Transactions (JTA), and security using Jakarta Security. Portability is ensured by adhering to the specification, allowing beans to run on any compliant Jakarta EE server without vendor-specific modifications. In the EJB architecture, components are implemented as Plain Old Java Objects (POJOs) that are enhanced with metadata through annotations or XML descriptors for configuration and deployment. These beans are packaged and deployed into an EJB , which provides the runtime environment, manages lifecycles, and intercepts calls to deliver services transparently. This model simplifies development by abstracting complexities like and concurrency. EJB forms one of the core specifications in the platform, complementing others such as JPA for object-relational mapping and JTA for transaction demarcation to build full-stack enterprise solutions. The specification, which originated with Enterprise JavaBeans 1.0 in 1998, saw significant updates like JSR 318 for Enterprise JavaBeans 3.1 under and has evolved under the , adopting the jakarta.ejb.* namespace starting with version 4.0 for 9 and continuing in subsequent releases like 11. The current version, 4.0 (as of 11 released in June 2025), maintains while supporting modern SE features.

General Responsibilities

The Jakarta Enterprise Beans (EJB) container plays a central role in managing the lifecycle and execution of enterprise beans, ensuring and reliability in enterprise applications. It is responsible for pooling instances of stateless session beans to handle multiple client requests efficiently without creating new instances for each invocation, thereby optimizing resource usage. For stateful session beans, the container manages passivation and activation, passivating idle instances to secondary storage using algorithms like least-recently-used and activating them upon subsequent requests while invoking appropriate lifecycle callbacks such as @PrePassivate and @PostActivate. Additionally, the container oversees instance management, including creation via constructors, of resources and other beans using @EJB or Contexts and (CDI) mechanisms, and destruction through @PreDestroy callbacks. Developers, in turn, focus on implementing the core of enterprise beans while adhering to the EJB programming model. They must define business interfaces—either local or remote—or opt for a no-interface view, and annotate classes with @Stateless for stateless session beans, @Stateful for those maintaining conversational state, or @Singleton for shared instances. Developers are also tasked with handling exceptions appropriately, distinguishing between application exceptions that can be caught and rethrown and system exceptions that trigger instance removal or pooling. Furthermore, they ensure proper resource cleanup in lifecycle methods to avoid issues during passivation, such as nullifying non-serializable connections in @PrePassivate. The EJB container provides essential core services to support bean operations, including to prevent race conditions—such as serializing access to stateful instances or using locks for singletons—and for injecting dependencies like JDBC connections via the @Resource annotation into the java:comp/env namespace. It also facilitates interception mechanisms, allowing developers to address concerns like or validation through @AroundInvoke interceptors or lifecycle callbacks without embedding such logic directly in business methods. These services abstract away low-level details, enabling developers to concentrate on application-specific functionality. A key aspect of EJB invocation is the distinction between local and remote client views, which affects how beans are accessed and . Local views, used for collocated clients within the same application, employ pass-by-reference semantics for efficiency and do not require , while remote views support distributed access across JVMs using pass-by-value to ensure location transparency. Developers specify these views through interface annotations or deployment descriptors, with the container mediating the appropriate protocol.

History

Origins and Early Development

Enterprise JavaBeans (EJB) originated as a server-side component model developed by in 1997 to enable modular construction of scalable enterprise applications using . adopted and released the initial specification as EJB 1.0 on March 24, 1998, during the JavaOne conference, aiming to simplify by providing a standardized for deployment. The core motivation was to address the complexities of earlier distributed systems based on CORBA and RMI, which required developers to manage low-level details like transactions, , and persistence manually; EJB abstracted these into container-provided services, promoting component , portability across servers, and server-side for multi-user environments. EJB 1.1, finalized on December 17, 1999, standardized the model further by mandating entity bean support, replacing JavaBeans-based deployment descriptors with XML formats for better portability, and clarifying roles for developers, assemblers, and deployers. Key early features included session beans for encapsulating —either stateful for client-specific sessions or stateless for shared use—and entity beans for persistent data representation, with options for bean-managed persistence (BMP) or container-managed persistence (CMP) to handle database interactions transparently. These components integrated with the emerging J2EE platform, enabling full-stack enterprise development by combining EJB with technologies like servlets and JDBC, which drove early adoption among vendors seeking standardized, scalable solutions for transaction-oriented applications. Under the Java Community Process, EJB 2.0 (JSR 19) was released on August 22, 2001, introducing message-driven beans for asynchronous messaging via JMS integration, alongside enhancements to entity beans such as container-managed relationships (CMR) for modeling associations between persistent objects. This version improved finder methods with a portable (EJB QL) and bolstered through RMI-IIOP support, further simplifying distributed development. EJB 2.1 (JSR 153), finalized on November 24, 2003, extended these capabilities by adding web services support, allowing stateless session beans to be invoked via /HTTP using JAX-RPC and enabling JAXM for message-driven beans, thus aligning EJB with emerging service-oriented architectures while maintaining focus on core enterprise scalability.

Transition to Jakarta EE

In 2017, Oracle transferred the stewardship of Java EE, including the Enterprise JavaBeans (EJB) specification, to the primarily due to restrictions on the "Java" name, which prevented open-source relicensing under Eclipse's governance model. This move aimed to foster broader community involvement and ensure the platform's evolution as an open-source project, with initial contributions from , , and . The transition culminated in the rebranding to 8 in September 2019, marking the first release under Eclipse while maintaining functional compatibility with Java EE 8. The last EJB specification under the Java EE banner was version 3.2, finalized in 2013 via JSR 345 through the (JCP). Following the transfer, Jakarta Enterprise Beans 4.0 was released in November 2020 as part of 9, introducing a critical namespace change from javax.ejb to jakarta.ejb to resolve licensing and branding conflicts. Key updates in this version included the removal of outdated features such as support for java.security.Identity-dependent methods, JAX-RPC integration, EJBContext.getEnvironment(), and distributed interoperability mechanisms, streamlining the specification for modern environments. The specification further emphasized annotations for bean configuration—building on introductions from EJB 3.0—over XML descriptors, and deepened alignment with (CDI) for enhanced dependency management and portability across Jakarta EE components. Under Eclipse Foundation governance, the evolution of Jakarta Enterprise Beans became more community-driven, with active participation from vendors including , , , and Tomitribe through the Working Group. This shift promoted greater openness via transparent, consensus-based decision-making and Eclipse's Intellectual Property Policy, enabling faster release cycles compared to the JCP era—for instance, advancing from Jakarta EE 9 in 2020 to EE 10 in September 2022 and EE 11 on June 26, 2025. Jakarta Enterprise Beans remains at version 4.0 in EE 11. Additionally, the platform gained compatibility with contemporary versions, requiring Java SE 11 or higher starting with Jakarta EE 9 and supporting Java 17+ (with Java 21 recommended for runtime) in subsequent releases like EE 10 and 11, facilitating adoption in cloud-native and modular Java ecosystems.

Components

Session Beans

Session beans represent the core components in Jakarta Enterprise Beans for encapsulating , functioning as either client-specific or shared objects that handle transient processes without built-in . They execute within the EJB container, which manages their lifecycle, pooling, and invocation, and are invoked synchronously by clients through local, remote, or no-interface views. Unlike the now-deprecated entity beans, which were designed for persistent entity representation and data access, session beans focus on non-persistent operations and have been the preferred mechanism for business logic since EJB 3.0. Session beans are divided into three subtypes, each suited to different and needs. Stateful session beans maintain conversational state across multiple method calls for a specific client, associating instance variables with that client's session; the container ensures isolation by not sharing instances among clients. Stateless session beans, in contrast, hold no conversational state, allowing the container to pool and reuse instances interchangeably for any client, which enhances for high-volume operations. Singleton session beans provide exactly one instance per application, shared across all clients for the duration of the application's lifecycle, and support concurrent access with configurable locking mechanisms. Implementation of session beans relies on annotations applied to a plain class: @Stateful for stateful beans, @Stateless for stateless ones, and @Singleton for singletons, which may include @Startup for eager initialization or @DependsOn for dependency ordering. Access views include local interfaces for co-located clients (pass-by-reference semantics), remote interfaces for distributed invocation (pass-by-value), and no-interface views that expose the bean class's public methods directly for simple local use without an explicit interface. Stateful beans must implement passivation-capable state, serializing non-transient fields to secondary storage during idle periods via @PrePassivate and @PostActivate callbacks. Common use cases leverage these subtypes' strengths: stateful beans for interactive user sessions, such as maintaining a shopping cart's contents across requests; stateless beans for efficient, scalable tasks like mathematical computations or notifications that serve multiple users without ; and singleton beans for application-wide resources, including caches, configuration holders, or global counters that require shared access. For instance, a stateless bean might compute rates for transactions, while a singleton could track overall system metrics. Clients invoke session beans indirectly through container-provided proxies, obtained via dependency injection using the @EJB annotation or programmatic lookup in the Java Naming and Directory Interface (JNDI), such as java:global/app/module/BeanName!interface.Type, avoiding direct instantiation with new to enable container interception. Stateful beans support configurable timeouts via @StatefulTimeout to automatically remove idle instances after a specified duration, preventing resource exhaustion. Asynchronous invocation is possible with the @Asynchronous annotation on methods, returning Future or CompletionStage results for non-blocking calls.

Message-Driven Beans

Message-driven beans (MDBs) are a type of enterprise bean in Jakarta Enterprise Beans designed for asynchronous message processing, typically in conjunction with (JMS) queues or topics. They function as stateless components that act as message listeners, receiving and processing messages from messaging systems without direct client invocation, thereby decoupling message senders from receivers. This design enables scalable, event-driven architectures where MDBs have no client-visible identity or conversational state, ensuring they remain anonymous and focused solely on message handling. MDBs are activated through configuration that binds them to specific message destinations, such as queues or topics, often using resource adapters for integration with messaging providers. The primary configuration mechanism is the @MessageDriven annotation, which specifies the message listener interface (e.g., jakarta.jms.MessageListener) and activation properties like destination type and configuration details. Alternatively, activation can be defined in the ejb-jar.xml deployment descriptor, allowing the container to invoke the MDB upon message arrival at the bound endpoint. Message processing in MDBs occurs via the onMessage method, which the bean implements from the appropriate listener interface to execute on incoming messages. The container automatically invokes this method when a message is delivered, with each message handled independently and concurrently across instances. Transactions are enlisted automatically for container-managed scenarios, integrating message receipt and processing into the transaction context for reliability, such as rolling back on exceptions as detailed in the transactions specification. Common use cases for MDBs include event-driven architectures, such as processing orders from a JMS queue in an system or handling publish-subscribe notifications for real-time updates. They are particularly suited for workflows involving asynchronous integration, like updating multiple databases in response to events or managing concurrent message streams in distributed applications. For scalability, the container maintains a pool of MDB instances, similar to stateless session beans, to process multiple messages concurrently without maintaining client-specific state. This pooling allows load balancing across instances, with calls to a single instance serialized but overall throughput enhanced by distributing messages to available pooled beans. Pool size and behavior can be tuned via deployment configurations to match workload demands.

Lifecycle and Execution

Bean Lifecycle

The lifecycle of Jakarta Enterprise Beans (EJB) instances is managed by the EJB container, which handles creation, , passivation, and destruction to ensure efficient resource utilization and scalability. All bean types begin in a "Does Not Exist" state and transition to a "Method Ready" state upon instantiation, where they can service client requests. For stateless and singleton session beans, instances are pooled for reuse, while stateful session beans maintain conversational state and may enter a "Passivated" state during periods of inactivity. Message-driven beans (MDBs) follow a lifecycle akin to stateless session beans, with instances pooled for concurrent asynchronous message processing via the onMessage method; they support @PostConstruct for initialization after creation and @PreDestroy for cleanup before destruction, but lack passivation or due to their non-conversational, stateless nature. Stateless session beans follow a simple lifecycle without passivation, as they do not retain conversational state across invocations. Upon creation, the container invokes the bean's constructor, performs , and calls the @PostConstruct callback for initialization, transitioning the instance to the Method Ready pool. Client method calls are dispatched to pooled instances, which are returned to the pool after execution, enabling reuse across multiple clients. Destruction occurs via the @PreDestroy callback during application shutdown or explicit removal, releasing resources without state preservation. Stateful session beans support conversational state, introducing additional states and transitions for . From the Method Ready state, an instance handles client-specific interactions; if idle (not in a transaction), the may passivate it by invoking @PrePassivate to prepare for to secondary storage, transitioning to the Passivated state. On subsequent client access, restores the instance via @PostActivate, returning it to Method Ready. Completion of the conversation can be signaled by the client invoking a method annotated with @Remove, triggering @PreDestroy for cleanup. The may also evict idle instances via timeouts, invoking @PreDestroy to prevent resource exhaustion. Singleton session beans maintain a single shared instance per application, with no pooling or passivation due to their non-conversational nature. Creation occurs lazily on first access or eagerly if annotated with @Startup, following the standard sequence of constructor, , and @PostConstruct. The instance remains in the Method Ready state until application shutdown, at which point @PreDestroy is invoked for finalization. Concurrency is handled by the container, ensuring during method invocations. Lifecycle callbacks provide hooks for bean providers to manage resources and state. The @PostConstruct method initializes the bean after but before the first business method call, allowing access to SessionContext, JNDI, and resources. The @PreDestroy method performs cleanup symmetrically before removal. Stateful beans additionally use @PrePassivate to release non-serializable resources and @PostActivate to reacquire them post-restoration. Method interception via @AroundInvoke can wrap business methods for concerns like , though full details are covered elsewhere. These callbacks ensure deterministic behavior during container-managed transitions. For MDBs, @PostConstruct and @PreDestroy are invoked similarly, but @AroundInvoke applies to the onMessage method. The intervenes to optimize performance, such as pooling Method Ready instances for stateless beans and MDBs to minimize creation overhead and eager loading for @Startup singletons at deployment. For stateful beans, passivation thresholds and timeout configurations prevent bloat from long-lived conversations, with the container serializing only serializable state while discarding transients. These mechanisms collectively enable scalable, state-aware execution without developer intervention in instance management.

Transactions

Jakarta Enterprise Beans (EJBs) provide robust transaction management to ensure and consistency in enterprise applications, leveraging the Jakarta Transactions API (JTA) for demarcation and coordination. Transaction support in EJBs includes both container-managed transactions (CMT), where the EJB container automatically handles boundaries, and bean-managed transactions (BMT), where developers explicitly control them. This integration with JTA allows EJBs to participate in local or distributed transactions across multiple resources, such as databases, while adhering to properties. Container-managed transactions (CMT) are the default and recommended approach for most EJBs, as they simplify development by eliminating the need for explicit transaction code in the bean. In CMT, the container uses the @TransactionAttribute annotation to define behavior for business methods, with six possible values: REQUIRED (default, joins an existing transaction or starts a new one), REQUIRES_NEW (suspends any existing transaction and starts a new one), MANDATORY (requires an existing transaction, throws an exception if none), SUPPORTS (runs in the caller's transaction if present, otherwise non-transactionally), NOT_SUPPORTED (suspends any existing transaction and runs non-transactionally), and NEVER (runs non-transactionally and throws an exception if a transaction exists). These attributes integrate directly with JTA's TransactionManager for boundary management, ensuring the container demarcates transactions around method invocations. Message-driven beans support only CMT, with transactions typically spanning the onMessage method invocation. Bean-managed transactions (BMT) offer greater flexibility for complex scenarios, requiring the bean to programmatically handle transaction boundaries using the JTA UserTransaction interface, obtained via or JNDI lookup at java:comp/UserTransaction. In BMT, developers call methods such as begin() to start a transaction, commit() to end it successfully, and rollback() to abort it, typically within session bean methods marked with @TransactionManagement(TransactionManagementType.BEAN). Unlike CMT, BMT does not support nested transactions and prohibits certain container interventions, such as accessing setRollbackOnly from the EJBContext. BMT is not supported for message-driven beans. Transaction scopes in EJBs are typically per-method for CMT, where each business method invocation defines its own boundary based on the attribute, or per-bean for BMT, encompassing the explicit demarcation in the bean's code. Rollback rules distinguish between system exceptions (e.g., RuntimeException or errors), which automatically trigger rollback in CMT to maintain consistency, and application exceptions (e.g., checked exceptions), which do not unless the bean calls setRollbackOnly() on the session context or marks the exception with @ApplicationException(rollback = true). In BMT, rollbacks occur explicitly via rollback() or if an exception propagates without a commit. For distributed transactions involving multiple resources, EJBs rely on JTA's to ensure atomicity across participants, such as XA-compliant databases. The transaction manager coordinates resource managers via XAResource interfaces, first preparing all resources in phase one and then committing or rolling back in phase two if all prepare successfully, preventing partial updates in scenarios like updating records across separate databases. Best practices for EJB transactions emphasize using CMT for straightforward cases to reduce boilerplate and errors, while reserving BMT for scenarios requiring custom logic, such as conditional commits based on multiple operations. Developers should avoid long-running transactions by configuring timeouts (e.g., via setTransactionTimeout in BMT or server-wide settings, defaulting to 30 seconds in some implementations) to prevent resource locks and improve scalability. Effective exception handling is crucial: in CMT, catch application exceptions and invoke setRollbackOnly when partial failure occurs, logging the issue before rethrowing; in BMT, always pair begin with commit or rollback in a finally block to ensure cleanup.
Transaction AttributeBehavior if Client Has Transaction (T1)Behavior if No Client Transaction
REQUIREDJoins T1Starts new T2
REQUIRES_NEWSuspends T1, starts new T2Starts new T2
MANDATORYJoins T1Throws exception
SUPPORTSJoins T1Runs non-transactionally
NOT_SUPPORTEDSuspends T1, runs non-transactionallyRuns non-transactionally
NEVERThrows exceptionRuns non-transactionally
This table illustrates the propagation semantics for CMT attributes, highlighting how EJBs adapt to caller contexts.

Security and Interceptors

Jakarta Enterprise Beans (EJB) provide robust mechanisms to protect enterprise applications, encompassing both declarative and programmatic approaches. Declarative allows developers to specify access controls using or deployment descriptors without altering . For instance, the @RolesAllowed restricts method invocation to users in specified , while @PermitAll grants access to any authenticated caller and @DenyAll prohibits access entirely. These apply to business methods in session and message-driven beans, enabling the container to enforce at deployment time. Additionally, the @RunAs specifies a identity under which the bean operates when invoking other components, facilitating propagation of a specific rather than the caller's identity. Programmatic security complements declarative controls by allowing runtime checks within bean methods. The SessionContext interface exposes methods such as getCallerPrincipal(), which returns the Principal representing the caller, and isCallerInRole(String roleName), which verifies if the caller belongs to a given . These operations are available in business methods of session beans and message-driven beans, ensuring that sensitive logic can dynamically assess and respond to the security context. For MDBs, the MessageDrivenContext provides equivalent methods, though the caller principal may derive from the message sender or be unspecified if not authenticated. Lifecycle callback methods, however, execute in an unspecified security context, requiring developers to avoid security-dependent operations in interceptors like @PostConstruct or @PreDestroy. Security roles are declared using @DeclareRoles, mapping abstract roles to concrete principals during deployment. Interceptors in Jakarta Enterprise Beans address cross-cutting concerns, including , by interposing on method invocations and lifecycle events without modifying core bean code. Introduced in EJB 3.0, interceptors support annotations such as @AroundInvoke for business methods, which execute before and after the target method in the same context, allowing seamless integration of , validation, or additional checks. Lifecycle interceptors, including @PostConstruct, @PreDestroy, @PrePassivate, and @PostActivate, manage bean state transitions; for stateful session beans, these can operate within a transaction if specified, but their context remains undefined for portability. For MDBs, @AroundInvoke interceptors apply to the onMessage method. Binding interceptors to beans occurs via the @Interceptors annotation on the bean class or methods, supporting multiple interceptors in a defined order, or through XML deployment descriptors for finer control. In security contexts, interceptors can leverage InvocationContext to inspect or modify parameters, invocation targets, and contexts, enabling dynamic identity switching or enhanced verification. For example, an @AroundInvoke interceptor might validate caller roles before proceeding, throwing a exception if unauthorized, thus layering custom on top of container-managed protections. Container-provided interceptors, such as those for transactions or , execute before custom ones, ensuring consistent enforcement. This facility promotes modularity, as logic can be centralized in reusable interceptor classes applicable across multiple beans.

Services

Naming and Directory Services

In Jakarta Enterprise Beans (EJB), the Java Naming and Directory Interface (JNDI) serves as the primary mechanism for binding and locating enterprise beans within the environment, enabling clients to access bean instances without direct knowledge of their implementation details. The container automatically binds each EJB to a portable JNDI name upon deployment, following a structured syntax that includes the bean's name, module, and application context. For example, a bean named MyBean in a module myejb.jar within an application myapp.ear would be bound as java:global/myapp/myejb/MyBean. This binding supports both local and remote interfaces, with optional qualifiers for specific interfaces, such as java:global/myapp/myejb/MyBean!com.example.MyRemoteInterface. JNDI employs three distinct namespaces to scope bean accessibility: java:global for cross-application visibility, allowing beans to be referenced from any deployed application; java:app for application-scoped access within the same enterprise archive (); and java:module for module-local references, restricting visibility to components within the same EJB-JAR or WAR file. These namespaces ensure portability across compliant containers, with the application name derived from the file's base name unless overridden in deployment descriptors like application.xml. Bean names default to the unqualified class name but can be customized using annotations such as @Stateless(name = "CustomBeanName"). Access to bound EJBs occurs through portable extensions provided by the EJB specification. via the @EJB annotation allows server-managed clients, such as other EJBs, servlets, or managed beans, to obtain references transparently; for instance, @EJB MyBean myBean; injects the no-interface or interface view without explicit naming. For programmatic access, clients use the javax.naming.InitialContext to perform lookups, as in InitialContext ctx = new InitialContext(); MyBean bean = (MyBean) ctx.lookup("java:global/myapp/myejb/MyBean");, which is particularly useful for non-managed clients or dynamic resolution. These mechanisms are supported in lifecycle callbacks, methods, and methods, with EJBContext.lookup offering an alternative for bean instances to access their environment. While JNDI's core role centers on EJB resolution, it integrates with broader directory services such as LDAP to support enterprise-wide naming, where LDAP can serve as the underlying provider for storing and retrieving EJB-related administered objects alongside user directories and attributes. However, for EJB access, the focus remains on the container's managed rather than external directory queries, ensuring secure and efficient intra-application lookups. In modern Jakarta EE versions, the reliance on explicit JNDI lookups has diminished with the maturation of Contexts and (CDI), which provides a unified type-safe injection model using @Inject for EJBs and other beans, often supplanting @EJB and InitialContext in CDI-enabled environments. CDI integrates seamlessly with EJBs, allowing session beans to participate as CDI managed beans while retaining EJB-specific services, thus streamlining dependency management without direct JNDI interaction in many cases.

Remoting and Distributed Execution

Remote views in Jakarta Enterprise Beans enable distributed invocation of bean methods across different JVMs or servers, providing a location-independent client perspective. A session exposes a remote interface by annotating it with the @Remote , which designates the interface for access by clients outside the local . This can be applied to the interface itself or to the bean class to specify multiple remote interfaces. Traditionally, remote calls rely on RMI-IIOP as the underlying protocol for communication, allowing clients to invoke methods as if the bean were local, with arguments and return values passed by value to ensure portability across JVMs. In modern container implementations, alternatives such as HTTP-based transports or REST/JSON mappings are supported for lighter-weight remoting, particularly when integrating with web services. The EJB container generates client-side proxies, or stubs, that transparently handle the remote invocation, including serialization of parameters using Java serialization or compatible mechanisms, and propagation of remote exceptions to the client. These proxies are typically obtained via dependency injection with the @EJB annotation or JNDI lookup using a portable global JNDI name. For in distributed environments, EJB containers implement clustering to support load balancing and of remote invocations. Stateless session beans, in particular, can be deployed across a cluster of servers, where the container distributes client requests using algorithms like round-robin or weighted policies to balance load, while maintaining session affinity for stateful beans through replication or passivation. ensures that if a server fails, ongoing remote calls are redirected to another cluster member, often leveraging stub caching and retry mechanisms to minimize disruption. Stateful beans achieve via state replication or migration between nodes. Performance considerations are critical when designing remote EJBs, as network latency and serialization overhead can significantly impact throughput compared to local invocations. Developers should prefer local interfaces (@Local) for intra-application calls within the same JVM, which use pass-by-reference semantics for efficiency, reserving remote views for true cross-server distribution. To optimize remote performance, interfaces should be coarse-grained to reduce the number of calls—avoiding "chatty" designs with many fine-grained methods—and containers may enable call-by-reference optimizations within the same EAR file. In contemporary Jakarta EE applications, there is a reduced emphasis on traditional RMI-based remoting for EJBs, with a shift toward lighter protocols and integration with Eclipse MicroProfile specifications. MicroProfile's REST Client and Config APIs complement EJB remoting by enabling declarative HTTP/JSON invocations to beans exposed as REST endpoints, facilitating microservices architectures without the full overhead of IIOP. This evolution allows EJBs to coexist with non-Java clients and cloud-native deployments, while preserving backward compatibility for legacy remote views.

Events

Event handling in Jakarta Enterprise Beans (EJB) primarily leverages the Contexts and Dependency Injection (CDI) specification to enable between components through observer patterns. CDI provides a mechanism for firing and observing events without direct dependencies between producers and consumers, allowing EJBs to notify other beans or components of significant state changes. This approach promotes in enterprise applications by separating event producers from handlers. Asynchronous execution further enhances this by supporting non-blocking operations within session beans. CDI events are observed using the @Observes annotation on a method parameter, which identifies the event instance to be processed by the observer method in a bean class. Observer methods must have exactly one event parameter annotated with @Observes, and they can include additional qualifiers to filter events. To fire an event, a bean injects an instance of the jakarta.enterprise.event.Event interface and invokes its fire() method, passing the event payload; this synchronously notifies all matching observers within the deployment. Events support qualifiers, such as custom annotations, to enable typed and targeted notifications, ensuring precise delivery to relevant observers. Asynchronous methods in EJBs allow for non-blocking execution, marked by the @Asynchronous on session bean methods or at the class level to apply to all business methods. Such methods can return void for semantics or Future to allow clients to retrieve results later; in 8 and later, CompletionStage provides enhanced support for composing asynchronous operations. This feature is particularly useful in session beans for long-running tasks, decoupling the caller from the execution thread while maintaining EJB container management. Integration of CDI events with Jakarta Messaging (JMS) facilitates handling message-based events, where components can fire CDI events in response to JMS messages or vice versa, often using custom qualifiers for specificity; message-driven beans serve as a specialized event handler for JMS in this context (detailed in ### Message-Driven Beans). A key is decoupling application modules, such as firing an event to notify observers after completing a business operation like order processing, enabling independent scaling and maintenance of components. Event delivery in CDI is scoped to the container instance, typically within the same (VM) boundaries, ensuring reliable notification to observers in the same deployment without crossing network boundaries unless extended via messaging.

Development and Deployment

Implementation Practices

In modern implementations of Jakarta Enterprise Beans, developers create (POJO) classes that encapsulate , annotated to define the bean type and behavior. For instance, the @Stateless annotation designates a stateless session bean suitable for scalable operations without client-specific state, while @Stateful marks stateful session beans that maintain conversational state across method invocations. Similarly, @MessageDriven identifies message-driven beans for asynchronous message processing via . These annotations replace verbose deployment descriptors, simplifying development by embedding metadata directly in the class. Beans may expose functionality through business interfaces, plain Java interfaces annotated with @Local for co-located access or @Remote for distributed invocation, enabling pass-by-reference or pass-by-value semantics respectively. Alternatively, a no-interface view allows local clients to access public methods of the bean class directly, injected via @EJB or looked up via JNDI, which reduces boilerplate while maintaining for intra-application calls. This approach promotes , as clients depend on interfaces rather than concrete implementations. Best practices emphasize designing beans as thin layers that coordinate rather than implement core logic, delegating data access and operations to data access objects (DAOs) or lower-level services to enhance and . The exemplifies this, where a session bean acts as a coarse-grained , encapsulating interactions with entity beans or DAOs to minimize remote calls and centralize transaction management. For cross-cutting concerns like or auditing, developers apply interceptors via the @Interceptors on methods or classes, allowing modular extension without altering bean logic. In legacy pre-3.0 implementations, enterprise beans required explicit home interfaces extending javax.ejb.EJBHome (for remote) or javax.ejb.EJBLocalHome (for local), serving as factories for bean instances with mandatory create methods corresponding to ejbCreate in the bean class. Finder methods, such as findByPrimaryKey, were also defined in the home interface to locate existing entities, with corresponding ejbFind implementations in the bean for entity beans. Business methods were exposed via component interfaces extending javax.ejb.EJBObject or javax.ejb.EJBLocalObject, and XML deployment descriptors could override annotations or define bindings, though annotations were not yet standard. Testing EJBs typically involves unit tests using mocking frameworks like Mockito to isolate dependencies such as DAOs, ensuring bean methods function independently of external resources. For integration testing, frameworks like Arquillian deploy beans into embedded containers (e.g., Weld for CDI or OpenEJB), simulating the full runtime environment without a remote server, which verifies interactions with transactions and dependency injection. Arquillian's ShrinkWrap API builds deployable archives programmatically, facilitating repeatable tests across container implementations. Common pitfalls include attempting to manage state in stateless session beans, where instance variables may persist across pooled invocations but should not hold client-specific data, as the treats all instances interchangeably and may reinitialize them unpredictably. Developers must avoid non-serializable fields in stateful beans to prevent passivation failures, closing resources in @PrePassivate callbacks. Regarding exceptions, unchecked runtime exceptions propagate as system exceptions, potentially rolling back transactions and invalidating stateful instances, while application exceptions require explicit declaration to avoid wrapping and ensure proper client handling. Throwing EJBException for unrecoverable errors is recommended to trigger cleanup without misleading clients.

Deployment Configuration

Jakarta Enterprise Beans (EJBs) are typically packaged as files containing the bean class files, interfaces, and optional supporting classes, which can be deployed standalone or embedded within files alongside other modules such as archives (WARs). Within an EAR, the EJB resides in the root directory, while in a WAR, EJB classes may be placed in the WEB-INF/classes directory or bundled in a under WEB-INF/lib. The optional ejb-jar.xml deployment descriptor, located in the META-INF directory of the or WEB-INF of the WAR, allows for overrides of annotation-based metadata, such as transaction attributes or roles, ensuring portability across containers. Deployment descriptors in Jakarta EE primarily use XML for legacy configurations, with the ejb-jar.xml file adhering to the Jakarta XML schema to define bean structure and dependencies. For session beans, elements like <session-type> specify the type (e.g., Stateless, Stateful, or Singleton), while <ejb-name> uniquely identifies the bean within the module. Although annotations such as @Stateless or @Stateful are preferred for modern development to reduce XML verbosity, the descriptor provides a declarative alternative or supplement, particularly for assembly-time customizations by the application assembler. An example ejb-jar.xml snippet for a stateless session bean might include:

<ejb-jar xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/ejb-jar_4_0.xsd" version="4.0"> <session> <ejb-name>MyStatelessBean</ejb-name> <session-type>Stateless</session-type> </session> </ejb-jar>

<ejb-jar xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/ejb-jar_4_0.xsd" version="4.0"> <session> <ejb-name>MyStatelessBean</ejb-name> <session-type>Stateless</session-type> </session> </ejb-jar>

This schema ensures compliance with 4.0 standards for core EJB features. Environment entries enable configurable values for EJBs, declared in ejb-jar.xml using the <env-entry> element within the <session> or <message-driven> sections, allowing the deployer to customize behavior without code changes. For instance, a string entry might be defined as:

<env-entry> <env-entry-name>maxRetries</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>3</env-entry-value> </env-entry>

<env-entry> <env-entry-name>maxRetries</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>3</env-entry-value> </env-entry>

These entries are accessible via the java:comp/env JNDI context and can be injected directly into the bean using the @Resource annotation, such as @Resource(name="maxRetries") private String maxRetries;, promoting loose coupling and deployment-time flexibility. While the core EJB specification emphasizes portability through standard descriptors, container providers may include vendor-specific extensions in proprietary XML files (e.g., jboss-ejb3.xml for clustering or pooling configurations), which are placed alongside ejb-jar.xml but render the deployment non-portable across different servers. These extensions allow advanced features like custom resource adapters but must not conflict with standard metadata. The deployment process for EJBs involves a two-stage approach: first, the deployer uses container-provided tools to generate runtime classes and resolve dependencies, such as factories; second, the beans are installed into the operational environment. Build tools like Maven plugins (e.g., maven-ejb-plugin for packaging and cargo-maven3-plugin for deployment) facilitate automation, while server consoles in implementations like or support hot deployment for iterative development without full restarts.

Container Implementations

The reference implementation for Jakarta Enterprise Beans (EJB) is provided by Eclipse GlassFish, an open-source Jakarta EE server originally developed by Oracle and now maintained under the Eclipse Foundation. GlassFish serves as the baseline for verifying specification compliance and includes full support for EJB 4.0 features, such as session beans, message-driven beans, and interceptors, within its modular container architecture. Commercial and open-source alternatives offer robust EJB container implementations with varying emphases on enterprise scalability. Red Hat's , the community edition of (EAP), provides a full-featured EJB container with support for stateless and stateful session beans, including advanced transaction management and security integration. IBM , particularly its profile, delivers enterprise-grade EJB support compliant with 11, focusing on lightweight runtime for hybrid cloud environments while maintaining compatibility with legacy EJB 3.x applications. For lighter deployments, extends with EJB capabilities, supporting the EJB Lite subset alongside full Web Profile features in a minimal footprint suitable for . Implementations differ in key extensions beyond the core specification to address performance and reliability. excels in high-availability (HA) clustering, where stateful EJBs can replicate session state across nodes using Infinispan for , ensuring minimal in distributed setups. is common across containers, such as adjusting EJB pool sizes— for instance, allows configuration of steady and maximum pool sizes for stateless session beans to optimize resource utilization under varying loads, reducing latency by pre-allocating instances. Emerging extensions like enable native compilation of cloud-native applications using subsets such as CDI and MicroProfile, offering alternatives to traditional EJB with support for faster startup and lower memory usage. All certified EJB container implementations must pass the Jakarta EE Technology Compatibility Kit (TCK), a comprehensive test suite that verifies adherence to the specification for portability across vendors. This ensures that EJBs deployed on GlassFish behave identically when migrated to WildFly or WebSphere, minimizing vendor lock-in. With the release of Jakarta EE 11 in June 2025, EJB 4.0 remains the core specification, with major containers providing compatibility and enhancements for Java 21 and cloud-native features. Recent trends in EJB containers reflect a shift toward cloud-native architectures, with integrations for orchestration—such as WildFly's Helm charts and WebSphere Liberty's operator support—facilitating auto-scaling and resilient deployments. Additionally, reduced footprints via MicroProfile compatibility, as seen in TomEE and extensions, align EJB usage with serverless and , prioritizing low resource consumption over full-stack .

Examples

Session Bean Example

A simple example of a stateless session bean in Jakarta Enterprise Beans is a calculator that performs basic arithmetic operations, such as addition and multiplication. This bean encapsulates business logic without maintaining client-specific state, allowing the container to pool instances for efficient reuse across multiple invocations. The local business interface defines the contract for the bean's methods, marked with the @Local annotation to indicate in-VM access with pass-by-reference semantics. Here is an example interface:

java

import jakarta.ejb.Local; @Local public interface CalculatorLocal { int add(int a, int b); int multiply(int a, int b); }

import jakarta.ejb.Local; @Local public interface CalculatorLocal { int add(int a, int b); int multiply(int a, int b); }

The stateless session bean implementation uses the @Stateless annotation to declare its type, implementing the interface and providing the arithmetic methods. The container manages the bean's lifecycle, creating and destroying instances as needed from a pool. For simplicity, this example omits transaction or security configurations. Here is the bean class:

java

import jakarta.ejb.Stateless; @Stateless public class CalculatorBean implements CalculatorLocal { public int add(int a, int b) { return a + b; } public int multiply(int a, int b) { return a * b; } }

import jakarta.ejb.Stateless; @Stateless public class CalculatorBean implements CalculatorLocal { public int add(int a, int b) { return a + b; } public int multiply(int a, int b) { return a * b; } }

On the client side, such as in a servlet, the bean reference is injected using the @EJB annotation, enabling direct method invocation without explicit lookup. The Jakarta EE container resolves the dependency at runtime. Here is an example servlet that uses the bean:

java

import jakarta.ejb.EJB; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/calculator") public class CalculatorServlet extends HttpServlet { @EJB private CalculatorLocal calculator; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { int sum = calculator.add(5, 3); // Returns 8 int product = calculator.multiply(5, 3); // Returns 15 response.getWriter().println("Sum: " + sum + ", Product: " + product); } }

import jakarta.ejb.EJB; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/calculator") public class CalculatorServlet extends HttpServlet { @EJB private CalculatorLocal calculator; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { int sum = calculator.add(5, 3); // Returns 8 int product = calculator.multiply(5, 3); // Returns 15 response.getWriter().println("Sum: " + sum + ", Product: " + product); } }

As an alternative to annotations, the can be declared in the ejb-jar.xml deployment descriptor, which provides explicit configuration for the EJB . This XML approach is optional in but useful for overriding annotations or in environments requiring descriptor-based setup. A minimal snippet for the stateless calculator is:

xml

<?xml version="1.0" encoding="UTF-8"?> <ejb-jar xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/ejb-jar_4_0.xsd" version="4.0"> <session> <ejb-name>CalculatorBean</ejb-name> <business-local>CalculatorLocal</business-local> <ejb-class>CalculatorBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>[Container](/page/Container)</transaction-type> </session> </ejb-jar>

<?xml version="1.0" encoding="UTF-8"?> <ejb-jar xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/ejb-jar_4_0.xsd" version="4.0"> <session> <ejb-name>CalculatorBean</ejb-name> <business-local>CalculatorLocal</business-local> <ejb-class>CalculatorBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>[Container](/page/Container)</transaction-type> </session> </ejb-jar>

When deployed to a server, such as Apache OpenEJB or , the pools instances of the CalculatorBean and assigns them to incoming requests. For the servlet example, a GET request to /calculator invokes the methods, producing output like "Sum: 8, Product: 15", demonstrating synchronous execution without client state persistence. The @Stateless instructs the to handle pooling and passivation, ensuring for concurrent calls while keeping the example focused on core bean mechanics. These examples are compatible with Jakarta Enterprise Beans 4.0, as used in Jakarta EE 10 and 11 (as of 2025).

Message-Driven Bean Example

A representative example of a Message-Driven Bean (MDB) in Jakarta Enterprise Beans involves processing JMS messages asynchronously for logging purposes, such as recording incoming text payloads from a queue. This illustrates the MDB's role in handling decoupled, event-driven communication without direct client invocation. The example draws from the official tutorial's simplemessage application, which demonstrates queue-based message consumption. The MDB class, SimpleMessageBean, implements the jakarta.jms.MessageListener interface and uses annotations to define its configuration. The @MessageDriven annotation specifies the bean type, while @ActivationConfigProperty elements bind it to a JMS queue.

java

import jakarta.ejb.ActivationConfigProperty; import jakarta.ejb.MessageDriven; import jakarta.jms.JMSException; import jakarta.jms.Message; import jakarta.jms.MessageListener; import jakarta.jms.TextMessage; import java.util.logging.Level; import java.util.logging.Logger; @MessageDriven( activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/MyQueue"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "jakarta.jms.Queue") } ) public class SimpleMessageBean implements MessageListener { private static final Logger logger = Logger.getLogger("com.example.SimpleMessageBean"); @Override public void onMessage(Message message) { try { if (message instanceof TextMessage) { String payload = ((TextMessage) message).getText(); logger.log(Level.INFO, "Message received and logged: {0}", payload); } } catch (JMSException e) { logger.log(Level.SEVERE, "Error processing JMS message: {0}", e.getMessage()); } } }

import jakarta.ejb.ActivationConfigProperty; import jakarta.ejb.MessageDriven; import jakarta.jms.JMSException; import jakarta.jms.Message; import jakarta.jms.MessageListener; import jakarta.jms.TextMessage; import java.util.logging.Level; import java.util.logging.Logger; @MessageDriven( activationConfig = { @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/MyQueue"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "jakarta.jms.Queue") } ) public class SimpleMessageBean implements MessageListener { private static final Logger logger = Logger.getLogger("com.example.SimpleMessageBean"); @Override public void onMessage(Message message) { try { if (message instanceof TextMessage) { String payload = ((TextMessage) message).getText(); logger.log(Level.INFO, "Message received and logged: {0}", payload); } } catch (JMSException e) { logger.log(Level.SEVERE, "Error processing JMS message: {0}", e.getMessage()); } } }

This onMessage method extracts the text payload and logs it, with to manage processing errors. The configuration links the to the JNDI name jms/MyQueue and specifies a queue destination type, enabling the to route messages accordingly. For setup, the must configure the JMS resources, including the queue jms/MyQueue and the default connection factory java:comp/DefaultJMSConnectionFactory. These are typically administered via the server's console or deployment descriptors, ensuring the MDB can connect without explicit client-side wiring. A sender, such as an application client or another enterprise , produces messages to trigger the MDB. In the simplemessage example, the SimpleMessageClient sends three text messages to the queue using resource injection.

java

import jakarta.annotation.Resource; import jakarta.jms.ConnectionFactory; import jakarta.jms.JMSContext; import jakarta.jms.JMSProducer; import jakarta.jms.Queue; public class SimpleMessageClient { @Resource(lookup = "java:comp/DefaultJMSConnectionFactory") private static ConnectionFactory connectionFactory; @Resource(lookup = "jms/MyQueue") private static Queue queue; private static final int NUM_MSGS = 3; public static void main(String[] args) { try (JMSContext context = connectionFactory.createContext()) { for (int i = 0; i < NUM_MSGS; i++) { String text = "This is message " + (i + 1); JMSProducer producer = context.createProducer(); producer.send(queue, text); } } } }

import jakarta.annotation.Resource; import jakarta.jms.ConnectionFactory; import jakarta.jms.JMSContext; import jakarta.jms.JMSProducer; import jakarta.jms.Queue; public class SimpleMessageClient { @Resource(lookup = "java:comp/DefaultJMSConnectionFactory") private static ConnectionFactory connectionFactory; @Resource(lookup = "jms/MyQueue") private static Queue queue; private static final int NUM_MSGS = 3; public static void main(String[] args) { try (JMSContext context = connectionFactory.createContext()) { for (int i = 0; i < NUM_MSGS; i++) { String text = "This is message " + (i + 1); JMSProducer producer = context.createProducer(); producer.send(queue, text); } } } }

This sender code creates a JMS context and dispatches simple text messages, simulating payload logging scenarios like audit trails or notifications. Deployment involves packaging the MDB in an EJB-JAR file within an EAR archive, which the container deploys to servers like or . While annotations handle most configurations, the ejb-jar.xml deployment descriptor provides an equivalent XML-based binding for the destination, useful for overriding or legacy setups. For instance:

xml

<?xml version="1.0" encoding="UTF-8"?> <ejb-jar xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/ejb-jar_4_0.xsd" version="4.0"> <enterprise-beans> <message-driven> <ejb-name>SimpleMessageBean</ejb-name> <ejb-class>com.example.SimpleMessageBean</ejb-class> <messaging-type>jakarta.jms.MessageListener</messaging-type> <activation-config> <activation-config-property> <activation-config-property-name>destinationLookup</activation-config-property-name> <activation-config-property-value>jms/MyQueue</activation-config-property-value> </activation-config-property> <activation-config-property> <activation-config-property-name>destinationType</activation-config-property-name> <activation-config-property-value>jakarta.jms.Queue</activation-config-property-value> </activation-config-property> </activation-config> </message-driven> </enterprise-beans> </ejb-jar>

<?xml version="1.0" encoding="UTF-8"?> <ejb-jar xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/ejb-jar_4_0.xsd" version="4.0"> <enterprise-beans> <message-driven> <ejb-name>SimpleMessageBean</ejb-name> <ejb-class>com.example.SimpleMessageBean</ejb-class> <messaging-type>jakarta.jms.MessageListener</messaging-type> <activation-config> <activation-config-property> <activation-config-property-name>destinationLookup</activation-config-property-name> <activation-config-property-value>jms/MyQueue</activation-config-property-value> </activation-config-property> <activation-config-property> <activation-config-property-name>destinationType</activation-config-property-name> <activation-config-property-value>jakarta.jms.Queue</activation-config-property-value> </activation-config-property> </activation-config> </message-driven> </enterprise-beans> </ejb-jar>

In operation, the EJB container maintains a pool of MDB instances, similar to stateless session beans, to handle concurrent messages efficiently without client-managed threading. Message delivery occurs within a container-managed transaction: successful onMessage execution commits the transaction, acknowledging and removing the message from the queue; runtime exceptions trigger a , redelivering the message after a configurable delay to ensure reliability. This MDB pattern promotes decoupling by allowing producers to send messages without waiting for processing, enhancing system scalability and through asynchronous messaging and automatic error recovery via rollbacks.

Version History

Java EE Eras

The Enterprise JavaBeans (EJB) specification originated in the Java EE ecosystem with version 1.0, released in March 1998, which introduced the foundational concepts of session beans for and entity beans for data persistence, along with home and remote interfaces for client access. This initial release established EJB as a server-side component model for distributed enterprise applications, emphasizing container-managed services such as transaction and security handling. EJB 1.1, finalized in late 1999 as part of J2EE 1.2, refined these basics by mandating XML-based deployment descriptors for packaging and configuration, enabling better portability across application servers while retaining the core session and entity bean types. EJB 2.0, specified under JSR 19 and released in 2001, expanded the architecture to support message-driven beans for asynchronous messaging via JMS integration, alongside enhancements to entity beans including container-managed persistence (CMP) and bean-managed persistence (BMP) options with a portable (EJB QL) for finder methods. These additions facilitated relationships between beans, inheritance, and bulk operations through extended home interfaces, while introducing interceptors for container callbacks and RMI/IIOP for server interoperability. Building on this, EJB 2.1 (JSR 153, 2003) incorporated web services support through JAX-RPC mappings for session beans, extended message-driven beans for method-level acknowledgments, and refined EJB QL with aggregate functions and outer joins to improve query expressiveness. The EJB 3.0 specification (JSR 220, finalized in 2006) marked a significant simplification by leveraging Java annotations for metadata, allowing plain old Java objects (POJOs) to serve as beans without mandatory interfaces or verbose XML descriptors, and introducing dependency injection alongside interceptors for aspect-oriented extensions. This version deprecated legacy entity beans from EJB 1.1/2.x in favor of integration with the Java Persistence API (JPA), shifting persistence responsibilities to a more lightweight, ORM-focused model while maintaining backward compatibility for existing deployments. Subsequent releases aligned EJB with evolving Java EE platforms: EJB 3.1 (JSR 318, 2009) added asynchronous method invocations, singleton session beans for shared state, global JNDI access without portable extensions, and cron-like timer scheduling, eliminating the need for local business interfaces in many cases. EJB 3.2 (JSR 345, 2013) provided minor refinements, including enhanced transaction timeout controls and alignment with Java EE 7 and 8, focusing on PaaS compatibility without major architectural shifts.

Jakarta EE Eras

Jakarta EE 8, released in 2019, marked the initial transition of Enterprise JavaBeans to the Jakarta ecosystem under the Eclipse Foundation's governance, rebranding EJB 3.2 with minimal substantive changes to the specification while retaining compatibility with prior Java EE implementations. This version focused on stabilizing the core architecture for component-based business applications without introducing new features, ensuring seamless adoption for existing deployments. Jakarta EE 9, released in December 2020, introduced EJB 4.0, which primarily addressed the namespace migration from javax.* to jakarta.* to resolve trademark issues and enable open-source evolution. Jakarta EE 10, released in September 2022, continued with EJB 4.0. These updates required Java SE 8 or higher as the minimum baseline for EE 9, raised this to Java SE 11 or higher for EE 10, and eliminated dependencies like the javaee.jar artifact in favor of modular Jakarta APIs. EJB 4.0 also removed deprecated elements such as entity beans and the embeddable EJB container to streamline the model for modern enterprise needs. Jakarta EE 11, released on June 26, 2025, incorporated EJB without major specification alterations, maintaining EJB 4.0 while aligning with broader platform enhancements like CDI 4.1 integration for improved dependency injection. It added compatibility for Java SE 21 features, including virtual threads in the updated Concurrency Utilities specification, allowing EJB containers to leverage lightweight threading for better scalability in concurrent applications, and raised the minimum baseline to Java SE 17 or higher. The release emphasized no breaking changes to EJB's core functionality, prioritizing stability across certified runtimes. Looking ahead, EJB 4.1 is under development for inclusion in 12, tentatively scheduled for general availability in 2026, with a focus on enhancing configuration consistency and supporting cloud-native deployment patterns. Across these eras, key advancements include refined annotations for , deeper interoperability with Eclipse MicroProfile for microservices, and validated (TCK) compliance on emerging servers like Eclipse GlassFish and Open Liberty.

References

Add your contribution
Related Hubs
User Avatar
No comments yet.