EJB 3 In Action - Overview Notes

168 阅读10分钟

Ref

Overview

  • Presentation-layer

    • JSP: JavaServer Pages
    • JSF: JavaServer Faces
    • Struts
  • JDBC: Java Database Connectivity

  • EJB services

ServiceWhat it means for you
Registry, dependency injection, and lookupHelps locate and glue together components, ideally through simple configuration. Lets you change component wiring for testing.
Lifecycle managementLets you take appropriate actions when the lifecycle of a component changes, such as when it’s created and when it’s destroyed.
Thread safetyEJB makes all components thread-safe and highly performant in ways that are completely invisible to you. This means that you can write your multithreaded server components as if you were developing a single-threaded desktop application. It doesn’t matter how complex the component is; EJB will make sure it’s thread-safe.
TransactionsEJB automatically makes all of your components transactional, which means you don’t have to write any transaction code while using databases or messaging servers via JDBC, JPA, or Java Message Service (JMS).
PoolingEJB creates a pool of component instances that are shared by clients. At any point in time, each pooled instance can only be used by a single client. As soon as an instance is done servicing a client, it’s returned to the pool for reuse instead of being frivolously discarded for the garbage collector to reclaim. You can also specify the size of the pool so that when the pool is full, any additional requests are automatically queued. This means that your system will never become unresponsive trying to handle a sudden burst of requests. Similar to instance pooling, EJB also automatically pools threads across the container for better performance.
State managementThe EJB container manages the state transparently for stateful components instead of having you write verbose and error-prone code for state management. This means that you can maintain the state in instance variables as if you were developing a desktop application. EJB takes care of all the details of session/state maintenance behind the scenes.
Memory managementEJB steps in to optimize memory by saving less frequently used stateful components into the hard disk to free up memory. This is called passivation. When memory becomes available again and a passivated component is needed, EJB puts the component back into memory. This is called activation.
MessagingEJB 3 allows you to write message processing components without having to deal with a lot of the mechanical details of the JMS API.
SecurityEJB allows you to easily secure your components through simple configuration.
SchedulingEJB lets you schedule any EJB method to be invoked automatically based on simple repeating timers or cron expressions.
Asynchronous processingYou can configure any EJB method to be invoked asynchronously if needed.
InterceptorsEJB 3 introduces AOP (aspect-oriented programming) in a lightweight, intuitive way using interceptors. This allows you to easily separate out crosscutting concerns such as logging and auditing, and to do so in a configurable way.
Web servicesEJB 3 can transparently turn business components into Simple Object Access Protocol (SOAP) or Representational State Transfer (REST) web services with minimal or no code changes.
RemotingIn EJB 3, you can make components remotely accessible without writing any code. In addition, EJB 3 enables client code to access remote components as if they were local components using dependency injection (DI).
TestingYou can easily unit- and integration-test any EJB component using embedded containers with frameworks like JUnit.
  • EJB Componment Service

image.png

  • Domain-Driven Design

image.png

Why choose EJB 3

  • Ease of Use
  • Complete, Integrated, Solution Stack
    • EJB 3 offers a complete stack of server-side solutions, including transactions, security, messaging, scheduling, remoting, web services, asynchronous processing, testing, dependency injection, and interceptors.
    • In addition, EJB 3 provides seamless integration with other Java EE technologies, such as CDI, JPA, JDBC, JavaMail, Java Transaction API (JTA), JMS, Java Authentication and Authorization Service (JAAS), Java Naming and Directory Interface (JNDI), Remote Method Invocation (RMI), and so on. EJB is also guaranteed to seamlessly integrate with presentation-tier technologies like JSP, Servlets, and JSF. When needed, you can integrate third-party tools with EJB using CDI.
  • Open Java EE standard
    • EJB 3 has an open, public API specification and compatibility test kit that organizations are encouraged to use to create a container implementation.
    • The EJB 3 standard is developed by the Java Community Process (JCP), consisting of a nonexclusive group of individuals driving the Java standard. The open standard leads to broader vendor support for EJB 3, which means you don’t have to depend on a proprietary solution.
  • Broad vendor support
  • Clustering, load balancing, and failover
  • Performance and scalability

EJB Types

  • Session Beans

    • Stateful: A stateful session bean automatically saves the bean state between invocations from a single, unique client without your having to write any additional code.
    • Stateless: Don’t maintain any state and model application services that can be completed in a single client invocation
    • Singleton: maintain the state, are shared by all clients, and live for the duration of the application. Note that singleton beans are a new feature added in EJB 3.1.
  • Message Driven Beans

    • MDBs are different in one important way: clients never invoke MDB methods directly. Instead, MDBs are triggered by messages sent to a messaging server, which enables sending asynchronous messages between system components.
    • MDBs are typically used for robust system integration and asynchronous processing.

Related specifications

  • JPA
  • CDI

