1. Trang chủ >
  2. Công Nghệ Thông Tin >
  3. Kỹ thuật lập trình >

What’s New in EJB 3.2?

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (15.81 MB, 597 trang )


Chapter 7 ■ Enterprise JavaBeans







Restriction to obtain the current class loader has been removed, and the use of the java.io

package is now allowed.







Allignment of JMS 2.0.







Embeddable container implements Autocloseable to fit Java SE 7.







RMI/IIOP has been pruned in this release. This means that it might be marked as optional

in Java EE 8. Remote invocation would then be done with just RMI (without the IIOP

interoperability).



Table 7-2 lists the main packages defined in EJB 3.2 today.

Table 7-2.  Main EJB Packages



Package



Description



javax.ejb



Classes and interfaces that define the contracts between the EJB and its clients and

between the EJB and the container



javax.ejb.embeddable



Classes for the embeddable API



javax.ejb.spi



Interfaces that are implemented by the EJB container



Reference Implementation

GlassFish is an open source application server project led by Oracle for the Java EE platform. Sun launched the project

in 2005 and it became the reference implementation of Java EE 5 in 2006. Today, GlassFish v4 includes the reference

implementation for EJB 3.2. Internally, the product is built around modularity (based on the Apache Felix OSGi

runtime), allowing a very fast startup time and the use of various application containers (Java EE 7, of course, but also

Ruby, PHP, etc.).

At the time of writing this book GlassFish is the only EJB 3.2 compliant implementation. But others will soon

follow: OpenEJB, JBoss, Weblogic, Websphere . . .



Writing Enterprise Java Beans

Session beans encapsulate business logic, are transactional, and rely on a container that does pooling, multithreading,

security, and so on. What artifacts do we need to create such a powerful component? One Java class and one

annotation—that’s all. Listing 7-1 shows how simple it is for a container to recognize that a class is a session bean and

apply all the enterprise services.

Listing 7-1.  A Simple Stateless EJB

@Stateless

public class BookEJB {



@PersistenceContext(unitName = "chapter07PU")

private EntityManager em;



public Book findBookById(Long id) {

return em.find(Book.class, id);

}





233

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans



public Book createBook(Book book) {

em.persist(book);

return book;

}

}



Previous versions of J2EE required developers to create several artifacts in order to create a session bean: a local

or remote interface (or both), a local home or a remote home interface (or both), and a deployment descriptor.

Java EE 5 and EJB 3.0 drastically simplified the model to the point where only one class and one or more business

interfaces are sufficient and you don’t need any XML configuration. As shown in Listing 7-1, since EJB 3.1 the class

doesn’t even have to implement any interface. We use only one annotation to turn a Java class into a transactional

and secure component: @Stateless. Then, using the entity manager (as seen in the previous chapters), the BookEJB

creates and retrieves books from the database in a simple yet powerful manner.



Anatomy of an EJB

Listing 7-1 shows the easiest programming model for session beans: an annotated POJO with no interface. But,

depending on your needs, session beans can give you a much richer model, allowing you to perform remote calls,

dependency injection, or asynchronous calls. An EJB is made of the following elements:





A bean class: The bean class contains the business method implementation and can

implement zero or several business interfaces. The session bean must be annotated with

@Stateless, @Stateful, or @Singleton depending on its type.







Business interfaces: These interfaces contain the declaration of business methods that are

visible to the client and implemented by the bean class. A session bean can have local

interfaces, remote interfaces, or no interface at all (a no-interface view with local access only).



As shown in Figure 7-2, a client application can access a session bean by one of its interfaces (local or remote) or

directly by invoking the bean class itself.



Figure 7-2.  Bean class has several types of business interfaces



Bean Class

A session bean class is any standard Java class that implements business logic. The requirements to develop a session

bean class are as follows:





The class must be annotated with @Stateless, @Stateful, @Singleton, or the XML equivalent

in a deployment descriptor.







It must implement the methods of its interfaces, if any.



234

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans







The class must be defined as public, and must not be final or abstract.







The class must have a public no-arg constructor that the container will use to create instances.







The class must not define the finalize() method.







Business method names must not start with ejb, and they cannot be final or static.







