You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by bu...@apache.org on 2013/01/02 21:15:41 UTC

svn commit: r844654 - in /websites/staging/deltaspike/trunk/content: ./ deltaspike/core.html

Author: buildbot
Date: Wed Jan  2 20:15:41 2013
New Revision: 844654

Log:
Staging update by buildbot for deltaspike

Modified:
    websites/staging/deltaspike/trunk/content/   (props changed)
    websites/staging/deltaspike/trunk/content/deltaspike/core.html

Propchange: websites/staging/deltaspike/trunk/content/
------------------------------------------------------------------------------
--- cms:source-revision (original)
+++ cms:source-revision Wed Jan  2 20:15:41 2013
@@ -1 +1 @@
-1427879
+1427992

Modified: websites/staging/deltaspike/trunk/content/deltaspike/core.html
==============================================================================
--- websites/staging/deltaspike/trunk/content/deltaspike/core.html (original)
+++ websites/staging/deltaspike/trunk/content/deltaspike/core.html Wed Jan  2 20:15:41 2013
@@ -359,7 +359,289 @@ For such cases a custom ExpressionInterp
 <h2 id="i18n">I18n</h2>
 <p>TODO</p>
 <h2 id="exception-control">Exception Control</h2>
-<p>TODO (Overview)</p>
+<p>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 exception handling.</p>
+<p>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
+infrastructure.</p>
+<p>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.</p>
+<h2 id="exception-handling-usage">Exception Handling - Usage</h2>
+<h3 id="eventing-into-the-exception-handling-framework">Eventing into the exception handling framework</h3>
+<p>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.</p>
+<p>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:</p>
+<div class="codehilite"><pre><span class="n">public</span> <span class="n">class</span> <span class="n">InventoryActions</span> <span class="p">{</span>
+    <span class="nv">@PersistenceContext</span> <span class="n">private</span> <span class="n">EntityManager</span> <span class="n">em</span><span class="p">;</span>
+    <span class="nv">@Inject</span> <span class="n">private</span> <span class="n">Event</span><span class="sr">&lt;ExceptionToCatchEvent&gt;</span> <span class="n">catchEvent</span><span class="p">;</span>
+
+    <span class="n">public</span> <span class="n">Integer</span> <span class="n">queryForItem</span><span class="p">(</span><span class="n">Item</span> <span class="n">item</span><span class="p">)</span> <span class="p">{</span>
+        <span class="n">try</span> <span class="p">{</span>
+          <span class="n">Query</span> <span class="sx">q = </span><span class="n">em</span><span class="o">.</span><span class="n">createQuery</span><span class="p">(</span><span class="s">&quot;SELECT i from Item i where i.id = :id&quot;</span><span class="p">);</span>
+          <span class="sx">q.setParameter(&quot;id&quot;, item.</span><span class="n">getId</span><span class="p">());</span>
+          <span class="k">return</span> <span class="sx">q.getSingleResult();</span>
+<span class="sx">        } catch (PersistenceException e) {</span>
+<span class="sx">          catchEvent.</span><span class="n">fire</span><span class="p">(</span><span class="k">new</span> <span class="n">ExceptionToCatchEvent</span><span class="p">(</span><span class="n">e</span><span class="p">));</span>
+        <span class="p">}</span>
+    <span class="p">}</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>The <code>Event</code> of generic type <code>ExceptionToCatchEvent</code> is injected into your
+class for use later within a try/catch block.</p>
+<p>The event is fired with a new instance of <code>ExceptionToCatchEvent</code> constructed
+with the exception to be handled.</p>
+<h2 id="exception-handlers">Exception handlers</h2>
+<p>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.</p>
+<p><strong>If there are no exception handlers for an exception, the exception is
+rethrown.</strong></p>
+<p>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.</p>
+<p>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.</p>
+<p>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, <code>@ExceptionHandler</code> and
+<code>@Handles</code>, and <code>@BeforeHandles</code> to create a callback before the handler is
+called.</p>
+<h3 id="exception-handler-annotations">Exception handler annotations</h3>
+<p>Exception handlers are contained within exception handler beans, which are CDI
+beans annotated with <code>@ExceptionHandler</code>. Exception handlers are methods
+which have a parameter which is an instance of <code>ExceptionEvent&lt;T extends
+Throwable&gt;</code> annotated with the <code>@Handles</code> annotation.</p>
+<h4 id="exceptionhandler"><code>@ExceptionHandler</code></h4>
+<p>The <code>@ExceptionHandler</code> annotation is simply a marker annotation that
+instructs the DeltaSpike exception handling CDI extension to scan the bean for
+handler methods.</p>
+<p>Let's designate a CDI bean as an exception handler by annotating it with
+<code>@ExceptionHandler</code>.</p>
+<div class="codehilite"><pre><span class="nv">@ExceptionHandler</span>
+<span class="n">public</span> <span class="n">class</span> <span class="n">MyHandlers</span> <span class="p">{}</span>
+</pre></div>
+
+
+<p>That's all there is to it. Now we can begin defining exception handling methods on this bean.</p>
+<h4 id="handles-and-beforehandles"><code>@Handles</code> and <code>@BeforeHandles</code></h4>
+<p><code>@Handles</code> is a method parameter annotation that designates a method as an
+exception handler. Exception handler methods are registered on beans annotated
+with <code>@ExceptionHandler</code>. DeltaSpike will discover all such methods at
+deployment time.</p>
+<p>Let's look at an example. The following method is invoked for every exception
+that DeltaSpike processes and prints the exception message to stdout.
+(<code>Throwable</code> is the base exception type in Java and thus represents all
+exceptions).</p>
+<div class="codehilite"><pre><span class="nv">@ExceptionHandler</span>
+<span class="n">public</span> <span class="n">class</span> <span class="n">MyHandlers</span>
+<span class="p">{</span>
+    <span class="n">void</span> <span class="n">printExceptions</span><span class="p">(</span><span class="nv">@Handles</span> <span class="n">ExceptionEvent</span><span class="sr">&lt;Throwable&gt;</span> <span class="n">evt</span><span class="p">)</span>
+    <span class="p">{</span>
+        <span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span><span class="s">&quot;Something bad happened:&quot;</span> <span class="o">+</span>
+        <span class="n">evt</span><span class="o">.</span><span class="n">getException</span><span class="p">()</span><span class="o">.</span><span class="n">getMessage</span><span class="p">());</span>
+        <span class="n">evt</span><span class="o">.</span><span class="n">handleAndContinue</span><span class="p">();</span>
+    <span class="p">}</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>The <code>@Handles</code> 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 of type <code>ExceptionEvent&lt;T extends Throwable&gt;</code>, 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 <code>Throwable</code>).</p>
+<p>The <code>ExceptionEvent</code> 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 <code>getException()</code>.</p>
+<p>This handler does not modify the invocation of subsequent handlers, as
+designated by invoking <code>handleAndContinue()</code> on <code>ExceptionEvent</code>. As this
+is the default behavior, this line could be omitted.</p>
+<p>The <code>@Handles</code> annotation must be placed on a parameter of the method, which
+must be of type <code>ExceptionEvent&lt;T extends Throwable&gt;</code>. 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:</p>
+<ul>
+<li>a parameter of a handler method must be a <code>ExceptionEvent</code></li>
+<li>handlers are ordered before they are invoked (invocation order of
+    observers is non-deterministic)</li>
+<li>any handler can prevent subsequent handlers from being invoked</li>
+</ul>
+<p>In addition to designating a method as exception handler, the <code>@Handles</code>
+annotation specifies an <code>ordinal</code> 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.</p>
+<p>The <code>@BeforeHandles</code> designates a method as a callback to happen before
+handlers are called.</p>
+<p>Let's take a look at more sophisticated example that uses all the features of
+handlers to log all exceptions.</p>
+<div class="codehilite"><pre><span class="nv">@ExceptionHandler</span>
+<span class="n">public</span> <span class="n">class</span> <span class="n">MyHandlers</span>
+<span class="p">{</span>
+   <span class="n">void</span> <span class="n">logExceptions</span><span class="p">(</span><span class="nv">@BeforeHandles</span> <span class="nv">@WebRequest</span> <span class="n">ExceptionEvent</span><span class="sr">&lt;Throwable&gt;</span> <span class="n">evt</span><span class="p">,</span> <span class="n">Logger</span> <span class="nb">log</span><span class="p">)</span>
+   <span class="p">{</span>
+      <span class="nb">log</span><span class="o">.</span><span class="nb">warn</span><span class="p">(</span><span class="s">&quot;Something bad happened: &quot;</span> <span class="o">+</span> <span class="n">evt</span><span class="o">.</span><span class="n">getException</span><span class="p">()</span><span class="o">.</span><span class="n">getMessage</span><span class="p">());</span>
+   <span class="p">}</span>
+
+   <span class="n">void</span> <span class="n">logExceptions</span><span class="p">(</span><span class="nv">@Handles</span> <span class="nv">@WebRequest</span> <span class="n">ExceptionEvent</span><span class="sr">&lt;Throwable&gt;</span> <span class="n">evt</span><span class="p">,</span> <span class="n">Logger</span> <span class="nb">log</span><span class="p">)</span>
+   <span class="p">{</span>
+      <span class="sr">//</span> <span class="n">possibly</span> <span class="nb">send</span> <span class="n">a</span> <span class="n">HTTP</span> <span class="n">Error</span> <span class="n">code</span>
+   <span class="p">}</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>This handler has a default ordinal of 0 (the default value of the ordinal
+attribute on <code>@Handles</code>).</p>
+<p>This handler is qualified with <code>@WebRequest</code>. 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 <code>@WebRequest</code> qualifier.  We'll assume this qualifier distinguishes
+a web page request from a REST request.</p>
+<p>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 <code>Logger</code> bean that must be
+defined within the application (or by an extension).</p>
+<p>A handler is guaranteed to only be invoked once per exception (automatically
+muted), unless it re-enables itself by invoking the <code>unmute()</code> method on the
+<code>ExceptionEvent</code> instance.</p>
+<p>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.</p>
+<h2 id="exception-chain-processing">Exception Chain Processing</h2>
+<p>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 exception
+chain.</p>
+<p>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.</p>
+<p>The first exception handlers to be invoked by DeltaSpike are those that match
+the type of root cause. Thus, instead of seeing a vague <code>EJBException</code>, your
+handlers will instead see an meaningful exception such as
+<code>ConstraintViolationException</code>.  <em>This feature, alone, makes DeltaSpike's
+exception handling a worthwhile tool.</em></p>
+<p>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
+<code>ExceptionEvent#throwOriginal()</code>, DeltaSpike will rethrow the exception
+outside the DeltaSpike exception handling infrastructure. Otherwise, it simply
+returns flow control to the caller.</p>
+<p>Consider a exception chain containing the following nested causes (from outer
+cause to root cause):</p>
+<ul>
+<li>EJBException</li>
+<li>PersistenceException</li>
+<li>SQLGrammarException</li>
+</ul>
+<p>DeltaSpike will unwrap this exception and notify handlers in the following
+order:</p>
+<ul>
+<li>SQLGrammarException</li>
+<li>PersistenceException</li>
+<li>EJBException</li>
+</ul>
+<p>If there's a handler for <code>PersistenceException</code>, it will likely prevent the
+handlers for <code>EJBException</code> from being invoked, which is a good thing since
+what useful information can really be obtained from <code>EJBException</code>?</p>
+<h2 id="handler-ordinal">Handler ordinal</h2>
+<p>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.</p>
+<p>Let's define two handlers with different ordinals:</p>
+<div class="codehilite"><pre><span class="n">void</span> <span class="n">handleIOExceptionFirst</span><span class="p">(</span><span class="nv">@Handles</span><span class="p">(</span><span class="n">ordinal</span> <span class="o">=</span> <span class="mi">100</span><span class="p">)</span> <span class="n">ExceptionEvent</span><span class="sr">&lt;IOException&gt;</span> <span class="n">evt</span><span class="p">)</span>
+<span class="p">{</span>
+   <span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span><span class="s">&quot;Invoked first&quot;</span><span class="p">);</span>
+<span class="p">}</span>
+
+<span class="n">void</span> <span class="n">handleIOExceptionSecond</span><span class="p">(</span><span class="nv">@Handles</span> <span class="n">ExceptionEvent</span><span class="sr">&lt;IOException&gt;</span> <span class="n">evt</span><span class="p">)</span>
+<span class="p">{</span>
+ <span class="n">System</span><span class="o">.</span><span class="n">out</span><span class="o">.</span><span class="n">println</span><span class="p">(</span><span class="err">“</span><span class="n">Invoked</span> <span class="n">second</span><span class="err">”</span><span class="p">);</span>
+<span class="p">}</span>
+</pre></div>
+
+
+<p>The first method is invoked first since it has a higher ordinal (100) than the
+second method, which has the default ordinal (0).</p>
+<p>To summarize, here's how DeltaSpike determines the order of handlers to invoke
+(until a handler marks exception as handled):</p>
+<ol>
+<li>Unwrap exception stack</li>
+<li>Begin processing root cause</li>
+<li>Invoke any callback methods annotated with @BeforeHandles for the
+    closest type to the exception</li>
+<li>Find handler for the closest type to the exception</li>
+<li>If multiple handlers for same type, invoke handlers with higher
+    ordinal first</li>
+<li>Continue above steps for each exception in stack</li>
+</ol>
+<h2 id="apis-for-exception-information-and-flow-control">APIs for exception information and flow control</h2>
+<p>There are two APIs provided by DeltaSpike that should be familiar to
+application developers:</p>
+<ul>
+<li><code>ExceptionEvent</code></li>
+<li><code>ExceptionStackEvent</code></li>
+</ul>
+<h3 id="exceptionevent">ExceptionEvent</h3>
+<p>In addition to providing information about the exception being handled, the
+<code>ExceptionEvent</code> 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 <code>ExceptionEvent</code>
+object to give flow control to the handler</p>
+<ul>
+<li><code>abort()</code> - terminate all handling immediately after this handler,
+    does not mark the exception as handled, does not re-throw the
+    exception.</li>
+<li><code>throwOriginal()</code> - 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.</li>
+<li><code>handled()</code> - marks the exception as handled and terminates
+    further handling.</li>
+<li><code>handleAndContinue()</code> - default. Marks the exception as handled
+    and proceeds with the rest of the handlers.</li>
+<li><code>skipCause()</code> - marks the exception as handled, but proceeds to
+    the next cause in the cause container, without calling other
+    handlers for the current cause.</li>
+<li><code>rethrow(Throwable)</code> - Throw a new exception after this handler is
+    invoked</li>
+</ul>
+<p>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
+<code>unmute()</code> method on <code>ExceptionEvent</code>.</p>
 <h2 id="scopes">Scopes</h2>
 <h1 id="core-utils">Core - Utils</h1>
 <p>TODO</p>