Entities and the Java Persistence API

  • Entities

    • Entities are the Java objects that are persisted into the database.
    • While session beans are the “verbs” of a system, entities are the “nouns.”
    • Entities are the OO representations of the application data stored in the database.
    • Entities survive container crashes and shutdown.
    • JPA entities support a full range of relational and OO capabilities, including relationships between entities, inheritance, and polymorphism.
  • EntityManager

    • The EntityManager interface reads the ORM metadata for an entity and performs persistence operations.
    • The EntityManager knows how to add entities to the database, update stored entities, and delete and retrieve entities from the database.
  • Java Persistence Query Language

    • JPA provides a specialized SQL-like query language called Java Persistence Query Language (JPQL) to search for entities saved into the database.
    • JPA supports native, database-specific SQL

Contexts and dependency injection for Java EE

CDI is a powerful solution to the problem. It provides EJB (as well as all other APIs and components in the Java EE environment) best-of-breed, next-generation, generic dependency injection and context management services. CDI features include injection, automatic context management, scoping, qualifiers, component naming, producers, disposers, registry/lookup, stereotypes, interceptors, decorators, and events.

Unlike many older dependency injection solutions, CDI is completely type-safe, compact, futuristic, and annotation-driven.

EJB runtimes

To execute session beans and MDBs you need an EJB container. the container transparently provides EJB component services such as transactions, security management, remoting, and web services support. In EJB 3, the container provides services applicable only to session beans and MDBs.

Java EE container is an application server solution that supports EJB 3, a web container, and other Java EE APIs and services. Oracle WebLogic server, GlassFish server, IBM WebSphere application server, JBoss application server, and Caucho Resin are examples of Java EE containers.

Application servers

Application servers are Java EE containers that include support for all Java EE APIs, as well as facilities for administration, deployment, monitoring, clustering, load balancing, security, and so on.

image.png

EJB Lite

Similar to the idea of the Java EE 7 Web Profile, EJB 3.2 also comes in a scaled-down, lighter-weight version called EJB 3.2 Lite. EJB Lite goes hand-in-hand with the Web Profile and is intended for web applications.

  • EJB and EJB Lite feature comparison
FeatureEJB LiteEJB
Stateless beans
Stateful beans
Singleton beans
Message-driven beans
No interfaces
Local interfaces
Remote interfaces
Web service interfaces
Asynchronous invocation
Interceptors
Declarative security
Declarative transactions
Programmatic transactions
Timer service
EJB 2.x support
CORBA interoperability

Embedable containers

Traditional application servers run as a separate process that you deploy your applications into. Embedded EJB containers, on the other hand, can be started through a programmatic Java API inside your own application. This is very important for unit testing with JUnit as well as using EJB 3 features in command-line or Swing applications. When an embedded container starts, it scans the class path of your application and automatically deploys any EJBs it can find.

image.png

OpenEJB, EasyBeans, and Embedded JBoss are examples. Embeddable containers are only required to support EJB Lite, but most implementations are likely to support all features.

Using EJB 3 in Tomcat

Apache Tomcat, the lightweight, popular Servlet container, doesn’t support EJB 3, because unlike application servers, Servlet containers aren’t required to support EJB. But you can easily use EJB 3 on Tomcat through embedded containers. The Apache OpenEJB project has specific support for enabling EJB 3 on Tomcat.

OpenWebBeans and OpenEJB are closely related projects and work seamlessly together. In this way, you can use a majority of Java EE 7 APIs on Tomcat if you wish.

image.png

Annotations versus XML

XDoclet: which was popular in many relatively progressive EJB 2 shops. EJB 3 was the first mainstream Java technology to pave the way for annotation adoption. Since then, many other tools like JPA, JSF, Servlets, JAX-WS, JAX-RS, JUnit, Seam, Guice, and Spring have followed suit.

image.png

Unless you have a very strong preference for XML, it’s generally advisable to start with annotations and use XML overrides where they’re really needed.

Intelligent defaults versus explicit configuration

EJB takes a different approach to default behavior than most frameworks such as Spring.

In addition to making the task of configuration easier via annotations, EJB 3 reduces the total amount of configuration altogether by using sensible defaults wherever possible.

For example, the “Hello World” component is automatically thread-safe, pooled, and transactional without you having to do anything at all.

Similarly, if you want scheduling, asynchronous processing, remoting, or web services, all you need to do is add a few annotations to the component. There’s no service that you’ll need to understand, explicitly enable, or configure—everything is enabled by default. The same is true of JPA and CDI as well. Intelligent defaulting is especially important when you’re dealing with automated persistence using JPA.

Dependency injection versus JNDI lookup

EJB 3 was reengineered from the ground up for dependency injection. This means that you can inject EJBs into other Java EE components and inject Java EE components into EJBs. This is especially true when using CDI with EJB 3.

image.png

The @EJB annotation reads the type and name of the EJB and looks it up from JNDI under the hood. All EJB components are automatically registered with JNDI while being deployed. Note that you can still use JNDI lookups where they’re unavoidable.

For example, to dynamically look up your bean, you could use code like this:

Context context = new InitialContext();
HelloUserBean helloUser = (HelloUserBean)context.lookup("java:module/HelloUserBean");
helloUser.sayHello("Curious George");