The argument and return value of a remote method must be legal RMI types.



Remote, Local, and No-Interface Views

Depending from where a client invokes a session bean, the bean class will have to implement remote or local

interfaces, or no interface at all. If your architecture has clients residing outside the EJB container’s JVM instance,

they must use a remote interface. As shown in Figure 7-3, this applies for clients running in a separate JVM

(e.g., a rich client), in an application client container (ACC), or in an external web or EJB container. In this case, clients

will have to invoke session bean methods through Remote Method Invocation (RMI). You can use local invocation

when the bean and the client are running in the same JVM. That can be an EJB invoking another EJB or a web

component (Servlet, JSF) running in a web container in the same JVM. It is also possible for your application to use

both remote and local calls on the same session bean.



Figure 7-3.  Session beans invoked by several types of client

A session bean can implement several interfaces or none. A business interface is a standard Java interface that

does not extend any EJB-specific interfaces. Like any Java interface, business interfaces define a list of methods that

will be available for the client application. They can use the following annotations:





@Remote: Denotes a remote business interface. Method parameters are passed by value and

need to be serializable as part of the RMI protocol.







@Local: Denotes a local business interface. Method parameters are passed by reference from

the client to the bean.



You cannot mark the same interface with more than one annotation. The session beans that you have seen so far

in this chapter have no interface. The no-interface view is a variation of the local view that exposes all public business

methods of the bean class locally without the use of a separate business interface.



235

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans



Listing 7-2 shows a local interface (ItemLocal) and a remote interface (ItemRemote) implemented by the ItemEJB

stateless session bean. With this code, clients will be able to invoke the findCDs() method locally or remotely as it is

defined in both interfaces. The createCd() will only be accessible remotely through RMI.

Listing 7-2.  Stateless Session Bean Implementing a Remote and Local Interface

@Local

public interface ItemLocal {

List findBooks();

List findCDs();

}



@Remote

public interface ItemRemote {

List findBooks();

List findCDs();

Book createBook(Book book);

CD createCD(CD cd);

}



@Stateless

public class ItemEJB implements ItemLocal, ItemRemote {

// ...

}



Alternatively to the code in Listing 7-2, you might specify the interface in the bean’s class. In this case, you would

have to include the name of the interface in the @Local and @Remote annotations as shown in Listing 7-3. This is

handy when you have legacy interfaces where you can’t add annotations and need to use them in your session bean.

Listing 7-3.  A Bean Class Defining a Remote, Local and No Interface

public interface ItemLocal {

List findBooks();

List findCDs();

}



public interface ItemRemote {

List findBooks();

List findCDs();

Book createBook(Book book);

CD createCD(CD cd);

}



@Stateless

@Remote(ItemRemote.class)

@Local(ItemLocal.class)

@LocalBean

public class ItemEJB implements ItemLocal, ItemRemote {

// ...

}





236

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans



If the bean exposes at least one interface (local or remote) it automatically loses the no-interface view. It then

needs to explicitly specify that it exposes a no-interface view by using the @LocalBean annotation on the bean class.

As you can see in Listing 7-3 the ItemEJB now has a local, remote, and no interface.



Web Services Interface

In addition to remote invocation through RMI, stateless beans can also be invoked remotely as SOAP web services

or RESTful web services. Chapters 14 and 15 are dedicated to web services, so I won’t describe them here. I just want

to show you how a stateless session bean can be accessed in various forms just by implementing different annotated

interfaces. Listing 7-4 shows a stateless bean with a local interface, a SOAP web services endpoint (@WebService), and

a RESTful web service endpoint (@Path). Note that these annotations come, respectively, from JAX-WS (Chapter 14)

and JAX-RS (Chapter 15) and are not part of EJB.

Listing 7-4.  A Stateless Session Bean Implementing Several Interfaces

@Local

public interface ItemLocal {

List findBooks();

List findCDs();

}



@WebService

public interface ItemSOAP {

List findBooks();

List findCDs();

Book createBook(Book book);

CD createCD(CD cd);

}



@Path(/items)

public interface ItemRest {

List findBooks();

}



@Stateless

public class ItemEJB implements ItemLocal, ItemSOAP, ItemRest {

// ...

} 



