Recent from talks
Contribute something
Nothing was collected or created yet.
Jakarta Enterprise Beans
View on WikipediaJakarta 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:
- Transaction processing
- Integration with the persistence services offered by the Jakarta Persistence (JPA)
- Concurrency control
- Event-driven programming using Jakarta Messaging (JMS) and Jakarta Connectors (JCA)
- Asynchronous method invocation
- Job scheduling
- Naming and directory services via Java Naming and Directory Interface (JNDI)
- Interprocess Communication using RMI-IIOP and Web services
- Security (JCE and JAAS)
- Deployment of software components in an application server
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]
| 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]
| 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.Identitywhich 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
@Statefulannotation (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@TransactionAttributeannotation - 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 (
@Asynchronousfor 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]- ^ "Jakarta Enterprise Beans Specification". jakarta.ee. Retrieved 2025-04-06.
- ^ J2EE Design and Development, 2002 Wrox Press Ltd., p. 5.
- ^ J2EE Design and Development, 2002, Wrox Press Ltd., p. 19.
- ^ JSR 318, 4.1, http://jcp.org/en/jsr/detail?id=318
- ^ "Optional Local Business Interfaces (Ken Saks's Blog)". Archived from the original on 19 November 2015. Retrieved 1 June 2016.
- ^ JSR 318, 4.5, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 4.6, http://jcp.org/en/jsr/detail?id=318
- ^ a b JSR 318, 4.10.3, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 4.3.14, 21.4.2, http://jcp.org/en/jsr/detail?id=318
- ^ "Persistence Context in Stateful". Archived from the original on 16 March 2008. Retrieved 1 June 2016.
- ^ JSR 318, 4.7, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 4.3.14, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 4.8, http://jcp.org/en/jsr/detail?id=318
- ^ "Singleton EJB". Openejb.apache.org. Archived from the original on 2010-05-24. Retrieved 2012-06-17.
- ^ JSR 318, 5.1, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 5.7.2, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 5.4.2, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 5.6.2, http://jcp.org/en/jsr/detail?id=318
- ^ Developing Quartz MDB (29 April 2009). "Developing Quartz MDB". Mastertheboss.com. Retrieved 2012-06-17.
- ^ JSR 318, Chapter 17, http://jcp.org/en/jsr/detail?id=318
- ^ "Security Annotations". Openejb.apache.org. Retrieved 2012-06-17.
- ^ JSR 318, Chapter 13, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 13.6.2, http://jcp.org/en/jsr/detail?id=318
- ^ "Transaction Annotations". Openejb.apache.org. Retrieved 2012-06-17.
- ^ JSR 318, 13.3.6, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 4.4, http://jcp.org/en/jsr/detail?id=318
- ^ "Portable Global JNDI names (MaheshKannan)". Blogs.oracle.com. Archived from the original on 2011-06-20. Retrieved 2012-06-17.
- ^ "Portable Global JNDI Names (Ken Saks's Blog)". Blogs.oracle.com. Archived from the original on 2011-12-29. Retrieved 2012-06-17.
- ^ JSR 318, Chapter 15, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 2.6, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 3.2.4, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 4.3.6, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, 2.7, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 311, Chapter 6.2, http://jcp.org/en/jsr/detail?id=311
- ^ "Communication between JBoss AS 5 and JBoss AS 6 | JBoss AS | JBoss Community". Community.jboss.org. Retrieved 2012-06-17.
- ^ "Resin Java EE 6 Web Profile - Resin 3.0". Wiki.caucho.com. 2010-02-12. Archived from the original on 2012-03-23. Retrieved 2012-06-17.
- ^ JSR 318, 21.1 EJB 3.1 Lite, http://jcp.org/en/jsr/detail?id=318
- ^ JSR 318, Table 27 - Required contents of EJB 3.1 Lite and Full EJB 3.1 API, http://jcp.org/en/jsr/detail?id=318
- ^ "What is New in This Release". Jakarta Enterprise Beans, Core Features. Jakarta Enterprise Beans 4.0. Jakarta EE. November 5, 2020. Retrieved 2020-12-05.
- ^ "What's new in EJB 3.2 ? - Java EE 7 chugging along! (Arun Gupta, Miles to go ...)". Retrieved 1 June 2016.
- ^ "If you didn't know what is coming in EJB 3.2... (Marina Vatkina's Weblog)". Archived from the original on 4 March 2016. Retrieved 1 June 2016.
- ^ "JavaOne Conference Trip Report: Enterprise JavaBeans Technology: Developing and Deploying Business Applications as Components". Alephnaught.com. Retrieved 2012-06-17.
External links
[edit]- Official website

- Java EE 8 API Javadocs
- Jakarta Enterprise Beans Specification
- EJB 3.0 API Javadocs
- The EJB 3.0 Specification
- Sun's EJB 3.0 Tutorial
- EJB (3.0) Glossary
- EJB FAQ
- JSR 345 (EJB 3.2)
- JSR 318 (EJB 3.1)
- JSR 220 (EJB 3.0)
- JSR 153 (EJB 2.1)
- JSR 19 (EJB 2.0)
- "Working with Message-Driven Beans" from EJB3 in Action, Second Edition
- Client invokes an EJB
Jakarta Enterprise Beans
View on Grokipediajavax to jakarta and continued support for modern cloud-native deployments.[4][1][5]
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.[1] 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.[1][6] 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 container, which provides the runtime environment, manages lifecycles, and intercepts calls to deliver services transparently. This model simplifies development by abstracting complexities like resource management and concurrency.[1][6] EJB forms one of the core specifications in the Jakarta EE 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 Java EE and has evolved under the Eclipse Foundation, adopting thejakarta.ejb.* namespace starting with version 4.0 for Jakarta EE 9 and continuing in subsequent releases like Jakarta EE 11. The current version, 4.0 (as of Jakarta EE 11 released in June 2025), maintains backward compatibility while supporting modern Java SE features.[1][5]
General Responsibilities
The Jakarta Enterprise Beans (EJB) container plays a central role in managing the lifecycle and execution of enterprise beans, ensuring scalability 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, dependency injection of resources and other beans using @EJB or Contexts and Dependency Injection (CDI) mechanisms, and destruction through @PreDestroy callbacks.[6][2] Developers, in turn, focus on implementing the core business logic 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.[6][2] The EJB container provides essential core services to support bean operations, including concurrency control to prevent race conditions—such as serializing access to stateful instances or using locks for singletons—and resource management 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 cross-cutting concerns like logging 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.[6][2] A key aspect of EJB invocation is the distinction between local and remote client views, which affects how beans are accessed and serialized. Local views, used for collocated clients within the same application, employ pass-by-reference semantics for efficiency and do not require serialization, while remote views support distributed access across JVMs using pass-by-value serialization to ensure location transparency. Developers specify these views through interface annotations or deployment descriptors, with the container mediating the appropriate protocol.[6][2]History
Origins and Early Development
Enterprise JavaBeans (EJB) originated as a server-side component model developed by IBM in 1997 to enable modular construction of scalable enterprise applications using Java.[7] Sun Microsystems adopted and released the initial specification as EJB 1.0 on March 24, 1998, during the JavaOne conference, aiming to simplify distributed computing by providing a standardized architecture for business logic deployment.[8] 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, security, and persistence manually; EJB abstracted these into container-provided services, promoting component reuse, portability across servers, and server-side scalability for multi-user environments.[9] 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.[9] Key early features included session beans for encapsulating business logic—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.[9] 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.[9] 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.[10][11] This version improved finder methods with a portable query language (EJB QL) and bolstered interoperability through RMI-IIOP support, further simplifying distributed development.[10] 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 SOAP/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.[12]Transition to Jakarta EE
In 2017, Oracle transferred the stewardship of Java EE, including the Enterprise JavaBeans (EJB) specification, to the Eclipse Foundation primarily due to trademark restrictions on the "Java" name, which prevented open-source relicensing under Eclipse's governance model.[13] This move aimed to foster broader community involvement and ensure the platform's evolution as an open-source project, with initial contributions from Oracle, IBM, and Red Hat.[13] The transition culminated in the rebranding to Jakarta EE 8 in September 2019, marking the first release under Eclipse while maintaining functional compatibility with Java EE 8.[14] The last EJB specification under the Java EE banner was version 3.2, finalized in 2013 via JSR 345 through the Java Community Process (JCP).[15] Following the transfer, Jakarta Enterprise Beans 4.0 was released in November 2020 as part of Jakarta EE 9, introducing a critical namespace change fromjavax.ejb to jakarta.ejb to resolve licensing and branding conflicts.[1] 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.[16] The specification further emphasized annotations for bean configuration—building on introductions from EJB 3.0—over XML descriptors, and deepened alignment with Contexts and Dependency Injection (CDI) for enhanced dependency management and portability across Jakarta EE components.[6]
Under Eclipse Foundation governance, the evolution of Jakarta Enterprise Beans became more community-driven, with active participation from vendors including Red Hat, IBM, Fujitsu, and Tomitribe through the Jakarta EE 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.[5] Jakarta Enterprise Beans remains at version 4.0 in EE 11. Additionally, the platform gained compatibility with contemporary Java 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 business logic, functioning as either client-specific or shared objects that handle transient processes without built-in persistence. 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.[6] Session beans are divided into three subtypes, each suited to different scalability and state management 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 scalability 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.[6][2] Implementation of session beans relies on annotations applied to a plain Java 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 business 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.[6]
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 email notifications that serve multiple users without personalization; 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 tax rates for e-commerce transactions, while a singleton could track overall system metrics.[2]
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.[6][2]
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 Jakarta Messaging (JMS) queues or topics.[17] 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.[17] 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.[17] 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.[17] 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.[17] 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.[17]
Message processing in MDBs occurs via the onMessage method, which the bean implements from the appropriate listener interface to execute business logic on incoming messages.[17] The container automatically invokes this method when a message is delivered, with each message handled independently and concurrently across instances.[17] 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.[17]
Common use cases for MDBs include event-driven architectures, such as processing orders from a JMS queue in an e-commerce system or handling publish-subscribe notifications for real-time updates.[17] 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.[17]
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.[17] 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.[17] Pool size and behavior can be tuned via deployment configurations to match workload demands.[17]
Lifecycle and Execution
Bean Lifecycle
The lifecycle of Jakarta Enterprise Beans (EJB) instances is managed by the EJB container, which handles creation, activation, 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 theonMessage method; they support @PostConstruct for initialization after creation and @PreDestroy for cleanup before destruction, but lack passivation or activation due to their non-conversational, stateless nature.[18]
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 dependency injection, 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.[19]
Stateful session beans support conversational state, introducing additional states and transitions for resource management. From the Method Ready state, an instance handles client-specific interactions; if idle (not in a transaction), the container may passivate it by invoking @PrePassivate to prepare for serialization to secondary storage, transitioning to the Passivated state. On subsequent client access, activation 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 container may also evict idle instances via timeouts, invoking @PreDestroy to prevent resource exhaustion.[20]
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, dependency injection, 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 thread safety during method invocations.[21]
Lifecycle callbacks provide hooks for bean providers to manage resources and state. The @PostConstruct method initializes the bean after dependency injection 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 cross-cutting concerns like logging, though full chaining 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.[22]
The container 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 memory 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.[23]
Transactions
Jakarta Enterprise Beans (EJBs) provide robust transaction management to ensure data integrity and consistency in enterprise applications, leveraging the Jakarta Transactions API (JTA) for demarcation and coordination.[24] 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.[25] This integration with JTA allows EJBs to participate in local or distributed transactions across multiple resources, such as databases, while adhering to ACID properties.[26] 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.[25] 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).[26] 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.[27][24]
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 dependency injection or JNDI lookup at java:comp/UserTransaction.[25] 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).[28] 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.[25]
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.[26] 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).[25] In BMT, rollbacks occur explicitly via rollback() or if an exception propagates without a commit.[28]
For distributed transactions involving multiple resources, EJBs rely on JTA's two-phase commit protocol to ensure atomicity across participants, such as XA-compliant databases.[24] 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.[25]
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.[28] 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.[26] 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.[25]
| Transaction Attribute | Behavior if Client Has Transaction (T1) | Behavior if No Client Transaction |
|---|---|---|
| REQUIRED | Joins T1 | Starts new T2 |
| REQUIRES_NEW | Suspends T1, starts new T2 | Starts new T2 |
| MANDATORY | Joins T1 | Throws exception |
| SUPPORTS | Joins T1 | Runs non-transactionally |
| NOT_SUPPORTED | Suspends T1, runs non-transactionally | Runs non-transactionally |
| NEVER | Throws exception | Runs non-transactionally |
Security and Interceptors
Jakarta Enterprise Beans (EJB) provide robust security mechanisms to protect enterprise applications, encompassing both declarative and programmatic approaches. Declarative security allows developers to specify access controls using annotations or deployment descriptors without altering business logic. For instance, the@RolesAllowed annotation restricts method invocation to users in specified security roles, while @PermitAll grants access to any authenticated caller and @DenyAll prohibits access entirely.[6] These annotations apply to business methods in session and message-driven beans, enabling the container to enforce role-based access control at deployment time. Additionally, the @RunAs annotation specifies a security identity under which the bean operates when invoking other components, facilitating propagation of a specific role rather than the caller's identity.[29]
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 role.[6] 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.[30] Security roles are declared using @DeclareRoles, mapping abstract roles to concrete principals during deployment.[29]
Interceptors in Jakarta Enterprise Beans address cross-cutting concerns, including security, 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 security context, allowing seamless integration of logging, validation, or additional authorization checks.[6] 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 security context remains undefined for portability. For MDBs, @AroundInvoke interceptors apply to the onMessage method.[30]
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.[6] In security contexts, interceptors can leverage InvocationContext to inspect or modify parameters, invocation targets, and contexts, enabling dynamic identity switching or enhanced role verification.[31] For example, an @AroundInvoke interceptor might validate caller roles before proceeding, throwing a security exception if unauthorized, thus layering custom security on top of container-managed protections. Container-provided interceptors, such as those for transactions or security, execute before custom ones, ensuring consistent enforcement.[6] This facility promotes modularity, as security 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 application server environment, enabling clients to access bean instances without direct knowledge of their implementation details.[6] 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 namedMyBean in a module myejb.jar within an application myapp.ear would be bound as java:global/myapp/myejb/MyBean.[6] This binding supports both local and remote interfaces, with optional qualifiers for specific interfaces, such as java:global/myapp/myejb/MyBean!com.example.MyRemoteInterface.[2]
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 (EAR); and java:module for module-local references, restricting visibility to components within the same EJB-JAR or WAR file.[6] These namespaces ensure portability across compliant containers, with the application name derived from the EAR file's base name unless overridden in deployment descriptors like application.xml.[2] Bean names default to the unqualified class name but can be customized using annotations such as @Stateless(name = "CustomBeanName").[6]
Access to bound EJBs occurs through portable extensions provided by the EJB specification. Dependency injection 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 business interface view without explicit naming.[2] 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.[6] These mechanisms are supported in lifecycle callbacks, business methods, and dependency injection methods, with EJBContext.lookup offering an alternative for bean instances to access their environment.[2]
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.[32] However, for EJB access, the focus remains on the container's managed namespace rather than external directory queries, ensuring secure and efficient intra-application lookups.[6]
In modern Jakarta EE versions, the reliance on explicit JNDI lookups has diminished with the maturation of Contexts and Dependency Injection (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.[33] 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.[6]
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 bean exposes a remote business interface by annotating it with the@Remote annotation, which designates the interface for access by clients outside the local application server. This annotation can be applied to the interface itself or to the bean class to specify multiple remote interfaces.[34][35]
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.[36][6][35]
For high availability in distributed environments, EJB containers implement clustering to support load balancing and failover 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. Failover 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 failover via state replication or migration between nodes.[37][38]
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.[39][34]
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.[40][6]
Events
Event handling in Jakarta Enterprise Beans (EJB) primarily leverages the Contexts and Dependency Injection (CDI) specification to enable loose coupling 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 modular design 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 annotation on session bean methods or at the class level to apply to all business methods. Such methods can return void for fire-and-forget semantics or FutureDevelopment and Deployment
Implementation Practices
In modern implementations of Jakarta Enterprise Beans, developers create Plain Old Java Object (POJO) classes that encapsulate business logic, 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.[2] Similarly, @MessageDriven identifies message-driven beans for asynchronous message processing via Jakarta Messaging.[41] These annotations replace verbose deployment descriptors, simplifying development by embedding metadata directly in the class.[41]
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.[2] 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 type safety for intra-application calls.[41] This approach promotes loose coupling, as clients depend on interfaces rather than concrete implementations.[2]
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 maintainability and testability. The session facade pattern exemplifies this, where a session bean acts as a coarse-grained entry point, encapsulating interactions with entity beans or DAOs to minimize remote calls and centralize transaction management.[42] For cross-cutting concerns like logging or auditing, developers apply interceptors via the @Interceptors annotation on methods or classes, allowing modular extension without altering bean logic.[41]
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.[43] 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.[43] 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.[44]
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.[45] 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.[46] Arquillian's ShrinkWrap API builds deployable archives programmatically, facilitating repeatable tests across container implementations.[47]
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 container treats all instances interchangeably and may reinitialize them unpredictably.[41] Developers must avoid non-serializable fields in stateful beans to prevent passivation failures, closing resources in @PrePassivate callbacks.[41] 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.[41] Throwing EJBException for unrecoverable errors is recommended to trigger container cleanup without misleading clients.[48]
Deployment Configuration
Jakarta Enterprise Beans (EJBs) are typically packaged as Java Archive (JAR) files containing the bean class files, interfaces, and optional supporting classes, which can be deployed standalone or embedded within Enterprise Archive (EAR) files alongside other modules such as web application archives (WARs).[49] Within an EAR, the EJB JAR resides in the root directory, while in a WAR, EJB classes may be placed in theWEB-INF/classes directory or bundled in a JAR under WEB-INF/lib.[49] The optional ejb-jar.xml deployment descriptor, located in the META-INF directory of the JAR or WEB-INF of the WAR, allows for overrides of annotation-based metadata, such as transaction attributes or security roles, ensuring portability across containers.[6]
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.[6] 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.[6] 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.[6] 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>
ejb-jar.xml using the <env-entry> element within the <session> or <message-driven> sections, allowing the deployer to customize bean behavior without code changes.[50] 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>
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.[50][6]
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.[6] These extensions allow advanced features like custom resource adapters but must not conflict with standard metadata.[34]
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 resource factories; second, the beans are installed into the operational environment.[6] 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 WildFly or Payara support hot deployment for iterative development without full restarts.[51]
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.[52] 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.[53] Commercial and open-source alternatives offer robust EJB container implementations with varying emphases on enterprise scalability. Red Hat's WildFly, the community edition of JBoss Enterprise Application Platform (EAP), provides a full-featured EJB container with support for stateless and stateful session beans, including advanced transaction management and security integration.[54] IBM WebSphere Application Server, particularly its Liberty profile, delivers enterprise-grade EJB support compliant with Jakarta EE 11, focusing on lightweight runtime for hybrid cloud environments while maintaining compatibility with legacy EJB 3.x applications.[55] For lighter deployments, Apache TomEE extends Apache Tomcat with EJB capabilities, supporting the EJB Lite subset alongside full Jakarta EE Web Profile features in a minimal footprint suitable for microservices.[56] Implementations differ in key extensions beyond the core specification to address performance and reliability. WildFly excels in high-availability (HA) clustering, where stateful EJBs can replicate session state across nodes using Infinispan for failover, ensuring minimal downtime in distributed setups.[57] Performance tuning is common across containers, such as adjusting EJB pool sizes— for instance, GlassFish 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.[58] Emerging extensions like Quarkus enable native compilation of cloud-native applications using Jakarta EE subsets such as CDI and MicroProfile, offering alternatives to traditional EJB with GraalVM support for faster startup and lower memory usage.[59] 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.[60] 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.[5] Recent trends in EJB containers reflect a shift toward cloud-native architectures, with integrations for Kubernetes orchestration—such as WildFly's Helm charts and WebSphere Liberty's operator support—facilitating auto-scaling and resilient deployments.[57] Additionally, reduced footprints via MicroProfile compatibility, as seen in TomEE and Quarkus extensions, align EJB usage with serverless and edge computing, prioritizing low resource consumption over full-stack Jakarta EE.[61]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.[62] 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:
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);
}
@Stateless annotation to declare its type, implementing the local 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:
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;
}
}
@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:
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);
}
}
ejb-jar.xml deployment descriptor, which provides explicit configuration for the EJB container. This XML approach is optional in Jakarta EE but useful for overriding annotations or in environments requiring descriptor-based setup. A minimal snippet for the stateless calculator bean is:
<?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>
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 annotation instructs the container to handle pooling and passivation, ensuring scalability 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).[62][63][1]
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 Jakarta EE tutorial'ssimplemessage application, which demonstrates queue-based message consumption.[65]
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.
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());
}
}
}
onMessage method extracts the text payload and logs it, with exception handling to manage processing errors. The configuration links the bean to the JNDI name jms/MyQueue and specifies a queue destination type, enabling the container to route messages accordingly.[65]
For setup, the application server 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 bean, produces messages to trigger the MDB. In the simplemessage example, the SimpleMessageClient sends three text messages to the queue using resource injection.
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);
}
}
}
}
ejb-jar.xml deployment descriptor provides an equivalent XML-based binding for the destination, useful for overriding or legacy setups. For instance:
<?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>
onMessage execution commits the transaction, acknowledging and removing the message from the queue; runtime exceptions trigger a rollback, redelivering the message after a configurable delay to ensure reliability.[1]
This MDB pattern promotes decoupling by allowing producers to send messages without waiting for processing, enhancing system scalability and fault tolerance through asynchronous messaging and automatic error recovery via rollbacks.[66]
