What is an EJB, and what does it do?
Why really use them? (Why not just stick to POJO?)
IF you need a component that accesses the database, or accesses other connectivity/ directory resources, or is accessed from multiple clients, or is intended as a SOA service, EJBs today are usually "bigger, stronger, faster (or at least more scalable) and simpler" than POJOs. They are most valuable for servicing large numbers of users over the web or corporate network and somewhat less valuable for small apps within a department.
Reusing/Sharing Logic across multiple applications/clients with Loose Coupling.
EJBs can be packaged in their own jars, deployed, and invoked from lots of places. They are common components. True, POJOs can be (carefully!) designed as libraries and packaged as jars. But EJBs support both local and remote network access - including via local java interface, transparent RMI, JMS async message and SOAP/REST web service, saving from cut-and-paste jar dependencies with multiple (inconsistent?) deployments.
They are very useful for creating SOA services. When used for local access they are POJOs (with free container services added). The act of designing a separate EJB layer promotes extra care for maximizing encapsulation, loose coupling and cohesion, and promotes a clean interface (Facade), shielding callers from complex processing & data models.Scalability and Reliability If you apply a massive number of requests from various calling messages/processes /threads, they are distributed across the available EJB instances in the pool first and then queued. This means that if the number of incoming requests per second is greater than the server can handle, we degrade gracefully - there are always some requests being processed efficiently and the excess requests are made to wait. We don't reach server "meltdown" - where ALL requests experience terrible response time simultaneously, plus the server tries to access more resources than the hardware & OS can handle & hence crashes. EJBs can be deployed on separate tier that can be clustered - this gives reliability via failover from one server to another, plus hardware can be added to scale linearly.
Concurrency Management. The container ensures that EJB instances are automatically accessed safely (serially) by multiple clients. The container manages the EJB pool, the thread pool, the invocation queue, and automatically carries out method-level write locking (default) or read locking (through @Lock(READ)). This protects data from corruption through concurrent write-write clashes, and helps data to be read consistently by preventing read-write clashes.
This is mainly useful for @Singleton session beans, where the bean is manipulating and sharing common state across client callers. This can be easily over-ridden to manually configure or programmatically control advanced scenarios for concurrent code execution and data access.Automated transaction handling.
Do nothing at all and all your EJB methods are run in a JTA transaction. If you access a database using JPA or JDBC it is automatically enlisted in the transaction. Same for JMS and JCA invocations. Specify @TransactionAttribute(someTransactionMode) before a method to specify if/how that particular method partakes in the JTA transaction, overriding default mode: "Required".Very simple resource/dependency access via injection.
The container will lookup resources and set resource references as instance fields in the EJB: such as JNDI stored JDBC connections, JMS connections/topics/queues, other EJBs, JTA Transactions, JPA entity manager persistence contexts, JPA entity manager factory persistence units, and JCA adaptor resources. e.g. to setup a reference to another EJB & a JTA Transaction & a JPA entity Manager & a JMS connection factory and queue:@Stateless public class MyAccountsBean { @EJB SomeOtherBeanClass someOtherBean; @Resource UserTransaction jtaTx; @PersistenceContext(unitName="AccountsPU") EntityManager em; @Resource QueueConnectionFactory accountsJMSfactory; @Resource Queue accountPaymentDestinationQueue; public List<Account> processAccounts(DepartmentId id) { // Use all of above instance variables with no additional setup. // They automatically partake in a (server coordinated) JTA transaction } }
A Servlet can call this bean locally, by simply declaring an instance variable:
@EJB MyAccountsBean accountsBean;
and then just calling its' methods as desired.
Smart interaction with JPA. By default, the EntityManager injected as above uses a transaction-scoped persistence context. This is perfect for stateless session beans. When a (stateless) EJB method is called, a new persistence context is created within the new transaction, all entity object instances retrieved/written to the DB are visible only within that method call and are isolated from other methods. But if other stateless EJBs are called by the method, the container propagates and shares the same PC to them, so same entities are automatically shared in a consistent way through the PC in the same transaction.
If a @Stateful session bean is declared, equal smart affinity with JPA is achieved by declaring the entityManager to be an extended scope one: @PersistentContent(unitName="AccountsPU, type=EXTENDED). This exists for the life of the bean session, across multiple bean calls and transactions, caching in-memory copies of DB entities previously retrieved/written so they do not need to be re-retrieved.Life-Cycle Management. The lifecycle of EJBs is container managed. As required, it creates EJB instances, clears and initializes stateful session bean state, passivates & activates, and calls lifecycle callback methods, so EJB code can participate in lifecycle operations to acquire and release resources, or perform other initialization and shutdown behavior. It also captures all exceptions, logs them, rolls back transactions as required, and throws new EJB exceptions or @ApplicationExceptions as required.
Security Management. Role-based access control to EJBs can be configured via a simple annotation or XML setting. The server automatically passes the authenticated user details along with each call as security context (the calling principal and role). It ensures that all RBAC rules are automatically enforced so that methods cannot be illegally called by the wrong role. It allows EJBs to easily access user/role details for extra programmatic checking. It allows plugging in extra security processing (or even IAM tools) to the container in a standard way.
Standardization & Portability. EJB implementations conform to Java EE standards and coding conventions, promoting quality and ease of understanding and maintenance. It also promotes portability of code to new vendor app servers, by ensuring they all support the same standard features and behaviors, and by discouraging developers from accidentally adopting proprietary
non-portable vendor features.The Real Kicker: Simplicity. All of the above can be done with very streamlined code - either using default settings for EJBs within Java EE 6, or adding a few annotations. Coding enterprise/industrial strength features in your own POJOs would be way more volumous, complex and error-prone. Once you start coding with EJBs, they are rather easy to develop and give a great set of "free ride" benefits.
In the original EJB spec of 10 years ago, EJBs were a major productivity hassle. They were bloated, needed lots of code and configuration artifacts and provided about 2/3 of the benefits above. Most web projects did not actually use them. But this has changed significantly with 10 years of tweaking, overhauling, functional enhancement and development stream-lining. In Java EE 6 they provide maximum level industrial strength and simplicity of use.
What's not to like?? :-) :-)
Hope this from Oracle doc will help someone like me to understand the topic of EJB in a simple way.
What Is an Enterprise Bean? Written in the Java programming language, an enterprise bean is a server-side component that encapsulates the business logic of an application. The business logic is the code that fulfills the purpose of the application. In an inventory control application, for example, the enterprise beans might implement the business logic in methods called checkInventoryLevel and orderProduct. By invoking these methods, clients can access the inventory services provided by the application.
Benefits of Enterprise Beans For several reasons, enterprise beans simplify the development of large, distributed applications. First, because the EJB container provides system-level services to enterprise beans, the bean developer can concentrate on solving business problems. The EJB container, rather than the bean developer, is responsible for system-level services such as transaction management and security authorization.
Second, because the beans rather than the clients contain the application’s business logic, the client developer can focus on the presentation of the client. The client developer does not have to code the routines that implement business rules or access databases. As a result, the clients are thinner, a benefit that is particularly important for clients that run on small devices.
Third, because enterprise beans are portable components, the application assembler can build new applications from existing beans. These applications can run on any compliant Java EE server provided that they use the standard APIs.
When to Use Enterprise Beans You should consider using enterprise beans if your application has any of the following requirements:
The application must be scalable. To accommodate a growing number of users, you may need to distribute an application’s components across multiple machines. Not only can the enterprise beans of an application run on different machines, but also their location will remain transparent to the clients.
Transactions must ensure data integrity. Enterprise beans support transactions, the mechanisms that manage the concurrent access of shared objects.
The application will have a variety of clients. With only a few lines of code, remote clients can easily locate enterprise beans. These clients can be thin, various, and numerous.
An EJB is a Java component, containing business logic, that you deploy in a container, and that benefits from technical services provided by the container, usually in a declarative way, thanks to annotations:
- transaction management: a transaction can be started automatically before a method of the EJB is invoked, and committed or rollbacked once this method returns. This transactional context is propagated to calls to other EJBs.
- security management: a check can be made that the caller has the necessary roles to execute the method.
- dependency injection: other EJBs, or resources like a JPA entity manager, a JDBC datasource, etc. can be injected into the EJB.
- concurrency: the container makes sure that only one thread at a time invokes a method of your EJB instance.
- distribution: some EJBs can be called remotely, from another JVM.
- failover and load-balancing: remote clients of your EJBs can automatically have their call redirected to another server if necessary.
- resource management: stateful beans can automatically be passivated to disk in order to limit the memory consumption of your server.
- ... I probably have forgotten some points.
The question that interests me most is how and where can I use them. To understand this, we need first to see what types of EJBs exist. There are 2 big categories:
- Session beans
- Message driven beans
Let's consider Session Beans. They are of 3 kinds:
- Stateful - these components maintain state and are specific for a client across multiple requests. See it as a session. The immediate use these could be put to is shop carts or other type of sessions (login session and so on)
- Stateless - these are self contained components that don't persist information between requests, but they are unique to the user. Immediate use that comes to mind - Service classes in the service layer. Imagine
OrderService
. Another big use for these is to expose web services. Again, this be in the Service layer or totally separate. - Singleton - these are the beans that exist per application and are created once and can be reused / accessed multiple times. Immediately the
Configuration
component comes to mind - where you can store application level configs and access them when you need them from anywhere.
Now the rest of the capabilities or features can be used across layers in any such situations:
- Security - you can check for permissions with an annotation on the method that is called. This can happen in the Service layer as well as in Controller if you wish so.
- Transaction management - this is the obvious candidate in the Service layer or Persistence layer
- Dependency Injection - again will be used everywhere
One big use in modern times are the so called Microservices and Service Oriented Architectures. You can package some business logic components as EJBs and distribute them across the organization, to be used by multiple clients (by client here I mean other back-end applications).
And so on. Now the big drawback is that you become very dependent on the EJB container and although you could switch between 2 reference implementations, you will not be able to switch to something lighter - Tomcat for example. But why would you want to sacrifice all the benefits?