Portable JNDI Name

JNDI has been around for a long time. Its API is specified and is portable across application servers. But this wasn’t

the case with the JNDI name, which was implementation specific. When an EJB in GlassFish or JBoss was deployed,

the name of the EJB in the directory service was different and thus not portable. A client would have to look up an

EJB using one name for GlassFish, and another name for JBoss. Since EJB 3.1, JNDI names have been specified so the

code could be portable. So now each time a session bean with its interfaces is deployed to the container, each bean/

interface is automatically bound to a portable JNDI name. The Java EE specification defines portable JNDI names with

the following syntax:



java:[/]//[!]





237

www.it-ebooks.info



Chapter 7 ■ enterprise JavaBeans



Each portion of the JNDI name has the following meaning:





defines a series of standard namespaces that map to the various scopes of a Java EE

application:





global: The java:global prefix allows a component executing outside a Java EE

application to access a global namespace.







app: The java:app prefix allows a component executing within a Java EE application to

access an application-specific namespace.







module: The java:module prefix allows a component executing within a Java EE

application to access a module-specific namespace.







comp: The java:comp prefix is a private component-specific namespace and is not

accessible by other components.







is only required if the session bean is packaged within an ear or war file. If this is

the case, the defaults to the name of the ear or war file (without the .ear or .war

file extension).







is the name of the module in which the session bean is packaged. It can be an

EJB module in a stand-alone jar file or a web module in a war file. The defaults

to the base name of the archive with no file extension.







is the name of the session bean.







is the fully qualified name of each defined business

interface. For the no-interface view, the name can be the fully qualified bean class name.



To illustrate this naming convention, let’s take the example of an ItemEJB (defined in Listing 7-5), which has

a remote interface, a local interface, and a no-interface view (using the @LocalBean annotation). All these classes and

interfaces belong to the org.agoncal.book.javaee7 package. ItemEJB is the and is packaged in the

cdbookstore.jar (the ).

Listing 7-5. A Stateless Session Bean Implementing Several Interfaces

package org.agoncal.book.javaee7;

@Stateless

@Remote(ItemRemote.class)

@Local(ItemLocal.class)

@LocalBean

public class ItemEJB implements ItemLocal, ItemRemote {

// ...

}

Once deployed, the container will create three JNDI names so an external component will be able to access the

ItemEJB using the following global JNDI names:

java:global/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemRemote

java:global/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemLocal

java:global/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemEJB



238

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans



Note that, if the ItemEJB was deployed within an ear file (e.g., myapplication.ear), you would have to use the

as follow:



java:global/myapplication/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemRemote

java:global/myapplication/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemLocal

java:global/myapplication/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemEJB



The container is also required to make JNDI names available through the java:app and java:module

namespaces. So a component deployed in the same application as the ItemEJB will be able to look it up using the

following JNDI names:



java:app/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemRemote

java:app/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemLocal

java:app/cdbookstore/ItemEJB!org.agoncal.book.javaee7.ItemEJB

java:module/ItemEJB!org.agoncal.book.javaee7.ItemRemote

java:module/ItemEJB!org.agoncal.book.javaee7.ItemLocal

java:module/ItemEJB!org.agoncal.book.javaee7.ItemEJB



This portable JNDI name can be applied to all session beans: stateless, stateful, and singleton.



Stateless Beans

In Java EE applications, stateless beans are the most popular session bean components. They are simple, powerful,

and efficient and respond to the common task of doing stateless business processing. What does stateless mean? It

means that a task has to be completed in a single method call.

As an example, we can go back to the roots of object-oriented programming where an object encapsulates its

state and behavior. In object modeling, to persist a book to a database, you would do something like this: create an

instance of a Book object (using the new keyword), set some values, and call a method so it could persist itself to a

database (book.persistToDatabase()). In the following code, you can see that, from the very first line to the last one,

the book object is called several times and keeps its state:



Book book = new Book();

book.setTitle("The Hitchhiker's Guide to the Galaxy");

book.setPrice(12.5F);

book.setDescription("Science fiction comedy series created by Douglas Adams.");

book.setIsbn("1-84023-742-2");

book.setNbOfPage(354);

book.persistToDatabase();



