Ejb Annotations Primer
Ejb Annotations Primer
of Contents
Introduction 1.1
Getting Started 1.2
EJB Core 1.3
Lifecycle Management 1.4
Pooling 1.5
Concurrency 1.6
Aspect Oriented programming with Interceptors 1.7
Going Async with EJBs 1.8
Eager Initialization 1.9
Schedulers & Timers 1.10
Web Services support 1.11
Exception Handling 1.12
Security 1.13
Transactions 1.14
Dependency & Resource Injection 1.15
Heterogeneous Interfaces 1.16
References, resources & hello! 1.17
1
Introduction
Think of it as an EJB cheat sheet or a quick reference. It consists of short chapters, each of
which cover a specific part of the EJB specification. Here is a comprehensive list - life cycle
management, dependency & resource injection, pooling, concurrency, web services,
interceptors, security, transactions, schedulers & timers, asynchronous model, eager
initialization (with Singletons) and exception handling.
EJBs present a simplified, declarative and POJO based programming model powered
by annotations. This is personified by its API layout which consists of 32 annotations.
From a Java EE developer standpoint, the real magic of EJBs lies in its annotations !
The general outline of the book is simple and focused on the following
2
Introduction
Is it for you ?
Both beginners and experienced developers can make use of this book. For folks new to
Java EE (in general) and EJB (to be specific) can use it as a high level guide to get a feel of
what EJB as a technology has to offer and to pick up its feature. Seasoned developers can
use this as a quick reference/refrsher from time to time.
Source code
The code for this book is available in GitHub. It was developed using NetBeans 8.1 which
has out-of-the support for Java EE 7 and comes bundled with GlassFish 4.1.1
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives
4.0 International License.
3
Getting Started
Getting Started...
This chapter is more of super quick reference for those who are busy Googling for answers
like,
.....etc.
You can easily find answers to these common questions since this information has been
conveniently sub-divided into logical categories.
Only EJB 3.x releases (Java EE 5 and later) have been covered
EJB 3.0
Java EE 5 was where it all began - ease of use was driven by POJO based declarative
programming model and the annotations were largely responsible for this recarnation. Here
is a snapshot
4
Getting Started
EJB 3.1
Building further on the simplified model put forth in EJB 3.0, the 3.1 version introduced richer
features and made things even easier
5
Getting Started
TimerService API has been enhanced to add a getAllTimers method which returns all
6
Getting Started
7
Getting Started
8
Getting Started
Up next ...
Time to dive in ....!
9
EJB Core
EJB Core
The annotations described in this section are at the heart of EJBs. Just like other Java
annotations, these are just pieces of metadata with which you decorate your POJO (Plain
Old Java Objects) classes. But their real power is harnessed by the EJB container, which
automatically lines up services for your components based on the type of EJB represented
by the annotation.
Exploration of these implicit services provided by the EJB runtime and their corresponding
annotation is what this book is all about - so you'll read more about these features as you
progress. Some of these services include thread safety, concurrency, pooling, transactions,
scheduling etc.
Clearly distinguishes different EJBs and the bean developer can make an
appropriate choice depending upon the required business scenario.
Provides a simplified programming model based around POJOs, on top of which
features are applied in a declarative fashion using annotations and the heavy lifting is
delegated to the container
Promotes ease-of-use through Convention Over Configuration approach in (common
throughout the Java EE platform) - enables sensible defaults which can be further
refined by annotations or XML deployment descriptors
@Stateless
It was EJB 3.0 (part of the Java EE 5 specification), which initiated its revival as a
lightweight, POJO based programming tool and the @Stateless annotation was at the
centre of it all.
10
EJB Core
package ejbap.core;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
public class StatelessBeanExample {
@PersistenceContext
private EntityManager em;
What's critical to understand is that every time a method on the bean is invoked, a different
(pooled) instance is chosen by the container (at random). Hence it goes without saying that,
one should not store any state within the bean using instance variables. This is because
there is no guarantee as to whether or not the bean which was commissioned to your
application for executing the current request will be chosen for the subsequent invocations
as well. This is the idea behind the name Stateless: all instances of a Stateless session
bean are equivalent
Being unable to store state is not necessarily bad. It actually results in important
characteristics such as
Scalability - The container can be tuned to pool instances of your EJBs (more on this
later). This is only restricted by the amount of resources (memory and processing
capacity) on the physical machinehosting the server.
Thread safety by default - No two threads can ever act on the same instance of the
bean, since the container always spins up a new bean instance with each new request.
@Stateful
This annotation defines a session bean whose instances can hold state specific to a client
and remain attached to the very same client throughout its life cycle. The container also
renders other implicit services like thread safety, transactions etc.
11
EJB Core
package ejbap.core;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.ejb.Stateful;
@Stateful
public class StatefulBeanExample {
From EJB 3.2 onwards, one can also configure a Stateful bean to not get passivated at all.
package ejbap.core;
import javax.ejb.Stateful;
@Stateful(passivationCapable = false)
public class StatefulNoPassivationBeanExample {
//details omitted
}
Removal hooks - A Stateless bean does not provide explicit call back/hook (annotation)
which can control its eviction/removal - it's entirely managed by the EJB runtime. In the case
of Stateful beans, the bean developer can provide a method annotated with @Remove which
12
EJB Core
JPA Extended Persistence scope - A JPA Entity Manager injected within a Stateful can be
configured to leverage Extended Persistence scope which ensures that the JPA entities
handled by the Entity Manager remain managed throughout the lifecycle of the EJB i.e. they
are not limited to transaction boundaries as is the case with entity managers associates with
Stateless EJBs
package ejbap.core;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
@Stateful
public class StatefulBeanWithExtendedPersistenceContext {
@PersistenceContext(type = PersistenceContextType.EXTENDED)
EntityManager em;
@Singleton
The container creates a single instance of your bean (scoped to your container JVM of
course)
The container provides implicit thread safety by default
13
EJB Core
package ejbap.core;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
@Singleton
public class SingletonBeanExample {
private Properties config;
Some of the common use cases for using Singleton beans are bootstrapping global
configuration, implementing custom caches, starting services on application loading etc.
@MessageDriven
14
EJB Core
This annotation is used to define a Message Driven Bean (a.k.a MDB). The
@ActivationConfigProperty annotation works hand in hand with @MessageDriven and helps
package ejbap.core;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
@MessageDriven(activationConfig = {
//below mentioned annotation will be covered later
@ActivationConfigProperty(propertyName = "destinationLookup",
propertyValue = "java:comp/env/myQueue"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")
})
public class MDBExampleBean implements MessageListener{
@Override
public void onMessage(Message msg) {
try {
print(msg);
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
Why MDBs ?
Message Driven beans are generally used in conjunction with JMS (Java Message Service)
where JMS acts as a messaging provider/router. Sender (a JMS message producer) uses
the JMS API to send messages to JMS specific destinations (queues/topics) and the MDB in
turn is tuned to listen to these destinations.
The message sender does not directly interact with a MDB. A MDB is invoked by the
15
EJB Core
Sequence of events
1. The sender sends the message and it's associated thread returns (frees up) as
soon as the message sending process (i.e. the method call) completes
2. The message consumption and business logic execution is carried out by the MDB
in background by a completely different thread (managed by the EJB container)
Completely decouples the sender and receiver - the sender just knows where to send the
message. It's not aware of the specifics of the MDB. Similarly, all the MDB knows about is
the message it is supposed to process
Reilability - It offers various degrees of reliability by providing facilities for persistence and
acknowledgement of messages which in turn ensures guaranteed message delivery with
once-and-only-once semantics.
MDBs are not part of the JMS specification or coupled with JMS by any means. This is
a misconception. Just like Stateless session beans, MDBs are pooled components
which can process messages in an asynchronous fashion and can listen to any end
point (including a JMS queue or destination) for which there is a compliant JCA
resource adapter. In fact, this has been the case since EJB 2.1 and is made possible
by the JCA (Java Connector Architecture) specification.
16
EJB Core
17
EJB Core
What's next ?
The next chapter will dwell into the details of how the EJB container manages the lifecycle of
different instances of stateless, stateful, singleton and message driven EJBs.
18
Lifecycle Management
Lifecycle management
The EJB container manages the life cycle of session beans based on callback
annotations. Some of these annotations apply to all managed beans in general and some
are applicable only to specific EJB types. All these annotations can only be applied to a
single method only.
Identify methods which need to be executed when a session bean reaches a particular
life cycle stage (e.g. after is it constructed, prior to removal etc.)
Decorate those methods with an appropriate annotation which conveys information
regarding the actual life cycle stage during which the method will receive a call back i.e.
automatically invoked by the container
@PostConstruct
All managed beans can enjoy the services rendered by @PostConstruct . Methods decorated
with this annotation are automatically invoked by the container after the constructor
invocation and dependency injection (if any) have been executed.
@PreDestroy
The method annotated with @PreDestroy annotation is called just before the container is
about to discard the EJB instance. Just like @PostConstruct , this annotation can also be
applied to any Managed Bean executing within the container (including EJBs)
The destruction of an EJB instance might happen under multiple scenarios (we are not
covering this in depth). Also, the term destroy or discard in context of EJB instances
refers to putting that particular instance out of service i.e. it is made available for
garbage collection and will no longer be used by the EJB container to serve client
requests
19
Lifecycle Management
package ejbap.lcm;
import ejbap.core.StatelessBeanExample;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Stateless;
import javax.inject.Inject;
@Stateless
public class StatlessBeanBasicLCM {
@Inject
private StatelessBeanExample instance;
@PostConstruct
public void init(){
System.out.println("Post construct callback invoked");
System.out.println("Injected EJB instance - " + instance.hashCode());
}
@PreDestroy
public void destroy(){
System.out.println("I am about to be consumed by the GC !");
}
}
The annotations discussed below are only to Stateful session beans i.e. beans
decorated with @Stateful
@PrePassivate
A method annotated with this call back annotation instructs the container to invoke it before
serializing the Stateful bean instance from memory to disk
@PostActivate
The container calls a method decorated with @PostActivate right after it brings a passivated
stateful bean instance from disk back into the main memory
@Remove
When a method annotated with @Remove is invoked by the client of the stateful EJB
instance, the container destroys it after completion of the method.
20
Lifecycle Management
Unlike @PreDestroy , the @Remove is not a call back style annotation. Also, methods
annotated with @PreDestroy (if any) will be invoked prior to destruction of the EJB
instance
package ejbap.lcm.stateful;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.PrePassivate;
import javax.ejb.Stateful;
import java.sql.Connection;
import java.sql.SQLException;
import javax.ejb.PostActivate;
import javax.ejb.Remove;
@Stateful
public class StatefulBeanLCM {
@PostConstruct
@PostActivate
public void init(){
//fetch a DB connection
conn = getConnection();
}
@PreDestroy
@Remove
@PrePassivate
public void close(){
closeConnection();
}
21
Lifecycle Management
@StatefulTimeout
The container uses the value associated with the @StatefulTimeout annotation to determine
the duration for which the bean instance can remain idle (without serving client requests).
After the timeout threshold is crossed, the instance is a candidate for removal i.e. garbage
collection and (subsequent) passivation
package ejbap.lcm.stateful;
import java.util.concurrent.TimeUnit;
import javax.ejb.Stateful;
import javax.ejb.StatefulTimeout;
import java.util.Date;
@Stateful
@StatefulTimeout(value = 1, unit = TimeUnit.MINUTES)
public class StatefulBeanTimeout {
You can use the value and unit elements of this annotation to define its behaviour
Configuration options
Here are a few examples
@StatefulTimeout(0) – this means that your bean instance will be removed immediately
@StatefulTimeout(15000) – method will wait for 15000 ms (15 seconds) for client
22
Lifecycle Management
Does Not Exist: the bean does not yet exist in the EJB pool (has not been instantiated)
Ready: state where the EJB instance already exists in the EJB pool but is not servicing
a client request
Active: the EJB instance is summoned in order to service a client request, and as a
result it goes into a BUSY state
23
Lifecycle Management
container's main memory and serialized to disk (or any secondary storage supported by
the container)
Does Not Exist: when the instance has not yet been created
Active: the bean is busy serving a request
24
Pooling
EJB Pooling
Basics
EJB instances are stored in an in-memory cache and they are not very different from
Database Connection pools - so you can think of it as a simple object pool managed by the
EJB container. Unlike other features, there are no explicit annotations which affect instance
pooling capabilities of session beans. In fact, these are configured in a vendor specific
manner (mainly using non portable annotations or deployment descriptors) e.g. weblogic-
ejb-jar.xml in Weblogic.
There is virtually no limit to the number of EJB instances which you can tune your
container to pool in memory - you are only limited by your hardware resources,
specifically the RAM
Initial limit: Configure number of beans which should be ready in the pool initially (after
the application starts).
Lower threshold: The EJB container pool count will never fall below this value. Think of
it as a SLA (service level agreement)
Benefits
Instance pooling is a key feature of EJBs since it provides key benefits such as
25
Pooling
@Stateless - Pooled beans which do not store state b/w client invocations
@Stateful - Stores state specific to a client, held in memory by the container and it is
EJBs in the sense that they are pooled components which do not store state b/w
invocations.
What's next ?
We'll look at some of concurrency semantics of different EJBs.
26
Concurrency
Concurrency
Having a good understanding of the Concurrency semantics of different sessions beans is
extremly important in order to be able to leverage them effectively. This chapter covers
concurrency related annotations and talks about how they affect performance characteristics
Specifies the time period after which a queued request (waiting for another thread to
complete) times out. This feature does not make sense for Stateless beans since the
container allocates a new bean instance for each request.
This annotation is valuable for Stateful beans as well as Singleton beans configured
with container managed concurrency option ( ConcurrencyManagementType.CONTAINER )
During peak loads, your session bean instances are bombarded with concurrent requests.
The EJB container ensures sanity by serializing these calls i.e. blocking other threads until
the current thread finishes execution. Think of this annotation as a concurrency policy. It
ensures that the potential (waiting) threads are not kept blocked forever.
package ejbap.concurrency;
import javax.ejb.AccessTimeout;
import javax.ejb.Stateful;
@Stateful
public class StatefulBeanWithTimeout{
@AccessTimeout(value=5000, unit=java.util.concurrent.TimeUnit.MILLISECONDS)
public void find(String id){
//... business logic
}
}
You can use the value and unit elements of this annotation to refine its behaviour
@AccessTimeout(0) – this means that your method does not support concurrent access
@AccessTimeout(5000) – method will wait for 5000 ms (5 seconds) before the next
27
Concurrency
@ConcurrencyManagement
package ejbap.concurrency;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Singleton;
@Singleton
//applicable by default
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class ContainerManagedSingleton {
@PostConstruct
public void init() {
property = new Date().toString();
}
In case you opt for Bean managed concurrency, you as a bean developer are responsible
for the thread safety of objects used within the Singleton bean e.g. using synchronized
methods, thread safe collections etc
28
Concurrency
package ejbap.concurrency;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Singleton;
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class DeveloperManagedSingleton {
/**
* need to synchronize this manually since container
* has no control over how many threads can enter this method
*/
@PostConstruct
public void init() {
property = new Date().toString();
}
}
@Lock
threads at the same time. The other option LockType.READ , behaves in exactly the opposite
manner i.e. it allows multiple threads to concurrently access this method given that there is
no thread which is currently holding a write lock on the Singleton bean instance.
29
Concurrency
package ejbap.concurrency;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Singleton;
@Singleton
public class GoldiLocks {
@PostConstruct
public void init() {
configuration = UUID.randomUUID().toString();
System.out.println("Configuration bootstrapped -- " + configuration);
}
@PreDestroy
public void destroy() {
System.out.println("Destroying Configuration -- " + configuration);
configuration = null;
}
/**
* This is by default. We can afford to relax
* since this is a READ operation
*/
@Lock(LockType.READ)
public String getConfig() {
return configuration;
}
/**
* We don't want multiple threads updating the configuration
* (a WRITE operation) at the same time!
*/
@Lock(LockType.WRITE)
public void update(String config) {
this.configuration = configuration + " " + config;
}
}
What's next ?
Let's explore the Aspect Oriented features provided by EJBs !
30
Concurrency
31
Aspect Oriented programming with Interceptors
History
Debut
Interceptors (v 1.0) were first introduced in EJB 3.0 (they did not have a specification
dedicated them). They bought basic AOP related features to managed beans (POJOs) via
simple annotations like @Interceptors , @AroundInvoke etc.
32
Aspect Oriented programming with Interceptors
Version 1.1
Along came Java EE 6 with EJB 3.1 and Interceptors 1.1. They were still included as a part
of the EJB specification. New annotations such as @InterceptorBinding , @Interceptor ,
@AroundTimeout were introduced in this version
They are not coupled to EJBs at all. From a functionality perspective, you do not need
to do anything special to reap the benefits of aspect oriented programming offered by
Interceptors. Thanks to the introduction of Managed Beans specification in Java EE 6,
Interceptors' capabilities are applicable to any POJO (which qualifies as a Managed
Bean) within your Java EE application. As EJBs are nothing but a specialized/advanced
form of Managed Beans, one can utilize the Interceptor annotations on EJBs in order to
implement generic cross cutting functionality like logging, auditing etc.
Let us look at the Interceptor annotations in detail along with some code examples
demonstrating their usage
@AroundInvoke
This annotation is used to decorate the method of a class which contains the interception
logic for target class methods
33
Aspect Oriented programming with Interceptors
package ejbap.interceptors;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
@AroundInvoke
public Object log(InvocationContext ic) throws Exception{
Object result = null;
final String className = ic.getTarget().getClass().getSimpleName();
final String methodName = ic.getMethod().getName();
try {
System.out.println(String.format(">> %s#%s", className, methodName));
result = ic.proceed();
} catch (Exception ex) {
System.err.println(ex.getMessage());
}finally{
System.out.println(String.format("<< %s#%s", className, methodName));
}
return result;
}
}
@AroundConstruct
Use this annotation to intercept the constructor of a class itself i.e. a method decorated with
@AroundConstruct is invoked by the container before an instance of the class (to which the
package ejbap.interceptors;
import javax.interceptor.AroundConstruct;
import javax.interceptor.InvocationContext;
@AroundConstruct
public void logObjectCreation(InvocationContext ic){
final String className = ic.getTarget().getClass().getName();
System.out.println("Created an instance of class "+ className);
}
}
34
Aspect Oriented programming with Interceptors
@Interceptors
Use @Interceptors annotation to define a one or more interceptor classes. This can be
used on a class or method.
package ejbap.interceptors;
import java.util.Date;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
@Stateless
@Interceptors({LoggerInterceptor.class, CreationTracker.class})
public class StatelessBeanWithInterceptor {
The interceptor declaration forces you to provide the exact type of the target class - hence
introduces tight coupling between the interceptor and intercepted class. This was improved
with the help of the CDI 1.0 specification
@InterceptorBinding
CDI 1.0 introduced a loosely coupled and type safe way of specifying interceptors of a class
or a method.
package ejbap.interceptors.cdi;
import javax.interceptor.InterceptorBinding;
import java.lang.annotation.*;
@InterceptorBinding
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PerformanceMonitorInterceptorBinding {
@Interceptor
35
Aspect Oriented programming with Interceptors
Before the CDI specification came into being (i.e. prior to Java EE 6), there was no notion of
explicitly declaring a class (containing interception methods) as an interceptor. The
@Interceptor annotation was used to explicitly declare a class containing an interception
logic in a specific method (annotated with @AroundInvoke etc) as an interceptor along with
an appropriate Interceptor Binding (discussed above).
package ejbap.interceptors.cdi;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
@Interceptor
@PerformanceMonitorInterceptorBinding
public class PerformanceMonitor {
@AroundInvoke
public Object measure(InvocationContext ic) throws Exception{
long start = System.currentTimeMillis();
Object result = null;
final String className = ic.getTarget().getClass().getSimpleName();
final String methodName = ic.getMethod().getName();
try {
result = ic.proceed();
} catch (Exception ex) {
System.err.println(ex.getMessage());
}finally{
long elapsed = System.currentTimeMillis() - start;
System.out.println(String.format("Time spent in %s#%s - %s", className,
methodName, elapsed));
}
return result;
}
}
36
Aspect Oriented programming with Interceptors
package ejbap.interceptors.cdi;
import javax.ejb.Stateless;
@Stateless
public class StatelessBeanWithInterceptorBinding {
@PerformanceMonitorInterceptorBinding
public void timeTakingOp(){
try {
//not allowed inside EJB container... just for simulation
Thread.sleep(2000);
} catch (InterruptedException ex) {
//ignore...
}
}
}
Memory Aid
37
Aspect Oriented programming with Interceptors
What's next ??
The next chapter will explore ways of using EJBs to execute business logic in an
asynchronous manner.
38
Going Async with EJBs
Asynchronous Execution
EJBs provide support for asynchronous execution of business logic wherein the calling
thread (invoking the EJB business method) is released and the actual processing takes
place in a background thread which is managed by the EJB container itself.
Asynchronous Beans
Message Driven Beans
@Asynchronous
Using MDBs (along with a full fledged JMS infrastructure setup) is not something which you
would want to commit to, if all you need is a few methods to be invoked asynchronously. In
case you do not need strict decoupling b/w sender and receiver and the rich features of
enterprise messaging offered by JMS, an easier way of adopting the asynchronous
processing paradigm is via the @Asynchronous annotation.
package ejbap.async;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
@Stateless
@Asynchronous
public class EmailService {
System.out.println("Sending email......");
try {
//for sample purposes ONLY
Thread.sleep(5000);
} catch (InterruptedException ex) {
throw new RuntimeException(ex);
}
}
39
Going Async with EJBs
In the above example, the annotated method returns void. One also can return a
parameterized java.util.concurrent.Future object i.e. Future<T> . Think of it like a
tracking ID for your order - you can invoke methods on it to introspect the status of the
asynchronous invocation or even cancel your it !
package ejbap.async;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
@Stateless
public class DataService {
@Asynchronous
public Future<String> fetch() {
System.out.println("Invocation thread -- " + Thread.currentThread().getName())
;
return new AsyncResult<>(longRunningMethod());
}
try {
//for sample purposes ONLY
Thread.sleep(5000);
return UUID.randomUUID().toString();
}
}
@ActivationConfigProperty
This annotation is used to declaratively configure a Message driven bean. It accepts name
value pairs where the name represents an attribute
40
Going Async with EJBs
Message Driven Beans are powered by the @MessageDriven annotation. Please refer to
the EJB Core chapter for a detailed discussion on this.
package ejbap.async;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "destinationLookup",
propertyValue = "java:comp/env/orderQueue"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")
})
public class MDBWithActivationConfig implements MessageListener{
@Override
public void onMessage(Message msg) {
try {
emailOrderDetails(msg);
} catch (JMSException ex) {
throw new RuntimeException(ex);
}
}
As you noticed, the destinationType and destinationLookup attributes were used in the
above example. There are a set of standard attributes which are applicable for Message
driven beans which listen to JMS destinations (topics and queues)
41
Going Async with EJBs
42
Eager Initialization
Eager Initialization
Quite often, there are scenarios where it is good to have something ready to use without
having to wait for intial setup. EJB Pooling ensures that Stateless and Message Driven
beans can take advantage of eager initialzation. Singleton EJBs (introduced in EJB 3.1)
were enriched with @Startup and @DependsOn annotations which has ensured that they
don't lag behind their pooled counterparts. Some of the common use cases include
bootstrapping global configurations, initializing expensive resources etc.
These annotations are meant for usage with Singleton beans only
@Startup
This annotation marks a Singleton bean for initialization during application startup i.e. the
container automatically creates an instance of the bean when the application initializes. This
offers the advantage of being able to invoke business logic in an eager and automated
fashion (without any manual intervention). One can conveniently leverage the
@PostConstruct call back method to execute the bootstrapping logic and also use
43
Eager Initialization
package ejbap.eagerinit;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Singleton;
import javax.ejb.Startup;
@Singleton
@Startup
public class AppConfigInitBean {
@PostConstruct
public void init() {
configuration = UUID.randomUUID().toString();
System.out.println("Configuration bootstrapped -- " + configuration);
}
@PreDestroy
public void destroy() {
System.out.println("Destroying configuration -- " + configuration);
configuration = null;
}
It's important to bear in mind that, in the absence of this annotation, a Singleton EJB is
instantiated by the container when it is first used/invoked by the client
@DependsOn
Just like @Startup , the @DependsOn annotation is tied to Singleton EJBs. As the name
suggests, this annotation is used to establish dependencies between different Singleton
beans.
44
Eager Initialization
package ejbap.eagerinit;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.DependsOn;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
@Singleton
@Startup
@DependsOn("AppConfigInitBean")
public class DependentSingleton {
@Inject
private AppConfigInitBean appConfig;
@PostConstruct
public void init() {
System.out.println("Singleton is ready for use");
System.out.println("Configuration: "+appConfig.getConfig());
}
@PreDestroy
public void destroy() {
//Presence of 'AppConfigInitBean' instance is confirmed
System.out.println("Time to disappear!");
}
}
One can specify multiple dependent Singleton beans as a part of this annotation. Declaring
a dependency on one or multiple Singleton bean(s) ensures that the container
Initializes the dependent beans prior to conclusion of the setup process of the singleton
(before invocation of its @PostConstruct method)
Guarantees the presence of dependent bean instances before the destruction of the
singleton bean instance (before completion of its @PreDestroy method)
Next up ...
Let's dive into some of the scheduler and timer related features which EJBs offer...
45
Schedulers & Timers
@Schedule
This annotation is used to designate a method as a target for a timed call back i.e. the EJB
container invokes this method as per configuration/metadata provided in this annotation.
package ejbap.schedule;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.ejb.Timer;
@Stateless
public class ScheduledReportingService {
@Schedule
public void generateAuditReport(){
System.out.println("Generating audit report....");
}
/**
* A Timer instance is injected
* automatically by the container
*/
@Schedule
public void generateSalesReport(Timer timer){
System.out.println("Generating Sales report....");
System.out.println("Next execution on - "+ timer.getNextTimeout());
}
}
Please note that, in the above example, the @Schedule annotation is not configured
with the schedule frequency. In such a scenario, the EJB container invokes (by default)
the annotated method on a daily basis (at midnight)
46
Schedulers & Timers
and combinations are available as far the scheduling configurations are concerned. The
syntax is so rich that it is not possible to enumerate all the possible combinations. Here are a
few selective examples
package ejbap.schedule;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
@Stateless
public class SchedulerConfigurationExamples {
//every 10 minutes
@Schedule(minute="*/10", hour="*")
public void dbHealthCheck(){
//logic
}
@Schedules
This annotation is to be used when you want to impose/declare multiple timers scheduling
options to single method. All it does it accept multiple (an array) of @Schedule annotations
47
Schedulers & Timers
package ejbap.schedule;
import javax.ejb.Schedule;
import javax.ejb.Schedules;
import javax.ejb.Stateless;
@Stateless
public class MultipleSchedules {
@Schedules({
//1 AM on Monday
@Schedule(hour="1", dayOfWeek="Mon"),
//2:30 AM on Friday
@Schedule(hour="2", minute = "30", dayOfWeek="Fri")
})
public void generateAuditReport(){
System.out.println("Generating audit report....");
}
This is useful if you do not want to declare different methods for different timer configurations
(although it's perfectly legal to do so)
Timer persistence
Timers are persistent by default i.e. their state is persisted in case the application
terminates. One can toggle this using the persistent property in the @Schedule
annotation
@Timeout
This annotation is useful when you want to adopt a programmatic way of working with timers
rather than configuring them in declarative fashion using the annotations mentioned above.
@Timeout is used a marker for the EJB container to be able to determine the trigger point
which can be invoked when the timer expires. The method annotated with @Timeout
contains the actual logic which you want to execute as part of your scheduled operation
If you compare this with @Schedule , the major difference you would notice is that @Timeout
does not allow declarative configuration via annotation elements
48
Schedulers & Timers
package ejbap.schedule;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
@Stateless
public class SimpleProgrammaticTimer {
@Resource
private TimerService ejbTimerSvc;
@Timeout
public void onTimeout(Timer timer){
System.out.println("Event details: "+ timer.getInfo());
Since this annotation does not allow timer/scheduler configuration, it is used in conjunction
with the javax.ejb.TimerService API which helps you create timers on the fly. It's helper
method let you specify the timers in terms of duration, exact trigger date etc. as well as ad-
hoc schedules (similar to what @Schedule offers) using the javax.ejb.ScheduleExpression
class
49
Schedulers & Timers
package ejbap.schedule;
import javax.annotation.Resource;
import javax.ejb.ScheduleExpression;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerService;
@Stateless
public class CalendarBasedProgrammaticTimer {
@Resource
private TimerService ejbTimerService;
@Timeout
public void onTimeout(Timer timer) {
System.out.println("Timer schedule: " + timer.getSchedule());
}
}
What's next ??
Next, we'll look at EJBs in their Web Service avatar !
50
Web Services support
@Path
@WebService
@Path and @WebService are not a part of the EJB specification. They belong to JSR
@WebService
The real beauty lies in the fact that session beans can be decorated with this annotation and
the EJB container automagically exposes their functionality as SOAP based web services.
package ejbap.ws;
import java.util.Date;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@Stateless
@WebService
public class EJBasSOAPWebService {
@WebMethod
public String getDate(){
return new Date().toString();
}
@WebMethod
@WebResult(name = "response")
public String greet(@WebParam String greeting){
return greeting + " World !";
}
}
51
Web Services support
As you might have already noticed in the above example, JSR 181 exposes other
annotations like @WebMethod , @WebResult , @WebParam etc. to help further refine your web
service methods.
In order to gain more flexibility and ease of extension, a better approach would be to
provide a layer of indirection with the help of an additional session bean
@Path
REST web services cannot lag behind SOAP. Can they ! Java EE provides you the ability to
use the @Path annotation to expose session beans over a RESTful interface. I guess you
have already realized that the idea is not very different compared to the SOAP based web
service interface approach.
package ejbap.ws;
import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
@Stateless
@Path("test")
public class EJBonREST {
@GET
public String get(@QueryParam("name") String propName){
return System.getProperty(propName);
}
@POST
public String greet(final String greeting){
return greeting + " World !";
}
52
Web Services support
Avoid coupling b/w your EJB and RESTful interface by introducing another layer of
abstraction/facade
Continue to enrich your EJB methods with additional annotations from the JAX-RS
API e.g. @PUT , @DELETE , @PathParam etc.
Up ahead...
The next chapter covers exception handling and its one and only annotation
53
Exception Handling
Exception Handling
Before exploring exception related annotation (just one!), let's first understand the basic
types of exceptions defined by the EJB specification
System Exceptions
Application Exceptions
System Exceptions
As per the EJB specification, a System exception is defined by the following criteria
System Exceptions are to EJBs what Errors are to the Java language. They help deal
with scenarios where the issue should be propagated to the EJB container rather than
handling it within the application itself.
The EJB container defines standard mechanism or pathways which are followed when a
System application is thrown e.g. rolling back the transaction.
Application Exceptions
By design, Application Exceptions are meant to expressing business specific error scenarios
and they can be propagated to the caller. Application Exceptions can be modelled as both
checked and unchecked exceptions. An EJB can throw a checked exception and declare it
in the throws clause. In case you want to model your application exception as an unchecked
(RuntimeException) exception (here is where the @ApplicationException annotation comes
into the picture)
@ApplicationException
If an exception extends RuntimeException, then you have to use this annotation so that the
EJB container treats it as an Application Exception. Failure to use this will result in your
exception being interpreted as a System Exception (which is handled differently)
54
Exception Handling
package ejbap.exceptions;
package ejbap.exceptions;
import javax.ejb.ApplicationException;
@ApplicationException
public class BookNotFoundException extends RuntimeException{
//details ommitted
}
Rollback semantics
By default, the container does not roll back the transaction as a result of an
Application exception. You can toggle the annotation property to refine this as per your
business requirements.
package ejbap.exceptions;
import javax.ejb.ApplicationException;
@ApplicationException(rollback = true)
public class UpdateException extends RuntimeException{
//details ommitted
}
55
Exception Handling
For optimum performance under heavy loads, you would want to have as many MDBs
in the pool as possible. In such a case you would want to avoid MDB instances being
destroyed due to excpetions. Sensible exception handling can help you realize this
goal. It is simple as annotating your exception class with @ApplicationException and
leaving the rest to the container
Moving on...
Let's explore the security related annotations and how they can help secure EJBs
56
Security
Security
All the annotations in this section belong to the Common Annotations specification. The EJB
specification defines their expected behaviour implements these annotations in a way that
they are honoured at runtime.
@DeclareRoles
As the name itself indicates, this Class level annotation is used to declare a list of roles
available for use by an EJB. Specifically, it comes into picture when programmatic (API
based) authorization check is initiated by the javax.ejb.EJBContext.isCallerInRole(String
role) method
package ejbap.security;
import java.math.BigDecimal;
import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.ejb.EJBContext;
import javax.ejb.Stateless;
@DeclareRoles({"admin"})
@Stateless
public class AdminOperationsFacade {
@Resource
private EJBContext ejbCtx;
@RolesAllowed
This annotation can be used on classes, individual methods or both. It specifies one or more
roles which are permitted to invoke bean methods. In case the annotation is used on both
class and individual methods of the bean class, the method level annotation takes
precedence
57
Security
@PermitAll
@PermitAll can be used on both class and individual methods. If applied on a class, this
annotation allows all its methods to be executed without any restrictions unless a method is
explicitly annotated using @RolesAllowed
@DenyAll
This can be applied on a class or on specific methods. It instructs the container to forbid
execution of the particular method guarded by this annotation. Please note that the method
can still be used internally within the bean class
package ejbap.security;
import java.math.BigDecimal;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.DenyAll;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;
@Stateless
@DeclareRoles({"Administrators", "HR , Managers"})
@RolesAllowed({"Managers"})
public class EmployeeManagementFacade {
@RolesAllowed({"HR"})
public void updateSalary(BigDecimal salary){
//only 'HR'
}
@PermitAll
public String getEmailAddress(String empID){
//no authorization needed
String address = null;
//logic..
return address;
}
@DenyAll
public void deleteEmployeeRecord(int id){
//external access blocked
}
}
58
Security
@RunAs
The use of this annotation helps impersonate a user identity (on purpose) i.e. it allows a
bean method to be invoked via a specific role by explicitly mentioning the same. This
annotation can only be used on a class and is implicitly enforced on all the its methods
Authentication or Authorization ?
It is extremely important to understand that these annotations are meant for Authorization
only i.e. they just check whether the calling entity (principal) has the privileges to execute a
specific method. The actual Authentication is carried out by a different process (generally
using Security Realms configured within the application server) and usually happens at the
Web layer (enforced by the Web Container)
Principal/Identity Propagation
Authorization (in the EJB container) is not possible without prior authentication in the
Web container. This is because, the privileges (equivalent to groups in the security
realm e.g. database, LDAP etc.) of the authentication identity (principal) are
propagated from the Web to the EJB container which then enforces authorization
checks using the annotations. This principal can be ignored/manipulated only when the
@RunAs annotation is leveraged
59
Security
authorization configurations. In fact, there might be times when it is preferable to use these
descriptors along with the annotations.
Coming up next
We shall dive into transaction related annotations ...
60
Transactions
Transactions
Transaction management is one of the key features of the EJB container. Although the
concept of transactions itself is generic in nature and applicable to wide variety of use cases,
in the Java EE (and EJB) context, transaction management related capabilities allow for a
seamless integration between EJB and other specifications such as JPA (EJBs serve as the
gateway for persistence related operations in Java EE applications), JMS etc.
@TransactionManagement
This (class level) annotation is used to convey as to who will be manage the transaction
related details - the container itself (automatic & declarative management) or the bean
developer (manual & programmatic based). It's possible values are defined by the enum
javax.ejb.TransactionManagementType
package ejbap.tx;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.transaction.UserTransaction;
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class BeanManagedTx {
@Resource
private UserTransaction uTx;
61
Transactions
@TransactionAttribute
This annotation defines the transactional semantic of the method it is applied on.
Notable aspects
javax.ejb.TransactionAttributeType defines all the possible values and what their usage
implies
REQUIRED: (default) the method executes in the caller's transaction context (if any)
REQUIRED_NEW: container starts new transaction, irrespective of the caller's
transactional context state
MANDATORY: the method needs to be invoked by the client in scope of an existing
transaction (else an exception is thrown)
NEVER: no transactional context would be associated with the method and the caller
gets an exception in case it calls the method within a transaction
NOT_SUPPORTED: an unspecified transactional context is associated with the method
SUPPORTS: the method executes in the caller's transaction context (if any) otherwise
the context is unspecified
@AfterBegin
The method decorated with this annotation is 'called-back' by the container after a
transaction starts
@BeforeCompletion
This annotation marks a method to be called just prior to completion (commit/rollback) of a
transaction.
62
Transactions
@AfterCompletion
A method decorated with this annotation is called back at the end of transactional boundary
(consisting of one or more methods). It should declare a boolean argument to accpet the
transaction status - committed (true) or rollback (false)
The methods decorated with the aforementioned annotations have a few constraints
63
Dependency & Resource Injection
Message Driven Beans (MDB) are not eligible for direct reference/injection
In case there is more than one implementation for an EJB type, the beanName element of
the @EJB annotation can be used to further narrow down the instance to be injected and it
takes into account the value of the (optional) name element in the @Stateful , @Stateless
or @Singleton bean annotation
package ejbap.di_and_ri;
import javax.ejb.Stateless;
@Stateless(name = "CSVParserBean")
public class CSVParser implements Parser{
@Override
public String parse(String file) {
return ""; //dummy
}
}
64
Dependency & Resource Injection
package ejbap.di_and_ri;
import javax.ejb.EJB;
import javax.ejb.Stateless;
@Stateless
public class CSVParsingService {
The lookup element can be used to lookup a session bean using it's global JNDI name
EJB 3.1 introduced the notion of a portable global JNDI name syntax for looking up EJB
components. This is leveraged by the lookup element. The global JNDI name syntax is
as follows:
java:global[/<app-name>]/<module-name>/<bean-name>[!<fully-qualified-interface-
name>]
There are two more portable naming conventions based on application and module
name. They have not been discussed to keep things simple
package ejbap.di_and_ri;
import javax.ejb.EJB;
@EJB(lookup = "java:global/ejbap/TimeKeeper")
TimeKeeper timeKeeper;
Either the beanName or the lookup element should be used to lookup session beans.
It is illegal to use them together
In addition to existing EJBs, Servlets and JSF Managed Beans can also use this annotation
to lookup/inject other session bean references
65
Dependency & Resource Injection
package ejbap.di_and_ri;
import java.io.IOException;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@EJB
TimeKeeper keeper;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try (PrintWriter out = response.getWriter()) {
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<title>Time Keeper Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("<h2>Time is " + keeper.dateTime() + "</h2>");
out.println("</body>");
out.println("</html>");
}
}
66
Dependency & Resource Injection
package ejbap.di_and_ri;
import javax.annotation.ManagedBean;
import javax.ejb.EJB;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class TimeKeeperJSFController {
@EJB
TimeKeeper keeper;
@EJBs
This annotation is used to bind multiple EJB references to the JNDI naming context which
you can later refer to by searching the JNDI tree again. Please note that this annotation is
applicable to a class only
67
Dependency & Resource Injection
package ejbap.di_and_ri;
import javax.ejb.EJB;
import javax.ejb.EJBs;
import javax.ejb.Stateless;
import javax.naming.InitialContext;
import javax.naming.NamingException;
@Stateless
@EJBs({
@EJB(name = "CSVParserEJB", beanInterface = Parser.class, beanName = "CSVParser"),
@EJB(name = "XMLParserEJB", beanInterface = Parser.class, beanName = "XMLParser")
})
public class MultipleEJBReferences {
@Resource
This is more of a general purpose annotation used to declare a required resource and is
applicable to methods, fields as well as a class. Please note that the usage of this
annotation is not restricted to EJBs alone - all Managed Beans (which is almost every bean
out there) can leverage its capabilities
Just like @EJB , @Resource also has additional elements: name, type, mappedName,
lookup, description, authenticationType, shareable
68
Dependency & Resource Injection
package ejbap.di_and_ri;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
@Singleton
@Startup
public class ResourcefulBean {
@Resource
ConnectionFactory jmsCF;
@Resource
Destination jmsDestination;
@Resource
TimerService ejbTs;
@PostConstruct
public void setUp(){
ejbTs.createSingleActionTimer(10000, new TimerConfig());
}
@Timeout
public void onTimeout(){
jmsCF.createContext().createProducer().send(jmsDestination, "a new message tri
ggered by timer");
}
}
69
Dependency & Resource Injection
the class usage means that the dependent resource will be accessed at runtime
field/method usage implies that the resource injection will take place during
application initialization
@Resources
declare multiple dependent resources. This is because of the fact that prior to Java SE 8,
multiple annotations on an element were not possible. I am sure things will be refactored in
Java EE 8 which will (most probably) have Java 8 as a mandatory requirement
package ejbap.di_and_ri;
import javax.annotation.Resource;
import javax.annotation.Resources;
import javax.ejb.Stateless;
import javax.enterprise.concurrent.ManagedExecutorService;
import javax.sql.DataSource;
@Stateless
@Resources({
@Resource(lookup="java:comp/DefaultManagedExecutorService",
type = ManagedExecutorService.class),
@Resource(lookup = "java:comp/DefaultDataSource" ,
type = DataSource.class)
})
public class MultipleResources {
70
Dependency & Resource Injection
EJB, CDI, their differences, similarities and relationships are topics which are not
covered in depth
@Inject
This CDI annotation is a powerful, general purpose and type safe injection construct. During
container bootstrap, CDI container makes use of a process called Type Safe Resolution in
order to validate whether or not there are beans which satisfy the injection points (else the
application deployment is aborted). The CDI specification also offers other components like
Qualifiers (default & custom), Alternatives etc. which complement @Inject
only. Although, @Resource can be thought of as a more general purpose DI mechanism, CDI
is more powerful and in fact works very well in tandem with @Resource (via CDI Producers)
Stateless beans can only belong to the @Dependent scope i.e. you can either choose to
use the @Dependent pseudo-scope explicitly or just flow with the @Stateless annotation
in which case the CDI container will pretty much use @Dependent by default
(convention).
With Singleton beans, @ApplicationScoped is the only valid CDI scope ( @Dependent is
the default in case you do not use any other explicit CDI scope)
Stateful EJBs can have any scope – no restrictions whatsoever!
Unless you are using refined versions of @EJB , @Inject can pretty much be a drop in
replacement for injecting session beans and should work seamlessly
Support for @Inject within session beans is supported by the specification. The basic
CDI rules apply here as well
71
Dependency & Resource Injection
Let's move on
... and explore the different views which session beans expose to their clients.
72
Heterogeneous Interfaces
Heterogeneous views
This chapter deals with different views which which EJBs can expose to their prospective
clients. These are as follows
Local
Remote
No-interface
Web service
Web Service
This is typically in the form of a SOAP or REST web service. For further details, please refer
to the Web Services support chapter
@Local
This annotation can be used on a session bean interface or the bean implementation class
itself - either ways, it makes the session bean available to clients in the same JVM.
The container exchanges instances of these beans by reference (within the same
JVM). Hence Local session bean interfaces tend to be more efficient when compared to
their remote ( @Remote ) counterparts (discussed soon)
Default
EJB implements an interface (without using @Local ). The container applies local bean
semantics by default
73
Heterogeneous Interfaces
package ejbap.views.local.interfaces;
import java.util.Date;
The implementation
package ejbap.views.local;
import ejbap.views.local.interfaces.GithubAPIInterface;
import java.util.Date;
import javax.ejb.Stateless;
@Stateless
//Local view assumed by default
public class GithubRestAPIImpl implements GithubAPIInterface {
@Override
public Date getLastUpdated(String repoID) {
return new Date(); //updated today !
}
@Override
public int getStars(String repoID) {
return 42;
}
@Override
public int getForks(String repoID) {
return 42;
}
74
Heterogeneous Interfaces
package ejbap.views.local.interfaces;
import javax.ejb.Local;
@Local
public interface TimerServiceInterface {
public String getTime();
}
package ejbap.views.local;
import ejbap.views.local.interfaces.TimerServiceInterface;
import java.util.Date;
import javax.ejb.Stateless;
@Stateless
public class TimerServiceBean implements TimerServiceInterface {
@Override
public String getTime() {
return new Date().toString();
}
package ejbap.views.local.interfaces;
75
Heterogeneous Interfaces
package ejbap.views.local;
import ejbap.views.local.interfaces.UserRepositoryInterface;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
@Local(UserRepositoryInterface.class)
public class DBUserRepository implements UserRepositoryInterface {
@PersistenceContext
private EntityManager em;
@Override
public String getUserFirstName(String id) {
//use EM
return "";
}
@Override
public String getUserEmail(String id) {
//use EM
return "";
}
EJB does not implement the interface but designates it as its local view
package ejbap.views.local.interfaces;
76
Heterogeneous Interfaces
package ejbap.views.local;
import ejbap.views.local.interfaces.TweeterInterface;
import javax.ejb.Local;
import javax.ejb.Stateless;
@Stateless
@Local(TweeterInterface.class)
public class TwitterJavaAPIBasedImpl {
@Remote
This annotation is also applicable for a session bean interface or the bean implementation
class itself. It makes the session bean available to clients outside the JVM in which it is
deployed
The container exchanges instances of these beans by value i.e. communication using
remote EJB views requires serialization (of method parameters and return types)
@LocalBean
The usage of the @LocalBean annotation is synonymous with the no-interface view which
means that the EJB does not implement any interfaces.
77
Heterogeneous Interfaces
package ejbap.views.nointerface;
import java.util.Date;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
@LocalBean //does not make a difference
public class AttachmentManagerBean {
@PersistenceContext
private EntityManager em;
Why is this even required ? Why not leave the bean alone (with just the
@Stateless annotation) ?
the no-interface view needs to co-exist with other views which a session bean
might expose
in case it implements another interface(s) which are not remote/local views
package ejbap.views.nointerface.interfaces;
78
Heterogeneous Interfaces
package ejbap.views.nointerface;
import ejbap.views.nointerface.interfaces.WorkflowManagementInterface;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@Stateless
@LocalBean
public class WorkflowMangementSessionFacade implements WorkflowManagementInterface {
@Override
public void trigger() {
//logic...
}
@Override
public String getCurrentAssigne(String workflowID) {
return "42";
}
@Override
public boolean isComplete(String workflowID) {
return true;
}
@Override
public int getStatus(String workflowID) {
return 42;
}
@LocalHome
This annotation acts as a bridge b/w EJB 3.x and 2.x style session beans i.e. it can help 3.x
session beans to be compatible with clients of EJB 2.1 (and before) session beans (since it
was mandatory for beans to have home interfaces)
@RemoteHome
This is the remote equivalent of the @LocalHome annotation. It helps remote EJB 3.x beans
adapt to EJB 2.1 style beans which previously required the existence of home interfaces
@Init
79
Heterogeneous Interfaces
This annotation is applied on a method is only required for stateful session beans that
provide an adapted remote/local home interface (using @RemoteHome or @LocalHome
annotations discussed above)
80
References, resources & hello!
Useful books
Below are some of the books I highly recommend
There are a bunch of other resources which I have collated as a part of my Java EE 7
dedicated page on ZEEF. It has been some time since I updated it (because there is
just too much happening in the Java EE world), but I still feel that you should check it
out at least once
Hello World !
This is not a goodbye, rather, it's a hello. Why ? Because I feel this is just the beginning.
Continue enjoying Java EE and EJBs !
My Blog
Twitter
Linkedin
Github
81