Distributed Objects   «Prev  Next»

Lesson 4 Jakarta EE 11 Container Services for Managed Components
Objective Describe the container services provided to managed components in Jakarta EE 11.

Jakarta EE 11 Container Services for Managed Components

A managed component in Jakarta EE is not just an ordinary Java object that the application creates with the new operator and then leaves alone. It runs inside a container, and that container supplies a set of services that support the component throughout its useful life. Older Enterprise JavaBeans lessons usually described these services as services of the EJB container and server. That historical description is still useful, but the modern Jakarta EE 11 model is broader.

In Jakarta EE 11, container services are provided across the Jakarta EE runtime, the CDI container, the web container, the Jakarta Enterprise Beans container where that technology is used, and related platform services such as Jakarta Transactions, Jakarta Security, Jakarta Persistence, Jakarta Messaging, Jakarta Concurrency, Jakarta Interceptors, and Jakarta Bean Validation. The main idea remains the same: the application developer writes business logic, while the runtime supplies common infrastructure services in a consistent and portable way.

The legacy service list included factory, lifecycle, state management, security, naming, and transactions. In a modern Jakarta EE application, those same ideas map to dependency injection, component scopes, lifecycle callbacks, persistence-backed state, resource injection, authorization, transaction boundaries, validation, interceptors, messaging, and managed concurrency.


From EJB Container Services to Jakarta EE Container Services

The original EJB architecture emphasized the container as the intermediary between a client and an enterprise bean. The client did not usually work directly with a raw bean instance. Instead, the container controlled creation, lifecycle, access checks, transactions, and communication. This model was designed to make enterprise applications more reliable by moving infrastructure concerns out of business methods.

Jakarta EE 11 keeps the container-centered idea, but the programming model has changed. CDI managed beans are now the default model for many ordinary application services. Jakarta Enterprise Beans still exist for specialized use cases, especially where an application needs features such as declarative transactions, timers, asynchronous methods, message-driven beans, pooling, or container-managed concurrency. REST resources, servlets, persistence services, and messaging endpoints may also participate in the same platform-level container model.

The practical result is that “container services” should not be understood as EJB-only services. They are Jakarta EE platform services applied to managed components through annotations, injection, configuration, deployment metadata, and runtime integration.

Dependency Injection Instead of the Old Bean Factory Model

The legacy lesson used the term bean factory. In older EJB designs, a client might use JNDI to locate a home object or factory-like entry point and then request access to a bean. That model was closely associated with remote EJB, stubs, home interfaces, and distributed-object middleware.

Modern Jakarta EE applications usually use CDI dependency injection instead. A component declares what it needs, and the container supplies the dependency. This produces code that is easier to read, test, and maintain because the component does not manually search for its collaborators.

@jakarta.enterprise.context.ApplicationScoped
public class CustomerService {
    public Customer findCustomer(long id) {
        // business logic
        return null;
    }
}

@jakarta.ws.rs.Path("/customers")
public class CustomerResource {
    @jakarta.inject.Inject
    CustomerService customerService;
}

In this example, the REST resource does not create the service class directly and does not locate a remote stub. The container creates and manages the service, resolves the injection point, and makes the service available to the resource. CDI also supports producers, qualifiers, alternatives, decorators, interceptors, and scopes. Those features are the modern replacement for much of the old factory-oriented thinking.


Lifecycle and Scopes

Lifecycle management means that the container decides when a managed component is created, initialized, reused, made available for injection, and destroyed. The developer writes lifecycle-aware code, but the runtime controls the lifecycle events.

CDI expresses lifecycle through scopes. A @RequestScoped bean lives for one request. A @SessionScoped bean can hold state across a user session. An @ApplicationScoped bean is shared across the application. A @Dependent bean has a lifecycle dependent on the object into which it is injected. These scopes allow the developer to match component lifetime to the kind of state or service being modeled.

Jakarta Enterprise Beans also have lifecycle rules. Stateless session beans may be pooled and reused. Stateful session beans can hold conversational state for a client. Singleton beans provide one shared instance per application. Message-driven beans receive and process messages from a messaging destination. Lifecycle callbacks such as @PostConstruct and @PreDestroy allow initialization and cleanup code to run at well-defined points.