CDI versus EJB injection

  • EJB-style injection predates CDI.
  • Most importantly, CDI can be used to inject almost anything.
  • EJB injection, on the other hand, can only be used with objects stored in JNDI, such as EJB, as well as some container-managed objects like the EJB context.
  • CDI is far more type-safe than EJB. Generally speaking, CDI is a superset of EJB injection.

For example, you can use CDI to inject the EJB as follows:

image.png

Although CDI can retrieve an EJB by type, it doesn’t work with remote EJBs. EJB injection (@EJB) will recognize whether an EJB is local or remote and return the appropriate type. You should use CDI for injection when possible.

Testable POJO components

  • Because all EJBs are simply POJOs, you can easily unit test them in JUnit for basic component functionality.
  • You can even use CDI to inject EJBs directly into unit tests, wire mock objects, and so on.
  • Thanks to embedded containers, you can even perform full integration testing of EJB components from JUnit.
  • Projects like Arquillian focus specifically on integrating JUnit with embedded containers.

The following listing shows how Arquillian allows you to inject EJBs into JUnit tests.

image.png

Changes in EJB 3.2

Previous EJB 2 features now optional

Support for EJB 2 has been made optional by EJB 3.2. This means a fully compliant Java EE 7 application server no longer needs to support EJB 2-style entities beans. EJB QL and JAX-RPC have also been made optional.

Enhancements to message-driven beans

In EJB 3.2, MDBs have been given a major overhaul. The update to JMS 2.0 brings a simplified API as well as integration with advances to Java in other areas such as dependency injection with CDI. It also makes using the javax.jms.MessageListener interface optional, giving you the ability to create an MDB with a no-methods listener interface, which makes public methods of the class message listener methods. Here’s a quick look at the simplified API for MDB.

  • Send a message:

image.png

  • Receive a message:

image.png

Enhancements to stateful session beans

A few enhancements have been made to stateful session beans concerning passivation and transaction support.

Disable passivation

Prior to EJB 3.2, stateful beans needed all objects in them to implement Serializable so that the EJB container could passivate a bean without error. If one object in your stateful bean wasn’t serializable, passivation would fail and the EJB container would destroy the bean, losing the state. Although it’s highly advisable to make sure your stateful beans are serializable so the EJB container can provide you with services like passivation and clustered failover, sometimes it’s not possible. To prevent the container from attempting to passivate a stateful bean you don’t want to passivate, use the passivationCapable element:

Transaction support to lifecycle callbacks

Prior to EJB 3.2, stateful session beans had lifecycle callback methods, but it was undefined how transactions were supported during these method calls. So the new API adds transactional support to the lifecycle callback methods by introducing the ability to annotate the lifecycle callback methods with @TransactionalAttribute(REQUIRES_NEW)REQUIRES_NEW is the only valid value for stateful lifecycle callback methods:

Simplifying local interfaces for stateless beans

Prior to 3.2, if interfaces weren’t marked as @Local or @Remote, then the implementing bean was forced to define them. Here’s what the pre-3.2 interface and bean looked like: image.png

Now EJB 3.2 has more intelligent defaults. By default, all interfaces that don’t specify @Local or @Remote automatically become local interfaces by the container. So you can skip line 1 and rewrite the code like this:

image.png

Enhancements in TimerService API

he TimerService API has been enhanced to expand the scope of where and how timers may be retrieved. Prior to EJB 3.2, the Timer and TimerHandler objects could only be accessed by the bean that owned the timer. This restriction has been lifted, and a new API method called getAllTimers() has been added that will return a list of all active timers in the EJB module. This allows any code to view all timers and have the ability to alter them.

Enhancements in EJBContainer API

For EJB 3.2, a couple of changes have been made to the embeddable EJBContainer API. First, the API now implements AutoCloseable so it may be used with a try-with-resources statement:

try (EJBContainer c = EJBContainer.createEJBContainer();) {
  // work with container
}

Second, the embeddable EJBContainer object is required to support the EJB Lite group of the EJB API. EJB API groups will be discussed further in the next section.

EJB API groups

EJB API groups were created for EJB 3.2. EJB API groups are well-defined subsets of the capabilities of EJBs created for specific purposes. The groups defined in the EJB 3.2 specification are these:

  • EJB Lite
  • Message-driven beans
  • EJB 3.x Remote
  • Persistent EJB timer services
  • JAX-WS Web Service endpoints
  • Embeddable EJB container (optional)
  • EJB 2.x API
  • Entity beans (optional)
  • JAX-RPC Web Service endpoints (optional)

Except for the few groups that are optional, a full EJB container is required to implement all of the groups. The most important of these is the EJB Lite group. The EJB Lite group consists of the minimum number of EJB features that’s still powerful enough to handle the majority of business transactions and security needs. This makes an EJB Lite implementation ideal to embed into a Servlet container like Tomcat to give the container some Enterprise features, or you can embed it into your Android tablet application to handle its data needs.

Summary

  • EJB 3 components are POJOs that are configurable through simplified metadata annotations.
  • Accessing EJB from client applications and unit tests has become very simple using dependency injection.
  • EJB provides a powerful, scalable, complete set of Enterprise services out-of-the-box.