ArchitectMind
  1. Home
  2. Tutorials
  3. Book 3 · Jakarta EE & Enterprise Java
  4. Volume III
  5. EJB Architecture
Book 3 · Volume III — Enterprise Business Services · Topic 1.1

EJB Architecture

Container, Enterprise beans, Container services

5 min readStage 1 · Foundations6 interview questions
On this page
  1. 1. · Concept & Definition
  2. 2. · Why It Matters
  3. 3. · How It Works
  4. 4. · Java / Jakarta EE Code Examples
  5. 5. · Configuration, Defaults & Diagnostics
  6. 6. · Production Usage Patterns
  7. 7. · Common Pitfalls & Misconceptions
  8. 8. · Best Practices
  9. 9. · Architect's Perspective & Trade-offs
  10. 10. · Interview Q&A

1· Concept & Definition

Enterprise JavaBeans is a server-side component architecture in which business components — enterprise beans — run inside an EJB container. Clients never call bean instances directly: they call a container-provided view (proxy), and the container interposes services such as transactions, security, concurrency control, instance pooling, timers and asynchronous execution before delegating to an instance.

2· Why It Matters

  • Explains the behaviour of many existing enterprise systems (transaction boundaries, exceptions, security).
  • The interposition model is the foundation of today's CDI interceptors and platform services.
  • Understanding services informs migration decisions and parity testing.

3· How It Works

Container

Container responsibilityDetail
Instance managementCreates, pools, passivates and destroys bean instances
Client viewsGenerates proxies for no-interface, local and remote views
InterpositionApplies services on every business method invocation
NamingRegisters beans in JNDI (java:global/app/module/Bean!Interface)
Resource managementInjects data sources, SessionContext, other beans
Lifecycle callbacks@PostConstruct, @PreDestroy, @PrePassivate, @PostActivate

Enterprise beans

The kinds of enterprise beans
Figure 1.1.1 — The kinds of enterprise beans
Bean typeAnnotationStateInstances
Stateless session@StatelessNone between callsPool; any instance per call
Stateful session@StatefulPer client (conversational)One per client reference
Singleton session@SingletonShared application stateExactly one per application
Message-driven@MessageDrivenNonePool; triggered by messages

Container services

Services applied on each business method call
Figure 1.1.2 — Services applied on each business method call
ServiceDeclared withDefault
Transactions@TransactionAttribute, @TransactionManagementCMT, REQUIRED
Security@RolesAllowed, @PermitAll, @DenyAll, @RunAsUnchecked (permit) unless declared
Concurrency@Lock, @ConcurrencyManagement, @AccessTimeoutSingleton: container-managed, @Lock(WRITE)
PoolingServer configurationVendor-specific pool sizes
Timers@Schedule, TimerServicePersistent automatic timers
Asynchronous@AsynchronousSynchronous
Interceptors@Interceptors, CDI bindingsNone

4· Java / Jakarta EE Code Examples

A stateless bean using transactions, security and resource injection
@Stateless                                         // stateless session bean
public class TransferService {
    @PersistenceContext EntityManager em;           // container-injected resources
    @Resource SessionContext ctx;
 
    @RolesAllowed("teller")                         // security service
    // REQUIRED tx by default
    public void transfer(long from, long to, BigDecimal amount) {
        Account a = em.find(Account.class, from, LockModeType.PESSIMISTIC_WRITE);
        Account b = em.find(Account.class, to,   LockModeType.PESSIMISTIC_WRITE);
        if (a.balance().compareTo(amount) < 0) { ctx.setRollbackOnly(); throw new
                InsufficientFunds(); }
        a.debit(amount); b.credit(amount);
    }
}
Obtaining a reference to an enterprise bean
// Clients: injection (preferred) or JNDI lookup with portable names
// CDI injection works for session beans
@Inject TransferService transfers;
@EJB    TransferService transfers2;                  // EJB injection
 
TransferService t = (TransferService) new InitialContext()
    .lookup("java:global/bank/core/TransferService!com.bank.TransferService");
Portable JNDI names logged at deployment (WildFly)
INFO  [org.jboss.as.ejb3.deployment] WFLYEJB0473: JNDI bindings for session bean named
        'TransferService':
      java:global/bank/core/TransferService!com.bank.TransferService
      java:app/core/TransferService!com.bank.TransferService
      java:module/TransferService!com.bank.TransferService

5· Configuration, Defaults & Diagnostics

ItemNote
Descriptorejb-jar.xml optional; can override annotations
PackagingEJBs in WARs (EJB 3.1+) or EJB JARs inside EARs
Portable JNDI namespacesjava:global, java:app, java:module
MonitoringServer consoles/JMX: invocation counts, pool usage, wait times

