Table of Contents
- Table of Contents
- Getting Started
- Feature Overview
- Exception Handling
- Security Module
- JPA Module
- CdiControl Module
DeltaSpike Module Overview
Annotated Type Builder
DeltaSpike provides an
AnnotatedType implementation (and corresponding implementations of the suite of Annotated interfaces from CDI) that should be suitable for the needs of most portable extensions. The
AnnotatedType is created from
AnnotatedTypeBuilder, typically in an extension's observer method, as follows:
In the example above we create a new builder, and initialize it using an existing
AnnotatedType. We can then add or remove annotations from the class, and its members. When we have finished modifying the type, we call
#create() to spit out a new, immutable,
AnnotatedType. In the example
@Named gets replaced if the bean-name doesn't start with a lower case character.
NamedLiteral takes the new value which should be used for the new instance of
@Named. That means if a class is annotated e.g. with
@Named("MyBean") it will be replaced with
@Named("myBean") during the bootstrapping process.
AnnotatedTypeBuilder provides the following methods:
DeltaSpike has the ability, with the AnnotationInstanceProvider class, to dynamically create instances of annotations. These are useful for adding annotations to bean metadata in extensions, adding qualifiers to events, etc. Usage is very simple and straight forward. There are two public methods:
of(Class<T extends Annotation>) and
of(Class<T extends Annotation>, Map<String, ?>). The first is simply a short cut passing an empty map to the second. The map parameter is a map of values to be used for the members of the annotation. The keys in the map must be the names of members in the annotation (i.e. value, type, etc.). Simple usages are below.
AnnotationInstanceProvider provides an implementation of equals, hashCode and toString compliant with the javadocs for Annotation. It also caches the instances for the duration of the application. Creating a new instance of the same class and same member values will yield the same instance as before.
DeltaSpikeConfig (CDI based config)
This interface is a marker interface for all type-safe configs which allows to find those configs easily within the IDE without knowing further details as well as with a programmatic lookup e.g.
Type-safe configs are just normal classes (application scoped CDI beans) and custom values can be provided by extending the config/class in question, annotate it with the std. CDI annotation
@Specializes and override the corresponding getter method which provides the default value.
Exception handling in DeltaSpike is based around the CDI eventing model. While
the implementation of exception handlers may not be the same as a CDI event, and
the programming model is not exactly the same as specifying a CDI event /
observer, the concepts are very similar. DeltaSpike makes use of events for many of
its features. Eventing is actually the only way to start using DeltaSpike's
This event is fired either by the application or a DeltaSpike exception handling integration. DeltaSpike then hands the exception off to a
chain of registered handlers, which deal with the exception appropriately. The use of CDI events to connect
exceptions to handlers makes this strategy of exception handling non-invasive and minimally coupled to the exception handling
The exception handling process remains mostly transparent to the developer. In most cases, you register an
exception handler simply by annotating a handler method. Alternatively, you can handle an exception
programmatically, just as you would observe an event in CDI.
Exception Handling - Usage
Eventing into the exception handling framework
The entire exception handling process starts with an event. This helps keep your application minimally coupled to
DeltaSpike, but also allows for further extension. Exception handling in DeltaSpike is all about letting you take care of
exceptions the way that makes the most sense for your application. Events provide this delicate balance. Firing the event
is the main way of starting the exception handling proccess.
Manually firing an event to use DeltaSpike's exception handling is primarily used in your own try/catch blocks. It's very
painless and also easy. Let's examine a sample that might exist inside of a simple business logic lookup
into an inventory database:
Event of generic type
ExceptionToCatchEvent is injected into
your class for use later within a try/catch block.
The event is fired with a new instance of
ExceptionToCatchEvent constructed with the
exception to be handled.
As an application developer (i.e., an end user of DeltaSpike's exception handling), you'll be focused on writing exception handlers. An
exception handler is a method on a CDI bean that is invoked to handle a specific type of exception. Within that
method, you can implement any logic necessary to handle or respond to the exception.
Given that exception handler beans are CDI beans, they can make use of dependency injection, be scoped, have
interceptors or decorators and any other functionality available to CDI beans.
Exception handler methods are designed to follow the syntax and semantics of CDI observers, with some special
purpose exceptions explained in this guide. The advantage of this design is that exception handlers will be
immediately familiar to you if you are studying or well-versed in CDI.
In this and subsequent sections, you'll learn how to define an exception handler, explore how and when it gets invoked, modify
an exception and a stack trace, and even extend exception handling further through events that are fired during the handling
workflow. We'll begin by covering the two annotations that are used to declare an exception handler,
@BeforeHandles to create a callback before the handler is called.
Exception handler annotations
Exception handlers are contained within exception handler beans, which are CDI beans annotated with
@ExceptionHandler. Exception handlers are methods which have a parameter which is an
ExceptionEvent<T extends Throwable> annotated with the
@ExceptionHandler annotation is simply a marker annotation that instructs the DeltaSpike
exception handling CDI extension to scan the bean for handler methods.
Let's designate a CDI bean as an exception handler by annotating it with
That's all there is to it. Now we can begin defining exception handling methods on this bean.
@Handles is a method parameter annotation that designates a method as an exception
handler. Exception handler methods are registered on beans annotated with
@ExceptionHandler. DeltaSpike will discover all such methods at deployment time.
Let's look at an example. The following method is invoked for every exception that DeltaSpike processes and
prints the exception message to stdout. (
Throwable is the base exception type in Java and
thus represents all exceptions).
@Handles annotation on the first parameter designates this method as an
exception handler (though it is not required to be the first parameter). This parameter must be
ExceptionEvent<T extends Throwable>, otherwise it's detected as
a definition error. The type parameter designates which exception the method should handle. This
method is notified of all exceptions (requested by the base exception type
ExceptionEvent instance provides access to information about the exception
and can be used to control exception handling flow. In this case, it's used to read the current
exception being handled in the exception chain, as returned by
This handler does not modify the invocation of subsequent handlers, as designated by invoking
ExceptionEvent. As this is the default behavior,
this line could be omitted.
@Handles annotation must be placed on a parameter of the method, which must
be of type
ExceptionEvent<T extends Throwable>. Handler methods are similar to CDI
observers and, as such, follow the same principles and guidelines as observers (such as invocation,
injection of parameters, qualifiers, etc) with the following exceptions:
- a parameter of a handler method must be a
- handlers are ordered before they are invoked (invocation order of observers is non-deterministic)
- any handler can prevent subsequent handlers from being invoked
In addition to designating a method as exception handler, the
annotation specifies an
ordinal about when the method should be invoked relative to other
handler methods of the same type. Handlers with higher ordinal are
invoked before handlers with a lower ordinal that handle the same exception type. The default
ordinal (if not specified) is 0.
@BeforeHandles designates a method as a callback to happen before handlers are called.
Let's take a look at more sophisticated example that uses all the features of handlers to log all
This handler has a default ordinal of 0 (the default value of the ordinal attribute on
This handler is qualified with
@WebRequest. When DeltaSpike calculates the handler
chain, it filters handlers based on the exception type and qualifiers. This handler will only be
invoked for exceptions passed to DeltaSpike that carry the
We'll assume this qualifier distinguishes a web page request from a REST request.
Any additional parameters of a handler method are treated as injection points. These parameters are
injected into the handler when it is invoked by DeltaSpike. In this case, we are injecting a
Logger bean that must be defined within the application (or by an extension).
A handler is guaranteed to only be invoked once per exception (automatically muted), unless it re-enables
itself by invoking the
unmute() method on the
Handlers must not throw checked exceptions, and should avoid throwing unchecked exceptions. Should a handler
throw an unchecked exception it will propagate up the stack and all handling done via DeltaSpike will cease. Any
exception that was being handled will be lost.
Exception Chain Processing
When an exception is thrown, chances are it's nested (wrapped) inside other exceptions. (If you've ever
examined a server log, you'll appreciate this fact). The collection of exceptions in its entirety is termed an
The outermost exception of an exception chain (e.g., EJBException, ServletException, etc) is probably of
little use to exception handlers. That's why DeltaSpike doesn't simply pass the exception chain directly to
the exception handlers. Instead, it intelligently unwraps the chain and treats the root exception cause
as the primary exception.
The first exception handlers to be invoked by DeltaSpike are those that match the type of root cause. Thus, instead
of seeing a vague
EJBException, your handlers will instead see an meaningful exception such
This feature, alone, makes DeltaSpike's exception handling a worthwhile tool.
DeltaSpike continues to work through the exception chain, notifying handlers of each exception in the stack,
until a handler flags the exception as handled or the whole exception chain has been iterated. Once an exception is marked as handled, DeltaSpike stops processing
the exception chain. If a handler instructs DeltaSpike to rethrow the exception (by invoking
ExceptionEvent#throwOriginal(), DeltaSpike will rethrow the exception outside the DeltaSpike exception handling
infrastructure. Otherwise, it simply returns flow control to the caller.
Consider a exception chain containing the following nested causes (from outer cause to root cause):
DeltaSpike will unwrap this exception and notify handlers in the following order:
If there's a handler for
PersistenceException, it will likely prevent the handlers for
EJBException from being invoked, which is a good thing since what useful information can
really be obtained from
When DeltaSpike finds more than one handler for the same exception type, it orders the handlers by ordinal.
Handlers with higher ordinal are executed before handlers with a lower ordinal. If DeltaSpike detects two
handlers for the same type with the same ordinal, the order is non-deterministic.
Let's define two handlers with different ordinals:
The first method is invoked first since it has a higher ordinal (100) than the second method, which has
the default ordinal (0).
To summarize, here's how DeltaSpike determines the order of handlers to invoke (until a handler marks exception as
- Unwrap exception stack
- Begin processing root cause
- Invoke any callback methods annotated with @BeforeHandles for the closest type to the exception
- Find handler for the closest type to the exception
- If multiple handlers for same type, invoke handlers with higher ordinal first
- Continue above steps for each exception in stack
APIs for exception information and flow control
There are two APIs provided by DeltaSpike that should be familiar to application developers:
In addition to providing information about the exception being handled, the
ExceptionEvent object contains methods to control the exception handling process, such
as rethrowing the exception, aborting the handler chain or unmuting the current handler.
Five methods exist on the
ExceptionEvent object to give flow control to the handler
abort()- terminate all handling immediately after this handler, does not mark the exception as handled, does not re-throw the exception.
throwOriginal()- continues through all handlers, but once all handlers have been called (assuming another handler does not call abort() or handled()) the initial exception passed to DeltaSpike is rethrown. Does not mark the exception as handled.
handled()- marks the exception as handled and terminates further handling.
handleAndContinue()- default. Marks the exception as handled and proceeds with the rest of the handlers.
skipCause()- marks the exception as handled, but proceeds to the next cause in the cause container, without calling other handlers for the current cause.
rethrow(Throwable)- Throw a new exception after this handler is invoked
Once a handler is invoked it is muted, meaning it will not be run again for that exception chain,
unless it's explicitly marked as unmuted via the
unmute() method on