In a service architecture, you would delegate the business logic to an external service. Stateless services are

ideal when you need to implement a task that can be concluded with a single method call (passing all the needed

parameters). Stateless services are independent, are self-contained, and do not require information or state from

one request to another. So, if you take the preceding code and introduce a stateless service, you need to create a Book

object, set some values, and then use a stateless service to invoke a method that will persist the book on its behalf,

in a single call. The state is maintained by Book but not by the stateless service:



Book book = new Book();

book.setTitle("The Hitchhiker's Guide to the Galaxy");

book.setPrice(12.5F);

book.setDescription("Science fiction comedy series created by Douglas Adams.");



239

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans



book.setIsbn("1-84023-742-2");

book.setNbOfPage(354);

statelessService.persistToDatabase(book);



Stateless session beans follow the stateless service architecture and are the most efficient component model

because they can be pooled and shared by several clients. This means that, for each stateless EJB, the container keeps

a certain number of instances in memory (i.e., a pool) and shares them between clients. Because stateless beans have

no client state, all instances are equivalent. When a client invokes a method on a stateless bean, the container picks up

an instance from the pool and assigns it to the client. When the client request finishes, the instance returns to the pool

to be reused. This means you need only a small number of beans to handle several clients, as shown in Figure 7-4.

The container doesn’t guarantee the same instance for the same client.



Figure 7-4.  Clients accessing stateless beans in a pool

Listing 7-5 shows what a stateless EJB could look like: a standard Java class with just a single @Stateless

annotation. Because it lives in a container, it can use any container-managed service, one of which is dependency

injection. We use the @PersistenceContext annotation to inject a reference of an entity manager. For stateless session

beans, the persistence context is transactional, which means that any method invoked in this EJB (createBook(),

createCD(), etc.) is transactional. Chapter 9 explains this process in more detail. Notice that all methods have the

needed parameters to process business logic in one single call. For example, the createBook() method takes a Book

as a parameter and persists it without relying on any other state.

Listing 7-5.  Stateless Session Bean ItemEJB

@Stateless

public class ItemEJB {



@PersistenceContext(unitName = "chapter07PU")

private EntityManager em;



public List findBooks() {

TypedQuery query = em.createNamedQuery(Book.FIND_ALL, Book.class);

return query.getResultList();

}





240

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans



public List findCDs() {

TypedQuery query = em.createNamedQuery(CD.FIND_ALL, CD.class);

return query.getResultList();

}



public Book createBook(Book book) {

em.persist(book);

return book;

}



public CD createCD(CD cd) {

em.persist(cd);

return cd;

}

}



Stateless session beans often contain several closely related business methods. For example, the ItemEJB bean in

Listing 7-5 defines methods related to items sold by the CD-BookStore application. So you will find methods to create,

update, or find books and CDs, as well as other related business logic.

The @Stateless annotation marks the ItemEJB POJO as a stateless session bean, thus turning a simple Java class

into a container-aware component. Listing 7-6 describes the specification of the @javax.ejb.Stateless annotation.

Listing 7-6.  @Stateless Annotation API

@Target({TYPE}) @Retention(RUNTIME)

public @interface Stateless {

String name() default "";

String mappedName() default "";

String description() default "";

}



The name parameter specifies the name of the bean and by default is the name of the class (ItemEJB in the

example in Listing 7-5). This parameter can be used to look up an EJB with JNDI, for example. The description

parameter is a String that can be used to describe the EJB. The mappedName attribute is the global JNDI name assigned

by the container. Note that this JNDI name is vendor specific and is therefore not portable. mappedName has no

relationship with the portable global JNDI name, which I described earlier.

Stateless session beans can support a large number of clients, minimizing any needed resources. Having stateless

applications is one way to improve scalability (as the container doesn’t have to store and manage state).



Stateful Beans

Stateless beans provide business methods to their clients but don’t maintain a conversational state with them. Stateful

session beans, on the other hand, preserve conversational state. They are useful for tasks that have to be done in

several steps, each of which relies on the state maintained in a previous step. Let’s take the example of a shopping

cart in an e-commerce web site. A customer logs on (her session starts), chooses a first book, adds it to her shopping cart,