6· Production Usage Patterns

  • Stateless beans as transactional service facades in layered monoliths.
  • EJBs packaged inside WARs alongside REST resources and CDI beans.
  • Singleton beans with @Schedule for background jobs.

7· Common Pitfalls & Misconceptions

  • Calling methods internally via this — container services are bypassed.
  • Fine-grained remote EJBs — network chattiness.
  • Assuming checked exceptions roll back transactions.
  • Mixing EJB and CDI scopes without understanding lifecycles.

8· Best Practices

  • Keep beans coarse-grained service facades.
  • Inject with @Inject; avoid manual JNDI lookups.
  • Declare transaction and security metadata explicitly for clarity.
  • Monitor pool and invocation metrics.

9· Architect's Perspective & Trade-offs

CriterionEJBCDI + Jakarta specs
TransactionsBuilt-in CMT@Transactional interceptor
PoolingBuilt-inNot needed (thread-safe beans)
Remote accessRMI-IIOP / vendorREST, gRPC, messaging
TimersRich, persistentConcurrency / schedulers
Profile availabilityPlatform (full), Web (Lite)Core/Web/Platform

10· Interview Q&A

Q1Basic

What is an EJB container?

An EJB container is the part of a Jakarta EE application server that manages enterprise beans. It creates bean instances and may pool them, injects their dependencies and controls their life cycle. Most importantly, it intercepts every business method call through a proxy and applies services around it: starting or joining a transaction, checking security roles, managing concurrency and running interceptors. The developer writes a plain class with annotations such as @Stateless and @TransactionAttribute, and the container provides the infrastructure behaviour declaratively. Many of these ideas later moved into CDI and are now used well beyond EJB.

Q2Intermediate

What are the types of enterprise beans?

There are two main kinds. Session beans implement business logic called by clients. A stateless session bean keeps no conversational state between calls, so the container can pool instances and give any instance to any caller. A stateful session bean keeps state for one client across several calls, such as a multi-step checkout, and is removed or passivated when no longer needed. A singleton session bean has exactly one instance per application, useful for shared caches or start-up logic, with container-managed concurrency. Message-driven beans are the second kind: they consume messages asynchronously from a queue or topic, usually through JMS.

Q3Intermediate

How do clients obtain EJB references?

Clients obtain an EJB reference either by injection or by lookup. Injection with @EJB, or with @Inject when CDI is used, is the usual approach inside the same application. Lookup uses JNDI with portable global names in the form java:global/app/module/BeanName!fully.qualified.Interface, which is useful from code the container does not manage. In every case the client receives a container-generated proxy, not the bean instance itself. That proxy is what lets the container apply transactions, security and interceptors on every call, and it is also why a remote client can call a bean running in another server.

Q4Senior Engineer

Why do internal calls within an EJB bypass container services?

Container services such as transactions, security checks and interceptors are applied by the proxy that sits between the client and the bean. When one business method calls another method on the same bean through this, the call goes directly to the instance and never passes through the proxy. As a result, the second method's @TransactionAttribute, for example REQUIRES_NEW, its security roles and its interceptors are silently ignored. The fix is to call through the container: inject the bean's own reference with @Resource SessionContext and use getBusinessObject, inject itself, or move the method into a separate bean. Spring proxies behave the same way.

Q5Technical Architect

Which EJB concepts survived into CDI and Jakarta EE today?

Most of EJB's useful ideas were generalised so they work with any CDI bean, not just EJBs. Interceptors became a general Jakarta mechanism with @Interceptor and interceptor bindings. Declarative transactions are available through @Transactional from Jakarta Transactions. Declarative security uses @RolesAllowed and related annotations from Jakarta Security. Asynchronous methods and scheduled tasks are provided by Jakarta Concurrency, including managed executors and, in Jakarta EE 11, support for virtual threads. As a result, new Jakarta EE applications rarely need EJBs at all, while existing EJBs keep working alongside CDI beans in the same application.

Q6Solution Architect

How would you assess an EJB-heavy application for modernisation?

Start with an inventory: every bean and its type, remote interfaces and their clients, timers and schedules, transaction attributes, security annotations, message-driven beans and any pooling or concurrency settings. Map each to its modern equivalent, such as CDI beans with @Transactional, Jakarta Concurrency for asynchronous work and schedules, or REST or messaging for remote interfaces. Flag behaviours that change subtly, such as which exceptions cause rollback, the loss of instance pooling limits that used to throttle load, and stateful bean passivation. Then migrate incrementally, protected by behavioural tests around each area, and record the target architecture in an ADR.

Newsletter

Get new tutorials every week

New ArchitectMind tutorials and interview questions, once a week. No spam, unsubscribe anytime.

Almost done! Check your inbox and click the confirmation link to complete your subscription.