ActionBazzar Application
EJB 3 Base solution
Building business logic with EJB 3
Using stateless session beans
Stateless session beans are used to model actions or processes that can be done in a single method call.
@Stateless—The@Statelessannotation tells the EJB container that Default- BidService is a stateless session bean. This means that the container automatically makes sure that the bean is completely thread-safe, transactional, and pooled. Thread-safe and transactional mean that you can use any back-end resources such as a database or message queue without writing any concurrency or transaction code yourself. Pooling ensures that the service will perform well even under a very heavy load. You can add additional EJB services to the compo- nent, such as security, scheduling, or interceptors, on an as-needed basis.@Local—The@Localannotation on the BidService interface tells the con- tainer that theBidServiceEJB can be accessed locally through the interface. Because EJBs and components that use them are typically collocated in the same application, this is probably perfect. If you want, you can omit the@Localannotation and the interface will still count as a local EJB interface. Alternatively, you could have marked the interface with the@Remoteor@WebServiceannotations. Remote access through the@Remoteannotation is provided under the hood by Java Remote Method Invocation (RMI), so this is the ideal means of remote access from Java clients. If the EJB needs to be accessed by non-Java clients like Microsoft .NET or PHP applications, SOAP–based remote access can be enabled using the@WebServiceannotation applied either on the interface or on the bean class. Note also that an EJB need not have an interface at all.@Inject—As you know, the bid service depends on the bid DAO for persistence. The@InjectCDI annotation injects the non-EJB DAO into theBidServiceinstance variable. If you’re not familiar with dependency injection, you may think that what the@Injectannotation is doing is a little unusual—in a nifty, black-magic kind of way. You might have been wondering if thebidDaoprivate variable is even usable because it’s never set! If the container didn’t intervene, you’d get the infamousjava.lang.NullPointerExceptionwhen you tried to call theaddBidmethod in listing 2.1 because thebidDaovariable would still be null. One interesting way to understand dependency injection is to think of it as “custom” Java variable instantiation. The@Injectannotation in listing 2.1 makes the container “instantiate” thebidDaovariable with the right DAO implementa- tion before the variable is available for use.
Understanding stateless
Using stateful beans
Stateful session beans guarantee that a client can expect to set the internal state of a bean and count on the state being maintained between any number of method calls.
Maintaining the Session
Implementing the solution
The @Remove annotation marks the end of the workflow modeled by a stateful bean.
In this case, you’re telling the container that there’s no longer a need to maintain the bean’s session with the client after the placeOrder method is invoked. If you didn’t tell the container what method invocation marked the end of the workflow, the container could wait for a long time until it could safely time out the session. Because stateful beans are guaranteed to be dedicated to a client for the duration of a session, this could mean a lot of orphaned state data consuming precious server resources for long time periods!
Unit testing EJB 3
Embedded containers are most useful in unit testing EJB 3 components with frameworks like JUnit or TestNG. Allowing for robust EJB 3 unit testing is the primary focus of projects like Arquillian.
The @RunWith annotation tells JUnit to run Arquillian as part of the test. Arquillian controls the lifecycle of the embedded EJB container behind the scenes—it starts the container before the unit test starts and shuts it down when the unit test ends. Arquillian then deploys the components under testing to the embedded container—we’ve omit- ted the code that makes the deployment happen, but you can find it in the code samples. Arquillian is also responsible for injecting the ordering processor into the test , along with any other required dependencies.
Using CDI With EJB 3
Using CDI with JSF 2 and EJB 3
Using CDI with RJB 3 and JPA 2
The DAO is very simple. Some of you might be surprised that neither the DAO class nor the interface has any annotations on it at all. This is normal in the CDI world because CDI-managed beans truly are bare POJOs. When CDI sees the @Inject annota- tion in the BidService EJB, it looks for any object that implements the BidDao inter- face and injects it. It’s important to note that the BidDao is “nameless”—it doesn’t have an @Named annotation. This is because the DAO doesn’t need to be referenced by name anywhere. The DAO also doesn’t have a defined scope. When this happens, CDI assumes that the bean belongs in the default scope. By default, CDI creates a brand- new instance of the bean and injects it into the dependent component—basically the same behavior as a “new” operator at the injection point. Notice also that the BidDAO itself can request injection.
Using JPA 2 with EJB 3
Mapping JPA 2 entities to the database
@GeneratedValue: annotation` is used to indicate that the persistence provider should automatically generate the primary key when the entity is saved into the database.@ManyToOne: annotation indicates the nature of the relationship between the entities. In relational terms, this means that theBIDStable holds foreign-key references to the tables holding theItemandBidderentities.@JoinColumn: annotation specifies what these foreign-key references are. In the case of the bid–item relationship, the foreign key stored in theBIDStable isITEM_ID, which references a key namedITEM_IDthat’s likely the primary key of theITEMStable.
Using the EntityManager
The EntityManager knows how to store a POJO entity into the database as a relational record, read relational data from a database and turn it into an entity, update entity data stored in the database, and delete data mapped to an entity instance from the database. The EntityManager has methods corresponding to each of these CRUD (create, read, update, delete) operations, in addition to support for the robust Java Persistence Query Language (JPQL).
EntityManager interface is as an interpreter between the object-oriented and relational worlds. The manager reads the O/R map- ping annotations like @Table and @Column on the Bid entity and figures out how to save the entity into the database.
persistmethod is called to save theBiddata into the database c . After the persist method returns, an SQL statement much like the following is issued against the database to insert a record corresponding to the bidfindmethod retrieves an entity by the primary keymergemethod updates an entity in the databaseremovemethod deletes an entity
Working with EJB components
Building business logic with session beans
Getting to Know session beans
The theory behind session beans centers on the idea that each request by a client to complete a distinct business process is completed in a session.
When to use session beans
- Session beans are much more than a simple abstraction for partitioning business logic. The container manages session beans and provides them with a number of important services. These services include injection, transaction management, con- currency control, security, remoting, scheduling (timer), and interceptors.
- By default, all session beans are transactional and completely thread-safe
- In addition, many containers pool stateless session beans for scalability
- Session beans are also the de facto delivery mechanisms for container services like security, scheduling, asynchronous processing, remoting, and web services. Compo- nents that might need these services should be session beans (usually these services are applied at the business application API layer anyway).
Session beans shouldn’t be used for page navigation or processing the request parameters from a web form. These are tasks best suited for JSF-backing beans or plain CDI-managed beans. Putting this logic in a session bean pushes the session bean up into the UI layer. Mixing UI logic and business logic makes for messy code that’s hard to maintain in the long run.
Component state and session bean types
- Stateless session beans are ideal for business services that have atomic, fire-and-forget API methods.
- Stateful bean instances are created when a client first accesses them, aren’t shared with any other clients, maintain state in instance variables on behalf of that client, and are destroyed when the client ends the session. Stateful session beans are useful in model- ing workflow-based multistep services where the service must hold state from one workflow state to the other.
- The container instantiates the singleton and ensures that only one instance is created. The container also helps to properly manage concurrent access to the bean by multiple clients. All clients share the internal state of the singleton, and the singleton is expected to hold and pass on a state change that one client makes across all other clients via its current state. Singletons are intended to model services that utilize state stored in a shared cache.
Stateless session beans
A stateless session bean doesn’t maintain any conversational state, and service tasks must be completed in a single method call. This certainly doesn’t limit a stateless session bean to containing only one method. On the contrary, stateless session beans usually group together several closely related business service API methods.
When to use stateless beans
Stateless session bean pooling
GlassFish server:
Initial and minimum pool size—The minimum number of beans to appear in the pool. The default is 0.Maximum pool size—The maximum number of beans that can be present in the pool. The default is 32.Pool resize quantity—The number of beans to be removed when the pool idle time-out expires. The default is 8.- Pool idle time-out —The maximum number of seconds that a bean can reside in the pool without servicing a request before it’s released for garbage collection. The default is 600.
Using the @Statelesss annotation
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Stateless {
public String name() default "";
public String mappedName() default "";
public String description() default "";
}
name: parameter specifies the name of the bean. Containers use this parameter to bind the EJB to the global JNDI tree.- If the
nameparameter is omitted, the container assigns the unqualified name of the class to the bean. In this case, the container would assume the beannameto beDefaultBidService. - The
mappedNamefield is a vendor-specific name that you can assign to your EJBs; some containers use this name to assign the JNDI name for the EJB. Generally, you won’t be using the mappedNamefield.
Bean business interfaces
- Local Interface
- A local interface is designed for clients of a stateless session bean collocated in the same container (JVM) instance. You designate an interface as a local business interface by using the @Local annotation.
- Local interfaces are the easiest to define and use. They’re also by far the most common type of EJB interface and are the default type of interface for EJBs. This means that you can omit the
@Localannotation and the interface will still be treated as a local interface. - Note that in EJB 3.1 it’s not necessary to define a local interface.
- Remote Interface
- Clients residing outside the container’s JVM instance must use some kind of
remote interface. - EJB 3 enables a session bean to be made accessible via RMI through the
@Remoteannotation. - A remote business interface may extend
java.rmi.Remoteas you’ve done here, although this is strictly optional. - Remote business methods aren’t required to throw
java.rmi.RemoteExceptionunless the business interface extends thejava.rmi.Remoteinterface. - Remote business interfaces have one special requirement: all parameters and return types of the interface methods must be Serializable. This is because only Serializable objects can be sent across the network using RMI.
- Clients residing outside the container’s JVM instance must use some kind of
@Remote
public interface BidService extends Remote {
...
}
- Web service endpoint interface
- In addition to local and remote interfaces, session beans can also have web service interfaces.
- In Java EE 7 two different web service technologies are supported: SOAP via JAX-WS and REST via JAX-RS. With both JAX-WS and JAX-RS, annotations can be placed either on a separate interface or on the bean implementation class itself.
create a new interface and add the @javax.jws.WebService annotation. The follow- ing code snippet demonstrates this for the BidService:
@WebService
public interface BidSoapService {
List<Bid> getBids(Item item);
}
Lifecycle callback
- Creates bean instances using the default constructor.
- Injects resources such as JPA providers and database connections.
- Put instances of the bean in a managed pool (if the container supports pooling).
- Pulls an idle bean out of the pool when an invocation request is received from the client. At this point, the container may have to instantiate additional beans o handle additional requests. If the container doesn’t support pooling, bean instances are simply created on demand.
- Executes the requested business method invoked through the business interface by the client.
- When the business method finishes executing, the bean is placed back in the “method-ready” pool (if the container supports pooling). If the container doesn’t support pooling, the bean is discarded.
- As needed, the container retires beans from the pool.
If you look carefully, you’ll see that the stateless session bean lifecycle ensures that all bean instances are accessed only by one request thread at a time. This is why stateless session beans are completely thread-safe and you don’t have to worry about synchronization concerns at all, even though you’re running in a highly concurrent server environment!
A stateless session bean has two callbacks with the following annotations:
@PostConstruct—This is invoked immediately after a bean instance is created and set up and all resources are injected.@PreDestroy—This is invoked right before the bean instance is retired.
Using stateless session bean effectively
- Tune pooling
- Dont abuse remoting
- if you accidentally use the @Remote annotation instead of the
@Localannotation, you’ll still be able to transparently inject the remote EJB using@EJBas though it were a local EJB without realizing it. This is why it’s very important that you avoid the@Remoteannotation unless it’s really needed.
- if you accidentally use the @Remote annotation instead of the
- Using interfaces
- Although it’s technically possible to avoid using interfaces with EJB 3.1, we recom- mend that you use interfaces anyway unless you’re developing a prototype or using session beans as JSF-backing beans. If you’re developing a service, it’s best to maintain loose coupling through an interface for easier testability as well as future flexibility.
- Property design remote interfaces
- When using remote interfaces, make sure the methods that you include in the interface are really supposed to be remotely exposed. You can have a local interface and a remote interface that expose completely different methods.
- Remote objects aren't passed by reference
- Remote method parameters and return types must be serializable.
- Avoid fine-grained remote calls
- Remote calls are expensive—beans accessed locally can be finer grained, whereas remote beans should naturally be very coarse-grained.
Stateful session beans
- Stateful session beans maintain their state over multiple method invocations.
- In addition to ensuring that the same bean is used for all invocations from a given client, the container also ensures that only one thread is accessing the bean at a time.
- Bean instances can’t be readily returned to a pool and reused for another client. Instead, a bean instance must be squirreled away in memory to wait for the next request from the client owning the session.
When to use stateful session beans
Stateful session beans are ideal for multistep, workflow-oriented business processes.
- Stateful session beans are thread-safe and participate in transactions as well as container security.
- Stateful session beans can also be accessed remotely via RMI and SOAP as well as REST .
- Finally, the container manages them for you—stateful session beans are automatically passivated when no longer in use or destroyed after an in-activity timeout is triggered.
Stateful session bean passivation
- The container will archive stateful session beans if they haven’t been used for a while.
- The container employs a technique called
passivationto save memory when possible.- Passivation means moving a bean instance from memory to disk.
- The container accomplishes this task by serializing the entire bean instance.
- Activation is the opposite of passivation and is done when the bean instance is needed again.
- The container acti- vates a bean instance by retrieving it from per- manent storage and deserializing it.
- As a result, all bean instance variables must either be a Java primitive, implement
java.io.Serializable, or be marked astransient.
Stateful session bean clustering
Most application servers cluster stateful session beans. Even if the machine that your stateful session bean currently resides in crashes, a clustered, load-balanced, and failed-over set of servers means that you’ll be transparently rerouted to the next avail- able machine on the cluster and it’ll still have the up-to-date state of the bean.
Clustering is an essential feature for mission-critical systems that must guarantee reliability.
Bidder account creator bean example
Using the @Stateful annotation
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Stateless {
public String name() default "";
public String mappedName() default "";
public String description() default "";
}
Bean business interfaces
Stateful session beans support local and remote invocations through the @Local and @Remote annotations.
But a stateful session bean can’t have a web service endpoint interface. This means that a stateful session bean can’t be exposed using JAX-RS or JAX-WS. This is because web service interfaces are inherently stateless in nature.
Lifecycle callbacks
- The container always creates a new bean instance using the default constructor whenever a new client session is started.
- After the constructor has completed, the container injects the resources such as JPA contexts, data sources, and other beans.
- An instance is stored in memory awaiting method invocations.
- A client executes a business method through the business interface.
- The container waits for subsequent method invocations and executes them.
- If the client remains idle for a period of time, the container passivates the bean instance (if the container supports passivation). The bean gets serialized out to disk.
- If the client invokes a passivated bean, it’s activated (the object is read in from disk).
- If the client doesn’t invoke a method on the bean for a period of time, the bean is destroyed.
- If the client requests removal of a bean instance and it’s presently passivated, it’ll be activated, and then the bean will be destroyed and reclaimed by garbage collection.
The callbacks available on stateful session beans are as follows:
@PostConstruct—This is invoked right after the default constructor has executed and resources have been injected.@PrePassivate—This is invoked before a bean is passivated; that’s before the bean is serialized out to disk.@PostActivate—This is invoked after a bean has been read back into memory but before business methods are invoked from a client.@PreDestroy—This is invoked after the bean’s timeout has expired or the client has invoked a method annotated with@Remove. The instance will be subsequently released to the garbage collector.
In addition to these callbacks, one or more methods can be annotated with @Remove. This annotation informs the container that when the method exits, the stateful session bean is to be released.
Failure to remove stateful beans will have a serious impact on server performance. The problem might not be apparent with a small number of clients, but it will become critical as more people request state- ful session beans over time.
Using stateful session beans effectively
- Choosing session data appropriately
- Stateful session beans can become resource hogs and cause performance problems if they’re not used properly.
- Consequently, you have to closely examine what kind of data you’re storing in the conversation state and make sure the total memory footprint for the stateful bean is as small as possible.
- If you cluster stateful session beans, the conversational state is replicated between different instances of the EJB container. State replication uses network bandwidth. Storing a large object in the bean state may have a significant impact on the perfor- mance of your application because the container will spend an excessive amount of time replicating objects to other instances to ensure high availability.
- Tuning passivation
- Remove stateful session beans
- explicitly removing the bean instances that are no longer required rather than depending on the container to time them out.
Singleton session beans
Singleton session beans were added in EJB 3.1. Only one instance is created during the lifecycle of an enterprise application.
Singleton beans support the same callbacks as stateless session beans but come with some unique fea- tures, including the ability to control concurrent access to the bean as well as the abil- ity to chain singleton bean instantiation.
Just like stateless and stateful beans, singleton beans also support injection, security, and trans- action management.
When to use singleton session beans
Singleton beans enable you to get around having to use custom solutions, such as startup servlets, POJOs with static fields, and various other derivations. Thus, you use singleton beans when you want to have a shared state that’s application-global or a sin- gle chokepoint for a specific task.
- Startup tasks
- Centralized clearinghouse
- Counterpoint
You should never use singletons as stateless services; rather, use stateless session beans instead. Most stateless services aren’t read-only and require database interaction through non-thread-safe APIs like the JPA entity manager. Using a thread-safe singleton in such a case doesn’t scale because there’s only one instance of a bean that must be shared by all concurrent clients.
Example
Using the @Singleton annotation
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Stateless {
public String name() default "";
public String mappedName() default "";
public String description() default "";
}
Singleton bean concurrentcy control
With container-managed concurrency, the container synchronizes method calls. Annotations are provided so that you can mark methods as either read or write and also specify time-out for methods that may block. With bean-managed concurrency, it’s up to you to use Java’s concurrency features such as the synchronized and volatile primitives or the java.util.concurrent API to manage concurrent access and ensure correctness.
An annotation is used to specify which concurrency management approach is being used. If no annotation is provided, container-managed concurrency is assumed.
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)—Bean concurrency management@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)—Container concurrency management
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface ConcurrencyManagement {
public ConcurrencyManagementType value() default ConcurrencyManagementType.CONTAINER; }
Container-Managed concurrency
- By default, all bean methods are serialized via write locks.
- Two annotation combinations are provided by the EJB specification, enabling you to tell the container what type of lock- ing behavior you really want:
@Lock(LockType.READ)—This method can be accessed concurrently while no one holds a write lock on the bean.@Lock(LockType.WRITE)—Place a write lock on the bean when the method is invoked so that only the current thread gets access.
If the time-out is exceeded, a javax.ejb.ConcurrentAccessTimeoutException is thrown. This is a runtime exception, meaning that a caller doesn’t have to catch it. The @AccessTimeout annotation is used to specify lock time-outs.
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface AccessTimeout {
public long value();
public TimeUnit unit() default TimeUnit.MILLISECONDS;
}
Code example
public interface FeaturedItem {
@Lock(LockType.READ)
@AccessTimeout(value=1,unit=TimeUnit.MINUTES)
public Item getFeaturedItem();
}
Bean-Managed concurrency
- Bean-managed concurrency puts you completely in charge of managing the concurrency of your singleton bean.
- To do this, you use the Java concurrency primitives, such as
synchronized,volatile,wait,notify, and so on, or Doug Lea’s fabledjava.util .concurrentAPI.
Bean business interface
You can have remote, local, and web service (both SOAP and REST) business interfaces. Each of these three methods of accessing a singleton session bean is denoted using the annotations @Local, @Remote, and @WebService, respectively.
The only real difference between singleton and stateless session bean business interfaces is that you can annotate a singleton session bean interface’s methods with the following annotations:
@Lock(LockType.READ)@Lock(LockType.WRITE)@AccessTimeout
All three of these annotations have an effect only if container-managed concurrency is being used; otherwise they have no effect.
Lifecycle callbacks
The lifecycle of singleton session beans is the simplest of all of the beans. Once they’re instantiated, they’re not destroyed until the application terminates.
- The container starts by creating a new instance of the singleton bean. The bean may be instantiated on startup (
@Startup) or as a result of another bean being instantiated (@DependsOn). Normally, beans are instantiated lazily as they’re first accessed. - After the constructor has completed, the container injects the resources such as JPA contexts, data sources, and other beans.
- The
@PostConstructannotated method is invoked. The bean isn’t accessible until it completes successfully. - The instance is stored in memory awaiting method invocations.
- The client executes a business method through the business interface.
- The container is informed that it must shut down.
- The
@PreDestroycallback is invoked prior to the application terminating.
Two callback
@PostConstruct—This is invoked right after the default constructor has exe- cuted and resources have been injected.@PreDestroy—This is invoked before the bean is destroyed. The instance will subsequently be released to the garbage collector.
The most important thing to remember about these callbacks is that they’re invoked once at most.
@DependsOn annotation
@Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface DependsOn {
public String[] value();
}
The @DependsOn annotation ties nicely into the @Startup annotation.
@Startup annotation
To mark a singleton session bean as being auto-instantiated, all you need to do is add the @Startup annotation to the bean
Target(value = {ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Startup {
}
Using stateful singleton session beans effectively
Choosing correct concurrency type
- A lock type of
READenables multiple threads to access the bean concurrently, whereas theWRITElock grants exclusive access.
Configuring container-managed concurrency
- One of the dangers with container-managed concurrency is that the container by default uses the
writelock if you don’t specify otherwise.
Managing startup singletons
- Startup singletons can be used to auto-run business logic on application startup and cache data for the application.
- Containers, such as GlassFish, will throw a
java.lang .IllegalAccessExceptionif your bean tries to access a stateless/stateful session bean from the@PostConstructmethod. So other beans may not be available yet, but you’ll have access to JPA and can manipulate the database. @DependsOnannotation should be used to control the startup sequence.
Handling exceptions
- Exceptions generated from a singleton bean are treated differently than exceptions from a stateless or stateful session bean.
- An exception thrown from the
PostConstructmethod of a singleton causes the instance to be discarded. - An exception thrown by a business method doesn’t result in the bean being discarded—the bean will be discarded only when the application terminates.
Asynchronous session beans
- New to EJB 3.1 is support for asynchronous beans with the
@Asynchronousannotation.
Basics of asynchronous invocation
- The return type for an asynchronous method is either void or java.util.concurrent.Future
When to use asynchronous session beans
- You have a long-running operation that you want to start and then continue something else, regardless of what happens with this operation.
- You have a long-running operation for which you want to start and then check back later to see what the result is after doing something. You may also want to cancel this operation.
Using the @Asynchronous annotatioin
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Asynchronous { }
Using the Future interface
Using asynchronous session beans effectively
- Supporting cancel
- Handling exceptions