chooses a second book, and adds it to her cart. At the end, the customer checks out the books, pays for them, and logs out



241

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans



(the session ends). The shopping cart keeps the state of how many books the customer has chosen throughout the

interaction (which can take some time, specifically the time of the client’s session). This interaction with a stateful

component could be written as follows:



Book book = new Book();

book.setTitle("The Hitchhiker's Guide to the Galaxy");

book.setPrice(12.5F);

book.setDescription("Science fiction comedy series created by Douglas Adams.");

book.setIsbn("1-84023-742-2");

book.setNbOfPage(354);

statefulComponent.addBookToShoppingCart(book);

book.setTitle("The Robots of Dawn");

book.setPrice(18.25F);

book.setDescription("Isaac Asimov's Robot Series");

book.setIsbn("0-553-29949-2");

book.setNbOfPage(276);

statefulComponent.addBookToShoppingCart(book);

statefulComponent.checkOutShoppingCart();



The preceding code shows exactly how a stateful session bean works. Two books are created and added to

a shopping cart of a stateful component. At the end, the checkOutShoppingCart() method relies on the maintained

state and can check out the two books.

When a client invokes a stateful session bean in the server, the EJB container needs to provide the same instance

for each subsequent method invocation. Stateful beans cannot be reused by other clients. Figure 7-5 shows the

one-to-one correlation between a bean instance and a client. As far as the developer is concerned, no extra code is

needed, as the EJB container automatically manages this one-to-one correlation.



Figure 7-5.  Clients accessing stateful beans

The one-to-one correlation comes at a price because, as you might have guessed, if you have one million clients, you

will get one million stateful beans in memory. To avoid such a big memory footprint, the container temporarily clears

stateful beans from memory before the next request from the client brings them back. This technique is called passivation

and activation. Passivation is the process of removing an instance from memory and saving it to a persistent location

(a file on a disk, a database, etc.). It helps you to free memory and release resources (a database or JMS connections, etc.).

Activation is the inverse process of restoring the state and applying it to an instance. Passivation and activation are

done automatically by the container; you shouldn’t worry about doing it yourself, as it’s a container service. What you

should worry about is freeing any resource (e.g., database connection, JMS factories connection, etc.) before the bean

is passivated. Since EJB 3.2, you can also disable passivation as you’ll see in the next chapter with life-cycle and callback

annotations.



242

www.it-ebooks.info



Chapter 7 ■ Enterprise JavaBeans



Let’s return to the shopping-cart example and apply it to a stateful bean (see Listing 7-7). A customer logs on to

a web site, browses the catalog of items, and adds two books to the shopping cart (addItem() method). The cartItems

attribute holds the content of the cart. Then the customer decides to get a coffee at a coffee machine. During this time,

the container might passivate the instance to free some memory, which in turn saves the shopping content to permanent

storage. A few minutes later, the customer comes back and wants to know the total price (getTotal() method) of his

shopping cart before buying anything. The container activates the EJB and restores the data to the shopping cart.

The customer can then check out (checkout() method) and buy the books. Once the customer logs off, the customer’s

session ends, and the container frees memory by permanently removing the instance of the stateful bean.

Listing 7-7.  Stateful Session Bean ShoppingCartEJB

@Stateful

@StatefulTimeout(value = 20, unit = TimeUnit.SECONDS)

public class ShoppingCartEJB {



private List cartItems = new ArrayList<>();



public void addItem(Item item) {

if (!cartItems.contains(item))

cartItems.add(item);

}



public void removeItem(Item item) {

if (cartItems.contains(item))

cartItems.remove(item);

}



public Integer getNumberOfItems() {

if (cartItems == null || cartItems.isEmpty())

return 0;

return cartItems.size();

}



public Float getTotal() {

if (cartItems == null || cartItems.isEmpty())

return 0f;



Float total = 0f;

for (Item cartItem : cartItems) {

total += (cartItem.getPrice());

}

return total;

}



public void empty() {

cartItems.clear();

}



@Remove

public void checkout() {

// Do some business logic

cartItems.clear();

}

}





www.it-ebooks.info



243



Xem Thêm
Tải bản đầy đủ (.pdf) (597 trang)

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×