@jakarta.annotation.PostConstruct
public void initialize() {
    // initialize resources after dependency injection is complete
}

@jakarta.annotation.PreDestroy
public void close() {
    // release resources before the component is destroyed
}

State Management

State management must be handled deliberately in modern Jakarta EE applications. The legacy EJB explanation said that most beans have state and that the container maintains the bean instance state. That was partly true for certain EJB types, but it is too broad for Jakarta EE 11.

Modern applications distinguish several kinds of state. Request state exists for a single HTTP request. Session state belongs to a user session. Application state is shared by the application. Persistence-backed state is stored in a database and managed through Jakarta Persistence. Conversational state may be modeled with a stateful session bean where that style is appropriate. Message-processing state may belong to a queue, topic, or durable event stream.

In most modern designs, durable business state should be explicit and recoverable. It is commonly stored in a database, cache, session store, token, or message broker rather than being hidden inside a remote object. Entity beans are legacy technology. Jakarta Persistence entities are the modern model for mapping domain objects to relational database records.

Security Services

The legacy lesson correctly stated that the container can verify whether a request is valid. In Jakarta EE 11, this idea is expressed through authentication, authorization, role checks, endpoint security, and identity propagation. Jakarta Security provides a standard security model, while the surrounding runtime integrates security with web endpoints, enterprise components, and application resources.

Security may be applied at several levels. A web application can require authentication before a user accesses a protected URL. A REST endpoint can require a role. A method can require authorization before it executes. The application server may integrate with an external identity provider, directory, realm, or token-based authentication mechanism.

The key point is that security is no longer described as a vendor-specific check attached to every EJB message. It is a platform service. The developer declares security requirements, and the runtime enforces them at the boundary and component level.


Naming, Lookup, and Resource Injection

JNDI still exists in enterprise Java, but the old explanation that a client must look up a bean in JNDI and download a stub is no longer the ordinary model for modern Jakarta EE applications. That statement reflects legacy remote EJB and RMI-style thinking.

In Jakarta EE 11, application code usually obtains collaborators and resources through injection and configuration. A CDI bean may be injected with @Inject. A data source may be exposed by the runtime and injected or looked up as a configured resource. Messaging resources, environment entries, executor services, and persistence contexts can also be integrated through container-managed configuration.

@jakarta.annotation.Resource
javax.sql.DataSource dataSource;

External clients also do not normally access application behavior by downloading a stub. They commonly use explicit service boundaries such as Jakarta RESTful Web Services, JSON payloads, messaging destinations, or WebSocket endpoints. Remote Jakarta Enterprise Bean interfaces remain available for specialized cases, but they are not the default access model for every component.

Transactions

Transaction management is one of the most important container services. A transaction defines a unit of work that should either complete successfully or roll back as a unit. The original lesson described the container intercepting method calls, checking whether a transaction is required, starting a transaction, and propagating it to databases and other transactional resources. That remains the correct conceptual model for declarative transaction management, but the modern name is Jakarta Transactions.

In a Jakarta EE application, transaction boundaries may be applied declaratively. The runtime can begin, commit, or roll back transactions around a business method. Jakarta Persistence can participate in that transaction through a persistence context. This allows database changes to be coordinated with business operations without requiring every method to manually open, commit, and roll back database connections.

Most applications should prefer clear local transaction boundaries. Distributed transactions are still possible in enterprise systems, but they should be treated as specialized infrastructure because they introduce operational and performance complexity.


Interceptors, Validation, Messaging, and Concurrency

Modern Jakarta EE container services extend beyond the original list of factory, lifecycle, state, security, naming, and transactions. Jakarta Interceptors allow cross-cutting behavior to be applied around method calls. This is useful for transaction handling, auditing, logging, metrics, security checks, or other concerns that should not be mixed directly into core business logic.

Jakarta Bean Validation supports declarative validation of objects, method parameters, and application data. Jakarta Messaging supports asynchronous communication through queues and topics. Jakarta Concurrency provides managed executor services so background work can run under container control instead of unmanaged application-created threads.

Jakarta RESTful Web Services, JSON-B, and JSON-P provide modern service boundaries and serialization support. These technologies are often the public face of a Jakarta EE application, while CDI managed beans, persistence services, transactions, security, and messaging form the internal service layer.


Mapping Legacy EJB Services to Jakarta EE 11

Legacy EJB container service Jakarta EE 11 interpretation
Bean factory CDI dependency injection, producers, resource injection, and container-created components
Lifecycle CDI scopes, Enterprise Beans lifecycle, lifecycle callbacks, and runtime-managed component lifecycle
State management CDI scopes, stateful session beans where needed, HTTP session state, persistence-backed state, and caches
Security checks Jakarta Security, authentication, authorization, role checks, endpoint security, and method-level protection
Naming service and JNDI stub lookup Resource injection, JNDI where needed, configured data sources, messaging resources, and explicit service endpoints
Transactions Jakarta Transactions, declarative transaction boundaries, rollback behavior, and persistence transaction integration
Container interception Jakarta Interceptors, transaction interceptors, security interceptors, validation, and cross-cutting behavior
Persistence support Jakarta Persistence entities, persistence contexts, repositories, and data access services
Asynchronous integration Jakarta Messaging, message-driven beans, events, queues, topics, and managed executors
Concurrency Jakarta Concurrency and container-managed concurrency for supported enterprise components

When Jakarta Enterprise Beans Still Matter

CDI managed beans are the modern default for many application services, but Jakarta Enterprise Beans still have a place. They are useful when an application needs standardized enterprise services such as stateless business components, stateful conversational components, singleton services, timers, asynchronous methods, message-driven beans, or container-managed concurrency.

The important design choice is not whether one technology is “old” and the other is “new.” The important question is which component model matches the service being built. Use CDI for ordinary application services and dependency injection. Use Jakarta Enterprise Beans where their container-managed enterprise services provide a clear benefit.

Learning Objectives

After completing this lesson, you should be able to:

  1. Describe the purpose of Jakarta EE container services.
  2. Explain why managed components are not ordinary unmanaged Java objects.
  3. Map legacy EJB container services to Jakarta EE 11 services.
  4. Explain how CDI dependency injection replaces much of the old bean-factory lookup model.
  5. Describe how the container manages lifecycle and scope.
  6. Distinguish request, session, application, persistence-backed, and conversational state.
  7. Explain how Jakarta Security supports authentication and authorization.
  8. Explain how resource injection and JNDI relate in modern Jakarta EE.
  9. Describe transaction boundaries using Jakarta Transactions.
  10. Identify additional modern services such as interceptors, validation, persistence, messaging, and concurrency.
  11. Explain when Jakarta Enterprise Beans-specific services are still useful.
  12. Explain why CDI managed beans are usually the default for ordinary application services.

Summary

The older EJB container model introduced an important enterprise programming idea: application components should be managed by a runtime that provides infrastructure services. Jakarta EE 11 preserves that idea while modernizing the programming model. The container still supplies lifecycle management, security, transactions, naming, state-related support, and resource access, but those services now apply across CDI managed beans, Jakarta Enterprise Beans, REST resources, persistence services, messaging components, and other managed application classes.

The modern lesson is that Jakarta EE container services allow enterprise Java applications to separate business logic from infrastructure. Dependency injection replaces much of the old factory and lookup model. CDI scopes and lifecycle callbacks replace much of the old lifecycle vocabulary. Jakarta Persistence replaces entity beans. Jakarta Transactions, Jakarta Security, Jakarta Messaging, Jakarta Concurrency, Jakarta Interceptors, and Jakarta Bean Validation provide standardized services that make enterprise applications more consistent and maintainable.

Container Services - Quiz

Click the Quiz link below to test your understanding of Jakarta EE container services.
Container Services - Quiz
In the next lesson, session-oriented enterprise components will be discussed.


SEMrush Software