You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2022/08/06 17:28:51 UTC

[juneau] branch jbFixRestNpe updated: Replace @RestHook with @RestInit/etc...

This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch jbFixRestNpe
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/jbFixRestNpe by this push:
     new 3b21d86b3 Replace @RestHook with @RestInit/etc...
3b21d86b3 is described below

commit 3b21d86b325d8611e97b8a655570323a445792c3
Author: JamesBognar <ja...@salesforce.com>
AuthorDate: Sat Aug 6 13:23:17 2022 -0400

    Replace @RestHook with @RestInit/etc...
---
 .../java/org/apache/juneau/reflect/FieldInfo.java  |   2 +
 juneau-doc/docs/ReleaseNotes/6.4.0.html            |   2 +-
 .../05.jrs.LifecycleHooks.html                     |  41 +-
 .../02.jrs.JavaMethodParameters.html               |   2 +-
 .../08.juneau-rest-server/05.jrs.Marshalling.html  |   2 +-
 .../08.juneau-rest-server/12.jrs.SvlVariables.html |   2 +-
 .../08.juneau-rest-server/13.jrs.StaticFiles.html  |   3 +-
 .../16.jrs.ExecutionStatistics.html                |   2 +-
 .../18.jrs.LoggingAndDebugging.html                |   3 +-
 .../08.juneau-rest-server/22.jrs.RestContext.html  |   6 +-
 .../23.jrs.RestOpContext.html                      |   4 +-
 juneau-doc/src/main/javadoc/overview.html          |  67 +--
 .../microservice/resources/LogsResource.java       |   3 +-
 .../rest/test/client/ThirdPartyProxyResource.java  |   8 +-
 .../java/org/apache/juneau/rest/RestChildren.java  |   6 +-
 .../java/org/apache/juneau/rest/RestContext.java   | 200 ++++---
 .../java/org/apache/juneau/rest/RestOpContext.java |   4 +-
 .../java/org/apache/juneau/rest/RestSession.java   |   4 +-
 .../apache/juneau/rest/annotation/HookEvent.java   | 481 ----------------
 .../apache/juneau/rest/annotation/RestDestroy.java | 100 ++++
 ...kAnnotation.java => RestDestroyAnnotation.java} |  41 +-
 .../apache/juneau/rest/annotation/RestEndCall.java | 114 ++++
 ...kAnnotation.java => RestEndCallAnnotation.java} |  41 +-
 .../apache/juneau/rest/annotation/RestHook.java    | 125 -----
 .../apache/juneau/rest/annotation/RestInit.java    | 105 ++++
 ...HookAnnotation.java => RestInitAnnotation.java} |  41 +-
 .../juneau/rest/annotation/RestPostCall.java       | 175 ++++++
 ...Annotation.java => RestPostCallAnnotation.java} |  41 +-
 .../juneau/rest/annotation/RestPostInit.java       |  95 ++++
 ...Annotation.java => RestPostInitAnnotation.java} |  37 +-
 .../apache/juneau/rest/annotation/RestPreCall.java | 182 +++++++
 ...kAnnotation.java => RestPreCallAnnotation.java} |  41 +-
 .../juneau/rest/annotation/RestStartCall.java      | 106 ++++
 ...nnotation.java => RestStartCallAnnotation.java} |  41 +-
 .../org/apache/juneau/rest/arg/DefaultArg.java     |   1 -
 .../org/apache/juneau/rest/servlet/RestObject.java |  67 ++-
 .../apache/juneau/rest/servlet/RestServlet.java    |  61 +--
 ...n_Test.java => RestDestroyAnnotation_Test.java} |  29 +-
 ...n_Test.java => RestEndCallAnnotation_Test.java} |  29 +-
 .../juneau/rest/annotation/RestHook_Test.java      | 603 ---------------------
 ...tion_Test.java => RestInitAnnotation_Test.java} |  29 +-
 .../{Rest_Context_Test.java => RestInit_Test.java} | 135 +++--
 ..._Test.java => RestPostCallAnnotation_Test.java} |  29 +-
 ...st_Context_Test.java => RestPostCall_Test.java} | 117 ++--
 ..._Test.java => RestPostInitAnnotation_Test.java} |  34 +-
 .../juneau/rest/annotation/RestPostInit_Test.java  | 209 +++++++
 ...n_Test.java => RestPreCallAnnotation_Test.java} |  29 +-
 ...est_Context_Test.java => RestPreCall_Test.java} | 118 ++--
 ...Test.java => RestStartCallAnnotation_Test.java} |  29 +-
 ...t_Context_Test.java => RestStartCall_Test.java} | 117 ++--
 .../juneau/rest/annotation/Rest_Context_Test.java  |   8 +-
 .../Rest_DefaultRequestAttributes_Test.java        | 184 +++++++
 .../juneau/rest/annotation/Rest_Messages_Test.java |   8 +-
 53 files changed, 1899 insertions(+), 2064 deletions(-)

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
index 2abdfaa95..06be5cbf1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/FieldInfo.java
@@ -486,6 +486,7 @@ public final class FieldInfo implements Comparable<FieldInfo> {
 	 * Returns the field value on the specified object.
 	 *
 	 * @param o The object containing the field.
+	 * @param <T> The object type to retrieve.
 	 * @return The field value.
 	 * @throws BeanRuntimeException Field was not accessible or field does not belong to object.
 	 */
@@ -503,6 +504,7 @@ public final class FieldInfo implements Comparable<FieldInfo> {
 	 * Same as {@link #get(Object)} but wraps the results in an {@link Optional}.
 	 *
 	 * @param o The object containing the field.
+	 * @param <T> The object type to retrieve.
 	 * @return The field value.
 	 * @throws BeanRuntimeException Field was not accessible or field does not belong to object.
 	 */
diff --git a/juneau-doc/docs/ReleaseNotes/6.4.0.html b/juneau-doc/docs/ReleaseNotes/6.4.0.html
index 6418a73ef..c0caf253e 100644
--- a/juneau-doc/docs/ReleaseNotes/6.4.0.html
+++ b/juneau-doc/docs/ReleaseNotes/6.4.0.html
@@ -381,7 +381,7 @@
 	<ul class='spaced-list'>
 		<li>
 			Revamped and simplified servlet and REST-call lifecycle handling through new
-			{@link oajr.annotation.RestHook @RestHook} annotation.
+			{@del @RestHook} annotation.
 			<ul>
 				<li>The {@del oajr.RestServlet#init(ServletConfig)} method is now final and can
 					no longer be extended.
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/02.jrs.AnnotatedClasses/05.jrs.LifecycleHooks.html b/juneau-doc/docs/Topics/08.juneau-rest-server/02.jrs.AnnotatedClasses/05.jrs.LifecycleHooks.html
index c1341c94c..beaf8c43f 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/02.jrs.AnnotatedClasses/05.jrs.LifecycleHooks.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/02.jrs.AnnotatedClasses/05.jrs.LifecycleHooks.html
@@ -29,7 +29,7 @@
 		|		<jc>// Our database.</jc>
 		|		<jk>private</jk> Map&lt;Integer,Object&gt; <jf>myDatabase</jf>;
 		|
-		|		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		|		<ja>@RestInit</ja>
 		|		<jk>public void</jk> initMyDatabase(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		|			<jf>myDatabase</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;();
 		|		}
@@ -43,39 +43,30 @@
 		|	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig {
 		|
 		|		<jc>// Add a request attribute to all incoming requests.</jc>
-		|		<ja>@RestHook</ja>(<jsf>PRE_CALL</jsf>)
+		|		<ja>@RestPreCall</ja>
 		|		<jk>public void</jk> onPreCall(RestRequest <jv>req</jv>) {
 		|			<jv>req</jv>.setAttribute(<js>"foo"</js>, <js>"bar"</js>);
 		|		}
 		|	}
 	</p>
 	<p>
-		The hook events can be broken down into two categories:
+		The following lifecycle annotations are provided.
 	</p>
 	<ul class='javatree'>
-		<li class='je'>{@link oajr.annotation.HookEvent}
-			<ul class='spaced-list'>
-				<li>Resource lifecycle events:
-					<ul class='javatree'>
-						<li class='jf'>{@link oajr.annotation.HookEvent#INIT INIT} - Right before initialization.
-						<li class='jf'>{@link oajr.annotation.HookEvent#POST_INIT POST_INIT} - Right after initialization.
-						<li class='jf'>{@link oajr.annotation.HookEvent#POST_INIT_CHILD_FIRST POST_INIT_CHILD_FIRST} - Right after initialization but run child methods first.
-						<li class='jf'>{@link oajr.annotation.HookEvent#DESTROY DESTROY} - Right before servlet destroy.
-					</ul>
-				</li>
-				<li>REST call lifecycle events:
-					<ul class='javatree'>
-						<li class='jf'>{@link oajr.annotation.HookEvent#START_CALL START_CALL} - At the beginning of a REST call.
-						<li class='jf'>{@link oajr.annotation.HookEvent#PRE_CALL PRE_CALL} - Right before the <ja>@RestOp</ja> method is invoked.
-						<li class='jf'>{@link oajr.annotation.HookEvent#POST_CALL POST_CALL} - Right after the <ja>@RestOp</ja> method is invoked.
-						<li class='jf'>{@link oajr.annotation.HookEvent#END_CALL END_CALL} - At the end of the REST call after the response has been flushed.
-					</ul>
-				</li>
+		<li>Resource lifecycle events:
+			<ul class='javatree'>
+				<li class='ja'>{@link oajr.annotation.RestInit} - Right before initialization.
+				<li class='ja'>{@link oajr.annotation.RestPostInit} - Right after initialization.
+				<li class='ja'>{@link oajr.annotation.RestDestroy} - Right before servlet destroy.
+			</ul>
+		</li>
+		<li>REST call lifecycle events:
+			<ul class='javatree'>
+				<li class='ja'>{@link oajr.annotation.RestStartCall} - At the beginning of a REST call.
+				<li class='ja'>{@link oajr.annotation.RestPreCall} - Right before the <ja>@RestOp</ja> method is invoked.
+				<li class='ja'>{@link oajr.annotation.RestPostCall} - Right after the <ja>@RestOp</ja> method is invoked.
+				<li class='ja'>{@link oajr.annotation.RestEndCall} - At the end of the REST call after the response has been flushed.
 			</ul>
 		</li>
-	</ul>
-	
-	<ul class='seealso'>
-		<li class='ja'>{@link oajr.annotation.RestHook}
 	</ul>
 </div>
\ No newline at end of file
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/03.jrs.RestOpAnnotatedMethods/02.jrs.JavaMethodParameters.html b/juneau-doc/docs/Topics/08.juneau-rest-server/03.jrs.RestOpAnnotatedMethods/02.jrs.JavaMethodParameters.html
index 1edd7a2a1..148258bf3 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/03.jrs.RestOpAnnotatedMethods/02.jrs.JavaMethodParameters.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/03.jrs.RestOpAnnotatedMethods/02.jrs.JavaMethodParameters.html
@@ -183,6 +183,6 @@
 	</p>
 	<p>
 		Additional parameter types can be defined by overriding {@link oajr.RestContext.Builder#createRestOpArgs(BeanStore,Supplier)} or
-		by adding them to the bean store using {@link oajr.RestContext.Builder#createBeanStore(Class,Supplier)}.
+		by adding them to the bean store using {@link oajr.RestContext.Builder#createBeanStore(Supplier)}.
 	</p>
 </div>
\ No newline at end of file
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/05.jrs.Marshalling.html b/juneau-doc/docs/Topics/08.juneau-rest-server/05.jrs.Marshalling.html
index f3751eaa5..9001c3427 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/05.jrs.Marshalling.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/05.jrs.Marshalling.html
@@ -91,7 +91,7 @@
 		|	<ja>@Rest</ja>
 		|	<jk>public class</jk> MyResource {
 		|
-		|		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		|		<ja>@RestInit</ja>
 		|		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) {
 		|			<jv>builder</jv>.serializers().add(JsonSerializer.<jk>class</jk>, HtmlSerializer.<jk>class</jk>);
 		|			<jv>builder</jv>.parsers().add(JsonParser.<jk>class</jk>, HtmlParser.<jk>class</jk>);
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/12.jrs.SvlVariables.html b/juneau-doc/docs/Topics/08.juneau-rest-server/12.jrs.SvlVariables.html
index 5f2f333e4..e02eb9e4b 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/12.jrs.SvlVariables.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/12.jrs.SvlVariables.html
@@ -251,7 +251,7 @@
 	<ul class='javatree'>
 		<li class='jc'>{@link oajr.RestContext.Builder}
 			<ul class='javatreec'>
-				<li class='jmp'>{@link oajr.RestContext.Builder#createVarResolver(BeanStore,Class) createVarResolver(BeanStore,Class)}
+				<li class='jmp'>{@link oajr.RestContext.Builder#createVarResolver(BeanStore,Supplier,Class) createVarResolver(BeanStore,Supplier,Class)}
 				<li class='jm'>{@link oajr.RestContext.Builder#varResolver() varResolver()}
 				<li class='jm'>{@link oajr.RestContext.Builder#varResolver(Consumer) varResolver(Consumer)}
 			</ul>
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/13.jrs.StaticFiles.html b/juneau-doc/docs/Topics/08.juneau-rest-server/13.jrs.StaticFiles.html
index 4df5d8bc4..3d5d1ac40 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/13.jrs.StaticFiles.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/13.jrs.StaticFiles.html
@@ -63,9 +63,8 @@
 	<ul class='javatree'>
 		<li class='jc'>{@link oajr.RestContext.Builder}
 			<ul class='javatreec'>
-				<li class='jmp'>{@link oajr.RestContext.Builder#createStaticFiles(BeanStore,Supplier) createStaticFiles(BeanStore,Supplier)}
+				<li class='jmp'>{@link oajr.RestContext.Builder#createStaticFiles() createStaticFiles(BeanStore,Supplier)}
 				<li class='jm'>{@link oajr.RestContext.Builder#staticFiles() staticFiles()}
-				<li class='jm'>{@link oajr.RestContext.Builder#staticFiles(Consumer) staticFiles(Consumer)}
 			</ul>
 		</li>
 	</ul>
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/16.jrs.ExecutionStatistics.html b/juneau-doc/docs/Topics/08.juneau-rest-server/16.jrs.ExecutionStatistics.html
index bf525042c..f5d923a8e 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/16.jrs.ExecutionStatistics.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/16.jrs.ExecutionStatistics.html
@@ -18,7 +18,7 @@
 <div class='topic'>
 	<p>
 		{@link oajr.annotation.Rest}-annotated classes get automated timing and error statistic information for all <ja>@RestOp</ja>
-		and <ja>@RestHook</ja> annotated methods on the class.
+		and lifecycle-event annotated methods on the class.
 	</p>
 	<p>
 		If you extend from {@link oajr.servlet.BasicRestServlet} or {@link oajr.servlet.BasicRestObject}, then
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/18.jrs.LoggingAndDebugging.html b/juneau-doc/docs/Topics/08.juneau-rest-server/18.jrs.LoggingAndDebugging.html
index 8274c7a43..23dc4cc74 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/18.jrs.LoggingAndDebugging.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/18.jrs.LoggingAndDebugging.html
@@ -93,7 +93,6 @@
 			<ul class='javatreec'>
 				<li class='jmp'>{@link oajr.RestContext.Builder#createDebugEnablement(BeanStore,Supplier) createDebugEnablement(BeanStore,Supplier)}
 				<li class='jm'>{@link oajr.RestContext.Builder#debugEnablement() debugEnablement()}
-				<li class='jm'>{@link oajr.RestContext.Builder#debugEnablement(Consumer) debugEnablement(Consumer)}
 			</ul>
 		</li>
 	</ul>
@@ -169,7 +168,7 @@
 		</li>
 		<li class='jc'>{@link oajr.RestContext.Builder}
 			<ul class='javatreec'>
-				<li class='jmp'>{@link oajr.RestContext.Builder#createCallLogger() createCallLogger()}
+				<li class='jmp'>{@link oajr.RestContext.Builder#createCallLogger(BeanStore,Supplier) createCallLogger(BeanStore,Supplier)}
 				<li class='jm'>{@link oajr.RestContext.Builder#callLogger() callLogger()}
 			</ul>
 		</li>
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/22.jrs.RestContext.html b/juneau-doc/docs/Topics/08.juneau-rest-server/22.jrs.RestContext.html
index e8f0d4cb8..3f09c6b48 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/22.jrs.RestContext.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/22.jrs.RestContext.html
@@ -41,8 +41,8 @@
 		|				.debugEnablement(<jsf>CONDITIONAL</jsf>);
 		|	}
 		|
-		|	<jc>// Option #2 - Use an INIT hook.</jc>
-		|	<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		|	<jc>// Option #2 - Use an init hook.</jc>
+		|	<ja>@RestInit</ja>
 		|	<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		|			<jv>builder</jv>
 		|				.beanContext(<jv>x</jv> -&gt; <jv>x</jv>.swaps(TemporalCalendarSwap.Rfc1123DateTime.<jk>class</jk>))
@@ -68,9 +68,7 @@
 			<li class='jm'>{@link oaj.rest.RestContext.Builder#children(Object...) children}
 			<li class='jm'>{@link oaj.rest.RestContext.Builder#config(Config) config}
 			<li class='jm'>{@link oaj.rest.RestContext.Builder#consumes(MediaType...) consumes}
-			<li class='jm'>{@link oaj.rest.RestContext.Builder#debug(Enablement) debug}
 			<li class='jm'>{@link oaj.rest.RestContext.Builder#debugDefault(Enablement) debugDefault}
-			<li class='jm'>{@link oaj.rest.RestContext.Builder#debugOn(String) debugOn}
 			<li class='jm'>{@link oaj.rest.RestContext.Builder#defaultAccept(String) defaultAccept}
 			<li class='jm'>{@link oaj.rest.RestContext.Builder#defaultCharset(Charset) defaultCharset}
 			<li class='jm'>{@link oaj.rest.RestContext.Builder#defaultClasses(Class...) defaultClasses}
diff --git a/juneau-doc/docs/Topics/08.juneau-rest-server/23.jrs.RestOpContext.html b/juneau-doc/docs/Topics/08.juneau-rest-server/23.jrs.RestOpContext.html
index 09dcad3aa..23de568f8 100644
--- a/juneau-doc/docs/Topics/08.juneau-rest-server/23.jrs.RestOpContext.html
+++ b/juneau-doc/docs/Topics/08.juneau-rest-server/23.jrs.RestOpContext.html
@@ -28,8 +28,8 @@
 		To access the builder for these objects, simply implement the following init method that will be called for each {@link oajr.annotation.RestOp}-annotated method.
 	</p>
 	<p class='bjava'>
-		|	<jc>// Use an INIT hook with RestOpContext.Builder as a parameter.</jc>
-		|	<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		|	<jc>// Use an init hook with RestOpContext.Builder as a parameter.</jc>
+		|	<ja>@RestInit</ja>
 		|	<jk>public void</jk> init(RestOpContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		|			<jv>builder</jv>
 		|				.beanContext(<jv>x</jv> -&gt; <jv>x</jv>.swaps(TemporalCalendarSwap.Rfc1123DateTime.<jk>class</jk>))
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 5c8477295..200c92365 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -16803,7 +16803,7 @@
 		<jc>// Our database.</jc>
 		<jk>private</jk> Map&lt;Integer,Object&gt; <jf>myDatabase</jf>;
 
-		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		<ja>@RestInit</ja>
 		<jk>public void</jk> initMyDatabase(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 			<jf>myDatabase</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;();
 		}
@@ -16817,40 +16817,31 @@
 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestObject <jk>implements</jk> BasicUniversalConfig {
 
 		<jc>// Add a request attribute to all incoming requests.</jc>
-		<ja>@RestHook</ja>(<jsf>PRE_CALL</jsf>)
+		<ja>@RestPreCall</ja>
 		<jk>public void</jk> onPreCall(RestRequest <jv>req</jv>) {
 			<jv>req</jv>.setAttribute(<js>"foo"</js>, <js>"bar"</js>);
 		}
 	}
 	</p>
 	<p>
-		The hook events can be broken down into two categories:
+		The following lifecycle annotations are provided.
 	</p>
 	<ul class='javatree'>
-		<li class='je'>{@link org.apache.juneau.rest.annotation.HookEvent}
-			<ul class='spaced-list'>
-				<li>Resource lifecycle events:
-					<ul class='javatree'>
-						<li class='jf'>{@link org.apache.juneau.rest.annotation.HookEvent#INIT INIT} - Right before initialization.
-						<li class='jf'>{@link org.apache.juneau.rest.annotation.HookEvent#POST_INIT POST_INIT} - Right after initialization.
-						<li class='jf'>{@link org.apache.juneau.rest.annotation.HookEvent#POST_INIT_CHILD_FIRST POST_INIT_CHILD_FIRST} - Right after initialization but run child methods first.
-						<li class='jf'>{@link org.apache.juneau.rest.annotation.HookEvent#DESTROY DESTROY} - Right before servlet destroy.
-					</ul>
-				</li>
-				<li>REST call lifecycle events:
-					<ul class='javatree'>
-						<li class='jf'>{@link org.apache.juneau.rest.annotation.HookEvent#START_CALL START_CALL} - At the beginning of a REST call.
-						<li class='jf'>{@link org.apache.juneau.rest.annotation.HookEvent#PRE_CALL PRE_CALL} - Right before the <ja>@RestOp</ja> method is invoked.
-						<li class='jf'>{@link org.apache.juneau.rest.annotation.HookEvent#POST_CALL POST_CALL} - Right after the <ja>@RestOp</ja> method is invoked.
-						<li class='jf'>{@link org.apache.juneau.rest.annotation.HookEvent#END_CALL END_CALL} - At the end of the REST call after the response has been flushed.
-					</ul>
-				</li>
+		<li>Resource lifecycle events:
+			<ul class='javatree'>
+				<li class='ja'>{@link org.apache.juneau.rest.annotation.RestInit} - Right before initialization.
+				<li class='ja'>{@link org.apache.juneau.rest.annotation.RestPostInit} - Right after initialization.
+				<li class='ja'>{@link org.apache.juneau.rest.annotation.RestDestroy} - Right before servlet destroy.
+			</ul>
+		</li>
+		<li>REST call lifecycle events:
+			<ul class='javatree'>
+				<li class='ja'>{@link org.apache.juneau.rest.annotation.RestStartCall} - At the beginning of a REST call.
+				<li class='ja'>{@link org.apache.juneau.rest.annotation.RestPreCall} - Right before the <ja>@RestOp</ja> method is invoked.
+				<li class='ja'>{@link org.apache.juneau.rest.annotation.RestPostCall} - Right after the <ja>@RestOp</ja> method is invoked.
+				<li class='ja'>{@link org.apache.juneau.rest.annotation.RestEndCall} - At the end of the REST call after the response has been flushed.
 			</ul>
 		</li>
-	</ul>
-	
-	<ul class='seealso'>
-		<li class='ja'>{@link org.apache.juneau.rest.annotation.RestHook}
 	</ul>
 </div>
 </div><!-- END: 8.2.5 - juneau-rest-server.jrs.AnnotatedClasses.jrs.LifecycleHooks -->
@@ -17166,7 +17157,7 @@
 	</p>
 	<p>
 		Additional parameter types can be defined by overriding {@link org.apache.juneau.rest.RestContext.Builder#createRestOpArgs(BeanStore,Supplier)} or
-		by adding them to the bean store using {@link org.apache.juneau.rest.RestContext.Builder#createBeanStore(Class,Supplier)}.
+		by adding them to the bean store using {@link org.apache.juneau.rest.RestContext.Builder#createBeanStore(Supplier)}.
 	</p>
 </div>
 </div><!-- END: 8.3.2 - juneau-rest-server.jrs.RestOpAnnotatedMethods.jrs.JavaMethodParameters -->
@@ -18664,7 +18655,7 @@
 	<ja>@Rest</ja>
 	<jk>public class</jk> MyResource {
 
-		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		<ja>@RestInit</ja>
 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) {
 			<jv>builder</jv>.serializers().add(JsonSerializer.<jk>class</jk>, HtmlSerializer.<jk>class</jk>);
 			<jv>builder</jv>.parsers().add(JsonParser.<jk>class</jk>, HtmlParser.<jk>class</jk>);
@@ -19629,7 +19620,7 @@
 	<ul class='javatree'>
 		<li class='jc'>{@link org.apache.juneau.rest.RestContext.Builder}
 			<ul class='javatreec'>
-				<li class='jmp'>{@link org.apache.juneau.rest.RestContext.Builder#createVarResolver(BeanStore,Class) createVarResolver(BeanStore,Class)}
+				<li class='jmp'>{@link org.apache.juneau.rest.RestContext.Builder#createVarResolver(BeanStore,Supplier,Class) createVarResolver(BeanStore,Supplier,Class)}
 				<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#varResolver() varResolver()}
 				<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#varResolver(Consumer) varResolver(Consumer)}
 			</ul>
@@ -19730,9 +19721,8 @@
 	<ul class='javatree'>
 		<li class='jc'>{@link org.apache.juneau.rest.RestContext.Builder}
 			<ul class='javatreec'>
-				<li class='jmp'>{@link org.apache.juneau.rest.RestContext.Builder#createStaticFiles(BeanStore,Supplier) createStaticFiles(BeanStore,Supplier)}
+				<li class='jmp'>{@link org.apache.juneau.rest.RestContext.Builder#createStaticFiles() createStaticFiles(BeanStore,Supplier)}
 				<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#staticFiles() staticFiles()}
-				<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#staticFiles(Consumer) staticFiles(Consumer)}
 			</ul>
 		</li>
 	</ul>
@@ -20491,7 +20481,7 @@
 <div class='topic'>
 	<p>
 		{@link org.apache.juneau.rest.annotation.Rest}-annotated classes get automated timing and error statistic information for all <ja>@RestOp</ja>
-		and <ja>@RestHook</ja> annotated methods on the class.
+		and lifecycle-event annotated methods on the class.
 	</p>
 	<p>
 		If you extend from {@link org.apache.juneau.rest.servlet.BasicRestServlet} or {@link org.apache.juneau.rest.servlet.BasicRestObject}, then
@@ -21365,7 +21355,6 @@
 			<ul class='javatreec'>
 				<li class='jmp'>{@link org.apache.juneau.rest.RestContext.Builder#createDebugEnablement(BeanStore,Supplier) createDebugEnablement(BeanStore,Supplier)}
 				<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#debugEnablement() debugEnablement()}
-				<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#debugEnablement(Consumer) debugEnablement(Consumer)}
 			</ul>
 		</li>
 	</ul>
@@ -21441,7 +21430,7 @@
 		</li>
 		<li class='jc'>{@link org.apache.juneau.rest.RestContext.Builder}
 			<ul class='javatreec'>
-				<li class='jmp'>{@link org.apache.juneau.rest.RestContext.Builder#createCallLogger() createCallLogger()}
+				<li class='jmp'>{@link org.apache.juneau.rest.RestContext.Builder#createCallLogger(BeanStore,Supplier) createCallLogger(BeanStore,Supplier)}
 				<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#callLogger() callLogger()}
 			</ul>
 		</li>
@@ -21741,8 +21730,8 @@
 				.debugEnablement(<jsf>CONDITIONAL</jsf>);
 	}
 
-	<jc>// Option #2 - Use an INIT hook.</jc>
-	<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+	<jc>// Option #2 - Use an init hook.</jc>
+	<ja>@RestInit</ja>
 	<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 			<jv>builder</jv>
 				.beanContext(<jv>x</jv> -&gt; <jv>x</jv>.swaps(TemporalCalendarSwap.Rfc1123DateTime.<jk>class</jk>))
@@ -21768,9 +21757,7 @@
 			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#children(Object...) children}
 			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#config(Config) config}
 			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#consumes(MediaType...) consumes}
-			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#debug(Enablement) debug}
 			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#debugDefault(Enablement) debugDefault}
-			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#debugOn(String) debugOn}
 			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#defaultAccept(String) defaultAccept}
 			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#defaultCharset(Charset) defaultCharset}
 			<li class='jm'>{@link org.apache.juneau.rest.RestContext.Builder#defaultClasses(Class...) defaultClasses}
@@ -21876,8 +21863,8 @@
 		To access the builder for these objects, simply implement the following init method that will be called for each {@link org.apache.juneau.rest.annotation.RestOp}-annotated method.
 	</p>
 	<p class='bjava'>
-	<jc>// Use an INIT hook with RestOpContext.Builder as a parameter.</jc>
-	<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+	<jc>// Use an init hook with RestOpContext.Builder as a parameter.</jc>
+	<ja>@RestInit</ja>
 	<jk>public void</jk> init(RestOpContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 			<jv>builder</jv>
 				.beanContext(<jv>x</jv> -&gt; <jv>x</jv>.swaps(TemporalCalendarSwap.Rfc1123DateTime.<jk>class</jk>))
@@ -33963,7 +33950,7 @@
 	<ul class='spaced-list'>
 		<li>
 			Revamped and simplified servlet and REST-call lifecycle handling through new
-			{@link org.apache.juneau.rest.annotation.RestHook @RestHook} annotation.
+			{@del @RestHook} annotation.
 			<ul>
 				<li>The {@del org.apache.juneau.rest.RestServlet#init(ServletConfig)} method is now final and can
 					no longer be extended.
diff --git a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
index 07bd4f8bc..720e32ecc 100644
--- a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
+++ b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
@@ -12,7 +12,6 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.microservice.resources;
 
-import static org.apache.juneau.rest.annotation.HookEvent.*;
 import static org.apache.juneau.internal.StringUtils.*;
 
 import java.io.*;
@@ -56,7 +55,7 @@ public class LogsResource extends BasicRestServlet implements BasicUniversalConf
 	private LogEntryFormatter leFormatter;
 	boolean allowDeletes;
 
-	@RestHook(INIT)
+	@RestInit
 	public void init(Config config) throws Exception {
 		logDir = new File(config.get("Logging/logDir").asString().orElse("logs"));
 		allowDeletes = config.get("Logging/allowDeletes").asBoolean().orElse(true);
diff --git a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyResource.java b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyResource.java
index 9c1b66ffb..7fc2a57c8 100644
--- a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyResource.java
+++ b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyResource.java
@@ -53,7 +53,7 @@ public class ThirdPartyProxyResource extends BasicRestServlet implements BasicUn
 		}
 	}
 
-	@RestHook(HookEvent.START_CALL)
+	@RestStartCall
 	public static void startCall(HttpServletRequest req) {
 		try {
 			logFile.append("START["+new Date()+"]-").append(req.getQueryString()).append("\n");
@@ -63,7 +63,7 @@ public class ThirdPartyProxyResource extends BasicRestServlet implements BasicUn
 		}
 	}
 
-	@RestHook(HookEvent.PRE_CALL)
+	@RestPreCall
 	public static void preCall(HttpServletRequest req) {
 		try {
 			logFile.append("PRE["+new Date()+"]-").append(req.getQueryString()).append("\n");
@@ -73,7 +73,7 @@ public class ThirdPartyProxyResource extends BasicRestServlet implements BasicUn
 		}
 	}
 
-	@RestHook(HookEvent.POST_CALL)
+	@RestPostCall
 	public static void postCall(HttpServletRequest req) {
 		try {
 			logFile.append("POST["+new Date()+"]-").append(req.getQueryString()).append("\n");
@@ -83,7 +83,7 @@ public class ThirdPartyProxyResource extends BasicRestServlet implements BasicUn
 		}
 	}
 
-	@RestHook(HookEvent.END_CALL)
+	@RestEndCall
 	public static void endCall(HttpServletRequest req) {
 		try {
 			Throwable e = (Throwable)req.getAttribute("Exception");
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildren.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildren.java
index 5a31b7d06..2650ed6db 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildren.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestChildren.java
@@ -171,7 +171,7 @@ public class RestChildren {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
-	 * Called during servlet initialization on all children to invoke all {@link HookEvent#POST_INIT} methods.
+	 * Called during servlet initialization on all children to invoke all {@link RestPostInit} child-last methods.
 	 *
 	 * @throws ServletException Error occurred.
 	 */
@@ -181,7 +181,7 @@ public class RestChildren {
 	}
 
 	/**
-	 * Called during servlet initialization on all children to invoke all {@link HookEvent#POST_INIT_CHILD_FIRST} methods.
+	 * Called during servlet initialization on all children to invoke all {@link RestPostInit} child-first methods.
 	 *
 	 * @throws ServletException Error occurred.
 	 */
@@ -191,7 +191,7 @@ public class RestChildren {
 	}
 
 	/**
-	 * Called during servlet destruction on all children to invoke all {@link HookEvent#DESTROY} and {@link Servlet#destroy()} methods.
+	 * Called during servlet destruction on all children to invoke all {@link RestDestroy} and {@link Servlet#destroy()} methods.
 	 */
 	public void destroy() {
 		for (RestContext r : children.values()) {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index f9a428e37..791e08a33 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -101,8 +101,8 @@ import org.apache.juneau.utils.*;
  * 				.swaps(TemporalCalendarSwap.IsoLocalDateTime.<jk>class</jk>);
  * 	}
  *
- * 	<jc>// Option #2 - Use an INIT hook.</jc>
- * 	<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+ * 	<jc>// Option #2 - Use an init hook.</jc>
+ * 	<ja>@RestInit</ja>
  * 	<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
  * 			<jv>builder</jv>
  * 				.swaps(TemporalCalendarSwap.IsoLocalDateTime.<jk>class</jk>);
@@ -389,7 +389,7 @@ public class RestContext extends Context {
 			Supplier<?> r = this.resource;
 			Class<?> rc = resourceClass;
 
-			beanStore = createBeanStore()
+			beanStore = createBeanStore(resource)
 				.build()
 				.addBean(Builder.class, this)
 				.addBean(ResourceSupplier.class, this.resource)
@@ -403,9 +403,9 @@ public class RestContext extends Context {
 			BeanStore bs = beanStore;
 
 			beanStore.add(BeanStore.class, bs);
-			varResolver = createVarResolver(bs, rc);
+			varResolver = createVarResolver(bs, r, rc);
 			beanStore.add(VarResolver.class, varResolver.build());
-			config = beanStore.add(Config.class, createConfig(bs, rc));
+			config = beanStore.add(Config.class, createConfig(bs, r, rc));
 			beanStore.add(VarResolver.class, varResolver.bean(Config.class, config).build());
 
 			ClassInfo rci = ClassInfo.of(resourceClass);
@@ -465,7 +465,7 @@ public class RestContext extends Context {
 
 			Map<String,MethodInfo> map = map();
 			ClassInfo.ofProxy(r).forEachAllMethodParentFirst(
-				y -> y.hasAnnotation(RestHook.class) && y.getAnnotation(RestHook.class).value() == HookEvent.INIT && ! y.hasArg(RestOpContext.Builder.class),
+				y -> y.hasAnnotation(RestInit.class) && ! y.hasArg(RestOpContext.Builder.class),
 				y -> {
 					String sig = y.getSignature();
 					if (! map.containsKey(sig))
@@ -475,11 +475,11 @@ public class RestContext extends Context {
 
 			for (MethodInfo m : map.values()) {
 				if (! beanStore.hasAllParams(m))
-					throw servletException("Could not call @RestHook(INIT) method {0}.{1}.  Could not find prerequisites: {2}.", m.getDeclaringClass().getSimpleName(), m.getSignature(), beanStore.getMissingParams(m));
+					throw servletException("Could not call @RestInit method {0}.{1}.  Could not find prerequisites: {2}.", m.getDeclaringClass().getSimpleName(), m.getSignature(), beanStore.getMissingParams(m));
 				try {
 					m.invoke(r, beanStore.getParams(m));
 				} catch (Exception e) {
-					throw servletException(e, "Exception thrown from @RestHook(INIT) method {0}.{1}.", m.getDeclaringClass().getSimpleName(), m.getSignature());
+					throw servletException(e, "Exception thrown from @RestInit method {0}.{1}.", m.getDeclaringClass().getSimpleName(), m.getSignature());
 				}
 			}
 		}
@@ -602,7 +602,7 @@ public class RestContext extends Context {
 		 * Can be used to add more beans to the bean store.
 		 *
 		 * <p>
-		 * The bean store is created by the constructor using the {@link #createBeanStore()} method and is initialized with the following beans:
+		 * The bean store is created by the constructor using the {@link #createBeanStore(Supplier)} method and is initialized with the following beans:
 		 * <ul>
 		 * 	<li>{@link RestContext.Builder}
 		 * 	<li>{@link ServletConfig}
@@ -667,9 +667,11 @@ public class RestContext extends Context {
 		 * 		<br>Args can be any injectable bean including {@link org.apache.juneau.cp.BeanStore.Builder}, the default builder.
 		 * </ul>
 		 *
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new bean store builder.
 		 */
-		protected BeanStore.Builder createBeanStore() {
+		protected BeanStore.Builder createBeanStore(Supplier<?> resource) {
 
 			// Default value.
 			Value<BeanStore.Builder> v = Value.of(
@@ -710,7 +712,7 @@ public class RestContext extends Context {
 		 * used to resolve string variables of the form <js>"$X{...}"</js> in various places such as annotations on the REST class and methods.
 		 *
 		 * <p>
-		 * The var resolver is created by the constructor using the {@link #createVarResolver(BeanStore,Class)} method and is initialized with the following beans:
+		 * The var resolver is created by the constructor using the {@link #createVarResolver(BeanStore,Supplier,Class)} method and is initialized with the following beans:
 		 * <ul>
 		 * 	<li>{@link ConfigVar}
 		 * 	<li>{@link FileVar}
@@ -779,22 +781,25 @@ public class RestContext extends Context {
 		 * 	<li>
 		 * 		Looks for bean of type {@link org.apache.juneau.svl.VarResolver.Builder} in bean store and returns a copy of it.
 		 * 	<li>
-		 * 		Creates a default builder with default variables pulled from {@link #createVars(BeanStore,Class)}.
+		 * 		Creates a default builder with default variables pulled from {@link #createVars(BeanStore,Supplier,Class)}.
 		 * </ol>
 		 *
-		 * @param beanStore The bean store containing injected beans.
+		 * @param beanStore
+		 * 	The factory used for creating beans and retrieving injected beans.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @param resourceClass
 		 * 	The REST servlet/bean type that this context is defined against.
 		 * @return A new variable resolver sub-builder.
 		 */
-		protected VarResolver.Builder createVarResolver(BeanStore beanStore, Class<?> resourceClass) {
+		protected VarResolver.Builder createVarResolver(BeanStore beanStore, Supplier<?> resource, Class<?> resourceClass) {
 
 			// Default value.
 			Value<VarResolver.Builder> v = Value.of(
 				VarResolver
 					.create()
 					.defaultVars()
-					.vars(createVars(beanStore, resourceClass))
+					.vars(createVars(beanStore, resource, resourceClass))
 					.vars(FileVar.class)
 					.bean(FileFinder.class, FileFinder.create(beanStore).cp(resourceClass,null,true).build())
 			);
@@ -835,12 +840,15 @@ public class RestContext extends Context {
 		 * 		Creates a default builder with default variables.
 		 * </ol>
 		 *
-		 * @param beanStore The bean store containing injected beans.
+		 * @param beanStore
+		 * 	The factory used for creating beans and retrieving injected beans.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @param resourceClass
 		 * 	The REST servlet/bean type that this context is defined against.
 		 * @return A new var resolver variable list.
 		 */
-		protected VarList createVars(BeanStore beanStore, Class<?> resourceClass) {
+		protected VarList createVars(BeanStore beanStore, Supplier<?> resource, Class<?> resourceClass) {
 
 			// Default value.
 			Value<VarList> v = Value.of(
@@ -949,12 +957,15 @@ public class RestContext extends Context {
 		/**
 		 * Creates the config for this builder.
 		 *
-		 * @param beanStore The bean store to use for creating the config.
+		 * @param beanStore
+		 * 	The factory used for creating beans and retrieving injected beans.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @param resourceClass
 		 * 	The REST servlet/bean type that this context is defined against.
 		 * @return A new config.
 		 */
-		protected Config createConfig(BeanStore beanStore, Class<?> resourceClass) {
+		protected Config createConfig(BeanStore beanStore, Supplier<?> resource, Class<?> resourceClass) {
 
 			Value<Config> v = Value.empty();
 
@@ -1003,7 +1014,7 @@ public class RestContext extends Context {
 		 */
 		public Logger logger() {
 			if (logger == null)
-				logger = createLogger(beanStore(), resourceClass);
+				logger = createLogger(beanStore(), resource, resourceClass);
 			return logger;
 		}
 
@@ -1033,7 +1044,7 @@ public class RestContext extends Context {
 		 * Sets the logger for this resource.
 		 *
 		 * <p>
-		 * If not specified, the logger used is created by {@link #createLogger(BeanStore, Class)}.
+		 * If not specified, the logger used is created by {@link #createLogger(BeanStore, Supplier, Class)}.
 		 *
 		 * @param value The logger to use for the REST resource.
 		 * @return This object.
@@ -1060,14 +1071,15 @@ public class RestContext extends Context {
 		 * 	<li>Instantiates via <c>Logger.<jsm>getLogger</jsm>(<jv>resource</jv>.getClass().getName())</c>.
 		 * </ul>
 		 *
-		 * @param resourceClass
-		 * 	The REST servlet/bean class that this context is defined against.
 		 * @param beanStore
 		 * 	The factory used for creating beans and retrieving injected beans.
-		 * 	<br>Created by {@link RestContext.Builder#beanStore()}.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
+		 * @param resourceClass
+		 * 	The REST servlet/bean class that this context is defined against.
 		 * @return A new logger.
 		 */
-		protected Logger createLogger(BeanStore beanStore, Class<?> resourceClass) {
+		protected Logger createLogger(BeanStore beanStore, Supplier<?> resource, Class<?> resourceClass) {
 
 			// Default value.
 			Value<Logger> v = Value.of(
@@ -1746,7 +1758,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.responseProcessors(MyResponseProcessors.<jk>class</jk>);
 		 * 		}
@@ -1910,7 +1922,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Registered via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.callLogger(MyLogger.<jk>class</jk>);
 		 * 		}
@@ -1942,7 +1954,7 @@ public class RestContext extends Context {
 		 */
 		public BeanCreator<CallLogger> callLogger() {
 			if (callLogger == null)
-				callLogger = createCallLogger();
+				callLogger = createCallLogger(beanStore, resource);
 			return callLogger;
 		}
 
@@ -1982,6 +1994,7 @@ public class RestContext extends Context {
 		 * 		</ul>
 		 * 	<li>Looks for a static or non-static <c>createCallLogger()</c> method that returns {@link CallLogger} on the
 		 * 		resource class with any of the following arguments:
+		 * 		<ul class='javatreec'>
 		 * 			<li>{@link RestContext}
 		 * 			<li>{@link RestContext.Builder}
 		 * 			<li>{@link BeanContext}
@@ -2000,9 +2013,13 @@ public class RestContext extends Context {
 		 * 	<li class='jm'>{@link RestContext.Builder#callLogger()}
 		 * </ul>
 		 *
+		 * @param beanStore
+		 * 	The factory used for creating beans and retrieving injected beans.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new call logger sub-builder.
 		 */
-		protected BeanCreator<CallLogger> createCallLogger() {
+		protected BeanCreator<CallLogger> createCallLogger(BeanStore beanStore, Supplier<?> resource) {
 
 			BeanCreator<CallLogger> creator = beanStore.createBean(CallLogger.class).type(BasicCallLogger.class);
 
@@ -2448,7 +2465,7 @@ public class RestContext extends Context {
 		 */
 		public BeanCreator<FileFinder> fileFinder() {
 			if (fileFinder == null)
-				fileFinder = createFileFinder();
+				fileFinder = createFileFinder(beanStore, resource);
 			return fileFinder;
 		}
 
@@ -2494,7 +2511,7 @@ public class RestContext extends Context {
 		 * </ul>
 		 *
 		 * <p>
-		 * The file finder is instantiated via the {@link RestContext.Builder#createFileFinder()} method which in turn instantiates
+		 * The file finder is instantiated via the {@link RestContext.Builder#createFileFinder(BeanStore,Supplier)} method which in turn instantiates
 		 * based on the following logic:
 		 * <ul>
 		 * 	<li>Returns the resource class itself if it's an instance of {@link FileFinder}.
@@ -2546,7 +2563,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #4 - Registered via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.fileFinder(MyFileFinder.<jk>class</jk>);
 		 * 		}
@@ -2594,9 +2611,14 @@ public class RestContext extends Context {
 		 * 	<li>{@link BeanStore} - The bean store of this REST context.
 		 * 	<li>Any {@doc juneau-rest-server-springboot injected bean} types.  Use {@link Optional} arguments for beans that may not exist.
 		 * </ul>
+		 *
+		 * @param beanStore
+		 * 	The factory used for creating beans and retrieving injected beans.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new file finder bean creator.
 		 */
-		protected BeanCreator<FileFinder> createFileFinder() {
+		protected BeanCreator<FileFinder> createFileFinder(BeanStore beanStore, Supplier<?> resource) {
 
 			BeanCreator<FileFinder> creator = beanStore.createBean(FileFinder.class).type(BasicRestFileFinder.class);
 
@@ -2629,7 +2651,7 @@ public class RestContext extends Context {
 		 */
 		public BeanCreator<StaticFiles> staticFiles() {
 			if (staticFiles == null)
-				staticFiles = createStaticFiles();
+				staticFiles = createStaticFiles(beanStore, resource);
 			return staticFiles;
 		}
 
@@ -2674,7 +2696,7 @@ public class RestContext extends Context {
 		 * </ul>
 		 *
 		 * <p>
-		 * The static file finder is instantiated via the {@link RestContext.Builder#createStaticFiles()} method which in turn instantiates
+		 * The static file finder is instantiated via the {@link RestContext.Builder#createStaticFiles(BeanStore,Supplier)} method which in turn instantiates
 		 * based on the following logic:
 		 *
 		 * <ol class='spaced-list'>
@@ -2747,9 +2769,13 @@ public class RestContext extends Context {
 		 * 	<jk>public class</jk> MyResource {...}
 		 * </p>
 		 *
+		 * @param beanStore
+		 * 	The factory used for creating beans and retrieving injected beans.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new static files sub-builder.
 		 */
-		protected BeanCreator<StaticFiles> createStaticFiles() {
+		protected BeanCreator<StaticFiles> createStaticFiles(BeanStore beanStore, Supplier<?> resource) {
 
 			BeanCreator<StaticFiles> creator = beanStore.createBean(StaticFiles.class).type(BasicStaticFiles.class);
 
@@ -2840,7 +2866,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.defaultRequestHeaders(Accept.<jsm>of</jsm>(<js>"application/json"</js>));
 		 * 		}
@@ -3006,7 +3032,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.defaultResponseHeaders(ContentType.<jsm>of</jsm>(<js>"text/plain"</js>));
 		 * 		}
@@ -3136,7 +3162,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.defaultRequestAttribute(<js>"Foo"</js>, <js>"bar"</js>);
 		 * 		}
@@ -3279,7 +3305,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Registered via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.restOpArgs(MyRestParam.<jk>class</jk>);
 		 * 		}
@@ -3409,7 +3435,7 @@ public class RestContext extends Context {
 		 */
 		public BeanCreator<DebugEnablement> debugEnablement() {
 			if (debugEnablement == null)
-				debugEnablement = createDebugEnablement();
+				debugEnablement = createDebugEnablement(beanStore, resource);
 			return debugEnablement;
 		}
 
@@ -3453,9 +3479,13 @@ public class RestContext extends Context {
 		/**
 		 * Instantiates the debug enablement bean creator.
 		 *
+		 * @param beanStore
+		 * 	The factory used for creating beans and retrieving injected beans.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new debug enablement bean creator.
 		 */
-		protected BeanCreator<DebugEnablement> createDebugEnablement() {
+		protected BeanCreator<DebugEnablement> createDebugEnablement(BeanStore beanStore, Supplier<?> resource) {
 
 			BeanCreator<DebugEnablement> creator = beanStore.createBean(DebugEnablement.class).type(BasicDebugEnablement.class);
 
@@ -3527,7 +3557,7 @@ public class RestContext extends Context {
 
 			// Default value.
 			Value<MethodList> v = Value.of(
-				getHookMethods(resource, HookEvent.START_CALL)
+				getAnnotatedMethods(resource, RestStartCall.class, x -> true)
 			);
 
 			// Replace with bean from:  @RestBean(name="startCallMethods") public [static] MethodList xxx(<args>)
@@ -3590,7 +3620,7 @@ public class RestContext extends Context {
 
 			// Default value.
 			Value<MethodList> v = Value.of(
-				getHookMethods(resource, HookEvent.END_CALL)
+				getAnnotatedMethods(resource, RestEndCall.class, x -> true)
 			);
 
 			// Replace with bean from:  @RestBean(name="endCallMethods") public [static] MethodList xxx(<args>)
@@ -3653,7 +3683,7 @@ public class RestContext extends Context {
 
 			// Default value.
 			Value<MethodList> v = Value.of(
-				getHookMethods(resource, HookEvent.POST_INIT)
+				getAnnotatedMethods(resource, RestPostInit.class, x -> ! x.childFirst())
 			);
 
 			// Replace with bean from:  @RestBean(name="postInitMethods") public [static] MethodList xxx(<args>)
@@ -3716,7 +3746,7 @@ public class RestContext extends Context {
 
 			// Default value.
 			Value<MethodList> v = Value.of(
-				getHookMethods(resource, HookEvent.POST_INIT_CHILD_FIRST)
+				getAnnotatedMethods(resource, RestPostInit.class, x -> x.childFirst())
 			);
 
 			// Replace with bean from:  @RestBean(name="postInitChildFirstMethods") public [static] MethodList xxx(<args>)
@@ -3779,7 +3809,7 @@ public class RestContext extends Context {
 
 			// Default value.
 			Value<MethodList> v = Value.of(
-				getHookMethods(resource, HookEvent.DESTROY)
+				getAnnotatedMethods(resource, RestDestroy.class, x -> true)
 			);
 
 			// Replace with bean from:  @RestBean(name="destroyMethods") public [static] MethodList xxx(<args>)
@@ -3845,7 +3875,7 @@ public class RestContext extends Context {
 
 			// Default value.
 			Value<MethodList> v = Value.of(
-				getHookMethods(resource, HookEvent.PRE_CALL)
+				getAnnotatedMethods(resource, RestPreCall.class, x -> true)
 			);
 
 			// Replace with bean from:  @RestBean(name="preCallMethods") public [static] MethodList xxx(<args>)
@@ -3911,7 +3941,7 @@ public class RestContext extends Context {
 
 			// Default value.
 			Value<MethodList> v = Value.of(
-				getHookMethods(resource, HookEvent.POST_CALL)
+				getAnnotatedMethods(resource, RestPostCall.class, x -> true)
 			);
 
 			// Replace with bean from:  @RestBean(name="postCallMethods") public [static] MethodList xxx(<args>)
@@ -3966,7 +3996,7 @@ public class RestContext extends Context {
 
 			Map<String,MethodInfo> initMap = map();
 			ClassInfo.ofProxy(resource.get()).forEachAllMethodParentFirst(
-				y -> y.hasAnnotation(RestHook.class) && y.getAnnotation(RestHook.class).value() == HookEvent.INIT && y.hasArg(RestOpContext.Builder.class),
+				y -> y.hasAnnotation(RestInit.class) && y.hasArg(RestOpContext.Builder.class),
 				y -> {
 					String sig = y.getSignature();
 					if (! initMap.containsKey(sig))
@@ -3996,12 +4026,12 @@ public class RestContext extends Context {
 						beanStore = BeanStore.of(beanStore, resource.get()).addBean(RestOpContext.Builder.class, rocb);
 						for (MethodInfo m : initMap.values()) {
 							if (! beanStore.hasAllParams(m)) {
-								throw servletException("Could not call @RestHook(INIT) method {0}.{1}.  Could not find prerequisites: {2}.", m.getDeclaringClass().getSimpleName(), m.getSignature(), beanStore.getMissingParams(m));
+								throw servletException("Could not call @RestInit method {0}.{1}.  Could not find prerequisites: {2}.", m.getDeclaringClass().getSimpleName(), m.getSignature(), beanStore.getMissingParams(m));
 							}
 							try {
 								m.invoke(resource.get(), beanStore.getParams(m));
 							} catch (Exception e) {
-								throw servletException(e, "Exception thrown from @RestHook(INIT) method {0}.{1}.", m.getDeclaringClass().getSimpleName(), m.getSignature());
+								throw servletException(e, "Exception thrown from @RestInit method {0}.{1}.", m.getDeclaringClass().getSimpleName(), m.getSignature());
 							}
 						}
 
@@ -4161,7 +4191,7 @@ public class RestContext extends Context {
 		 */
 		public BeanCreator<SwaggerProvider> swaggerProvider() {
 			if (swaggerProvider == null)
-				swaggerProvider = createSwaggerProvider();
+				swaggerProvider = createSwaggerProvider(beanStore, resource);
 			return swaggerProvider;
 		}
 
@@ -4215,9 +4245,13 @@ public class RestContext extends Context {
 		 * 	<li class='jm'>{@link RestContext.Builder#swaggerProvider(SwaggerProvider)}
 		 * </ul>
 		 *
+		 * @param beanStore
+		 * 	The factory used for creating beans and retrieving injected beans.
+		 * @param resource
+		 * 	The REST servlet/bean instance that this context is defined against.
 		 * @return A new swagger provider sub-builder.
 		 */
-		protected BeanCreator<SwaggerProvider> createSwaggerProvider() {
+		protected BeanCreator<SwaggerProvider> createSwaggerProvider(BeanStore beanStore, Supplier<?> resource) {
 
 			BeanCreator<SwaggerProvider> creator = beanStore.createBean(SwaggerProvider.class).type(BasicSwaggerProvider.class);
 
@@ -4314,7 +4348,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.allowedMethodHeaders(<js>"PATCH"</js>);
 		 * 		}
@@ -4385,7 +4419,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder builder) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.allowedMethodParams(<js>"HEAD,OPTIONS,PUT"</js>);
 		 * 		}
@@ -4447,7 +4481,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.clientVersionHeader(<js>"Client-Version"</js>);
 		 * 		}
@@ -4515,7 +4549,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.defaultCharset(<js>"US-ASCII"</js>);
 		 * 		}
@@ -4573,7 +4607,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.disableContentParam();
 		 * 		}
@@ -4630,7 +4664,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.maxInput(<js>"10M"</js>);
 		 * 		}
@@ -4749,7 +4783,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.uriAuthority(<js>"http://localhost:10000"</js>);
 		 * 		}
@@ -4810,7 +4844,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.uriContext(<js>"/foo"</js>);
 		 * 		}
@@ -4869,7 +4903,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.uriRelativity(<jsf>PATH_INFO</jsf>);
 		 * 		}
@@ -4928,7 +4962,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.uriResolution(<jsf>ABSOLUTE</jsf>);
 		 * 		}
@@ -5101,7 +5135,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Registered via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.children(MyChildResource.<jk>class</jk>);
 		 * 		}
@@ -5201,7 +5235,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.path(<js>"/myResource"</js>);
 		 * 		}
@@ -5283,7 +5317,7 @@ public class RestContext extends Context {
 		 * 		...
 		 *
 		 * 		<jc>// Option #2 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.restChildrenClass(MyRestChildren.<jk>class</jk>);
 		 * 		}
@@ -5343,7 +5377,7 @@ public class RestContext extends Context {
 		 * 		...
 		 *
 		 * 		<jc>// Option #2 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.methodContextClass(MyRestOperationContext.<jk>class</jk>);
 		 * 		}
@@ -5405,7 +5439,7 @@ public class RestContext extends Context {
 		 * 		...
 		 *
 		 * 		<jc>// Option #2 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.restMethodsClass(MyRestOperations.<jk>class</jk>);
 		 * 		}
@@ -5463,7 +5497,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.produces(<jk>false</jk>, <js>"application/json"</js>);
 		 * 		}
@@ -5525,7 +5559,7 @@ public class RestContext extends Context {
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.consumes(<jk>false</jk>, <js>"application/json"</js>);
 		 * 		}
@@ -5625,13 +5659,13 @@ public class RestContext extends Context {
 		// Helper methods
 		//----------------------------------------------------------------------------------------------------
 
-		private static MethodList getHookMethods(Supplier<?> resource, HookEvent event) {
+		private static <T extends Annotation> MethodList getAnnotatedMethods(Supplier<?> resource, Class<T> annotation, Predicate<T> predicate) {
 			Map<String,Method> x = map();
 			Object r = resource.get();
 
 			ClassInfo.ofProxy(r).forEachAllMethodParentFirst(
-				y -> y.hasAnnotation(RestHook.class),
-				y -> y.forEachAnnotation(RestHook.class, z -> z.value() == event, z -> x.put(y.getSignature(), y.accessible().inner()))
+				y -> y.hasAnnotation(annotation),
+				y -> y.forEachAnnotation(annotation, predicate, z -> x.put(y.getSignature(), y.accessible().inner()))
 			);
 
 			MethodList x2 = MethodList.of(x.values());
@@ -6666,7 +6700,7 @@ public class RestContext extends Context {
 		} finally {
 			try {
 				s.finish();
-				finishCall(s);
+				endCall(s);
 			} finally {
 				localSession.remove();
 			}
@@ -6886,7 +6920,7 @@ public class RestContext extends Context {
 	}
 
 	/**
-	 * Called at the start of a request to invoke all {@link HookEvent#START_CALL} methods.
+	 * Called at the start of a request to invoke all {@link RestStartCall} methods.
 	 *
 	 * @param session The current request.
 	 * @throws BasicHttpException If thrown from call methods.
@@ -6904,7 +6938,7 @@ public class RestContext extends Context {
 	}
 
 	/**
-	 * Called during a request to invoke all {@link HookEvent#PRE_CALL} methods.
+	 * Called during a request to invoke all {@link RestPreCall} methods.
 	 *
 	 * @param session The current request.
 	 * @throws Throwable If thrown from call methods.
@@ -6915,7 +6949,7 @@ public class RestContext extends Context {
 	}
 
 	/**
-	 * Called during a request to invoke all {@link HookEvent#POST_CALL} methods.
+	 * Called during a request to invoke all {@link RestPostCall} methods.
 	 *
 	 * @param session The current request.
 	 * @throws Throwable If thrown from call methods.
@@ -6926,14 +6960,14 @@ public class RestContext extends Context {
 	}
 
 	/**
-	 * Called at the end of a request to invoke all {@link HookEvent#END_CALL} methods.
+	 * Called at the end of a request to invoke all {@link RestEndCall} methods.
 	 *
 	 * <p>
 	 * This is the very last method called in {@link #execute(Object, HttpServletRequest, HttpServletResponse)}.
 	 *
 	 * @param session The current request.
 	 */
-	protected void finishCall(RestSession session) {
+	protected void endCall(RestSession session) {
 		for (MethodInvoker x : endCallMethods) {
 			try {
 				x.invoke(session.getBeanStore(), session.getResource());
@@ -6944,7 +6978,7 @@ public class RestContext extends Context {
 	}
 
 	/**
-	 * Called during servlet initialization to invoke all {@link HookEvent#POST_INIT} methods.
+	 * Called during servlet initialization to invoke all {@link RestPostInit} child-last methods.
 	 *
 	 * @return This object.
 	 * @throws ServletException Error occurred.
@@ -6976,7 +7010,7 @@ public class RestContext extends Context {
 	}
 
 	/**
-	 * Called during servlet initialization to invoke all {@link HookEvent#POST_INIT_CHILD_FIRST} methods.
+	 * Called during servlet initialization to invoke all {@link RestPostInit} child-first methods.
 	 *
 	 * @return This object.
 	 * @throws ServletException Error occurred.
@@ -6997,7 +7031,7 @@ public class RestContext extends Context {
 	}
 
 	/**
-	 * Called during servlet destruction to invoke all {@link HookEvent#DESTROY} methods.
+	 * Called during servlet destruction to invoke all {@link RestDestroy} methods.
 	 */
 	public void destroy() {
 		for (MethodInvoker x : destroyMethods) {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
index e6861794f..fee7195a6 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestOpContext.java
@@ -862,7 +862,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Registered via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.converters(MyConverter.<jk>class</jk>);
 		 * 		}
@@ -1891,7 +1891,7 @@ public class RestOpContext extends Context implements Comparable<RestOpContext>
 		 * 		}
 		 *
 		 * 		<jc>// Option #3 - Defined via builder passed in through init method.</jc>
-		 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
+		 * 		<ja>@RestInit</ja>
 		 * 		<jk>public void</jk> init(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
 		 * 			<jv>builder</jv>.maxInput(<js>"10M"</js>);
 		 * 		}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestSession.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestSession.java
index 9fa1876ae..dbdf3ce7b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestSession.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestSession.java
@@ -544,9 +544,9 @@ public class RestSession extends ContextSession {
 	 * Does the following:
 	 * <ol>
 	 * 	<li>Finds the Java method to invoke and creates a {@link RestOpSession} for it.
-	 * 	<li>Invokes {@link HookEvent#PRE_CALL} methods by calling {@link RestContext#preCall(RestOpSession)}.
+	 * 	<li>Invokes {@link RestPreCall} methods by calling {@link RestContext#preCall(RestOpSession)}.
 	 * 	<li>Invokes Java method by calling {@link RestOpSession#run()}.
-	 * 	<li>Invokes {@link HookEvent#POST_CALL} methods by calling {@link RestContext#postCall(RestOpSession)}.
+	 * 	<li>Invokes {@link RestPostCall} methods by calling {@link RestContext#postCall(RestOpSession)}.
 	 * 	<li>If the Java method produced output, finds the response processor for it and runs it by calling {@link RestContext#processResponse(RestOpSession)}.
 	 * 	<li>If no Java method matched, generates a 404/405/412 by calling {@link RestContext#handleNotFound(RestSession)}.
 	 * </ol>
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HookEvent.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HookEvent.java
deleted file mode 100644
index 32de1ef37..000000000
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/HookEvent.java
+++ /dev/null
@@ -1,481 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import java.io.*;
-import java.util.*;
-import java.util.logging.*;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.config.*;
-import org.apache.juneau.cp.Messages;
-import org.apache.juneau.http.header.*;
-import org.apache.juneau.http.response.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.converter.*;
-import org.apache.juneau.rest.guard.*;
-import org.apache.juneau.rest.httppart.*;
-import org.apache.juneau.rest.matcher.*;
-
-/**
- * Identifies servlet and REST call lifecycle events which cause {@link RestHook @RestHook}-annotated Java methods
- * to be called.
- *
- * <ul class='seealso'>
- * 	<li class='link'>{@doc jrs.LifecycleHooks}
- * 	<li class='extlink'>{@source}
- * </ul>
- */
-public enum HookEvent {
-
-	/**
-	 * Identifies a method that is called immediately after the <c>HttpServlet.service(HttpServletRequest, HttpServletResponse)</c>
-	 * method is called.
-	 *
-	 * <p>
-	 * Note that you only have access to the raw request and response objects at this point.
-	 *
-	 * <p>
-	 * The list of valid parameter types are as follows:
-	 * <ul>
-	 * 	<li>Servlet request/response objects:
-	 * 		<ul>
-	 * 			<li>{@link HttpServletRequest}
-	 * 			<li>{@link HttpServletResponse}
-	 * 		</ul>
-	 * </ul>
-	 *
-	 * <h5 class='figure'>Example:</h5>
-	 * <p class='bjava'>
-	 * 	<ja>@Rest</ja>(...)
-	 * 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
-	 *
-	 * 		<jc>// Add a request attribute to all incoming requests.</jc>
-	 * 		<ja>@RestHook</ja>(<jsf>START_CALL</jsf>)
-	 * 		<jk>public void</jk> onStartCall(HttpServletRequest <jv>req</jv>) {
-	 * 			<jv>req</jv>.setAttribute(<js>"foobar"</js>, <jk>new</jk> FooBar());
-	 * 		}
-	 * 	}
-	 * </p>
-	 *
-	 * <ul class='notes'>
-	 * 	<li class='note'>
-	 * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
-	 * 	<li class='note'>
-	 * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
-	 * 	<li class='note'>
-	 * 		Static methods can be used.
-	 * 	<li class='note'>
-	 * 		Multiple START_CALL methods can be defined on a class.
-	 * 		<br>START_CALL methods on parent classes are invoked before START_CALL methods on child classes.
-	 * 		<br>The order of START_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
-	 * 	<li class='note'>
-	 * 		The method can throw any exception.
-	 * 		<br>{@link BasicHttpException BasicHttpExceptions} can be thrown to cause a particular HTTP error status code.
-	 * 		<br>All other exceptions cause an HTTP 500 error status code.
-	 * 	<li class='note'>
-	 * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
-	 * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
-	 * 		overridden by the child class.
-	 * </ul>
-	 */
-	START_CALL,
-
-	/**
-	 * Identifies a method that gets called immediately before the <ja>@RestOp</ja> annotated method gets called.
-	 *
-	 * <p>
-	 * At this point, the {@link RestRequest} object has been fully initialized, and all {@link RestGuard} and
-	 * {@link RestMatcher} objects have been called.
-	 *
-	 * <p>
-	 * The list of valid parameter types are as follows:
-	 * <ul>
-	 * 	<li>Servlet request/response objects:
-	 * 		<ul>
-	 * 			<li>{@link HttpServletRequest}
-	 * 			<li>{@link HttpServletResponse}
-	 * 		</ul>
-	 * 	<li>Extended request/response objects:
-	 * 		<ul>
-	 * 			<li>{@link RestRequest}
-	 * 			<li>{@link RestResponse}
-	 * 		</ul>
-	 * 	<li>Header objects:
-	 * 		<ul>
-	 * 			<li>{@link Accept}
-	 * 			<li>{@link AcceptCharset}
-	 * 			<li>{@link AcceptEncoding}
-	 * 			<li>{@link AcceptLanguage}
-	 * 			<li>{@link Authorization}
-	 * 			<li>{@link CacheControl}
-	 * 			<li>{@link Connection}
-	 * 			<li>{@link ContentLength}
-	 * 			<li>{@link ContentType}
-	 * 			<li>{@link org.apache.juneau.http.header.Date}
-	 * 			<li>{@link Expect}
-	 * 			<li>{@link From}
-	 * 			<li>{@link Host}
-	 * 			<li>{@link IfMatch}
-	 * 			<li>{@link IfModifiedSince}
-	 * 			<li>{@link IfNoneMatch}
-	 * 			<li>{@link IfRange}
-	 * 			<li>{@link IfUnmodifiedSince}
-	 * 			<li>{@link MaxForwards}
-	 * 			<li>{@link Pragma}
-	 * 			<li>{@link ProxyAuthorization}
-	 * 			<li>{@link Range}
-	 * 			<li>{@link Referer}
-	 * 			<li>{@link TE}
-	 * 			<li>{@link UserAgent}
-	 * 			<li>{@link Upgrade}
-	 * 			<li>{@link Via}
-	 * 			<li>{@link Warning}
-	 * 			<li>{@link TimeZone}
-	 * 		</ul>
-	 * 	<li>Other objects:
-	 * 		<ul>
-	 * 			<li>{@link ResourceBundle}
-	 * 			<li>{@link Messages}
-	 * 			<li>{@link InputStream}
-	 * 			<li>{@link ServletInputStream}
-	 * 			<li>{@link Reader}
-	 * 			<li>{@link OutputStream}
-	 * 			<li>{@link ServletOutputStream}
-	 * 			<li>{@link Writer}
-	 * 			<li>{@link RequestHeaders}
-	 * 			<li>{@link RequestQueryParams}
-	 * 			<li>{@link RequestFormParams}
-	 * 			<li>{@link RequestPathParams}
-	 * 			<li>{@link Logger}
-	 * 			<li>{@link RestContext}
-	 * 			<li>{@link org.apache.juneau.parser.Parser}
-	 * 			<li>{@link Locale}
-	 * 			<li>{@link Swagger}
-	 * 			<li>{@link RequestContent}
-	 * 			<li>{@link Config}
-	 * 			<li>{@link UriContext}
-	 * 			<li>{@link UriResolver}
-	 * 		</ul>
-	 * </ul>
-	 *
-	 * <h5 class='figure'>Example:</h5>
-	 * <p class='bjava'>
-	 * 	<ja>@Rest</ja>(...)
-	 * 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
-	 *
-	 * 		<jc>// Log the incoming request.</jc>
-	 * 		<ja>@RestHook</ja>(<jsf>PRE_CALL</jsf>)
-	 * 		<jk>public void</jk> onPreCall(Accept <jv>accept</jv>, Logger <jv>logger</jv>) {
-	 * 			<jv>logger</jv>.fine(<js>"Accept {0} header found."</js>, <jv>accept</jv>);
-	 * 		}
-	 * 	}
-	 * </p>
-	 *
-	 * <ul class='notes'>
-	 * 	<li class='note'>
-	 * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
-	 * 	<li class='note'>
-	 * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
-	 * 	<li class='note'>
-	 * 		Static methods can be used.
-	 * 	<li class='note'>
-	 * 		Multiple PRE_CALL methods can be defined on a class.
-	 * 		<br>PRE_CALL methods on parent classes are invoked before PRE_CALL methods on child classes.
-	 * 		<br>The order of PRE_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
-	 * 	<li class='note'>
-	 * 		The method can throw any exception.
-	 * 		<br>{@link BasicHttpException BasicHttpExceptions} can be thrown to cause a particular HTTP error status code.
-	 * 		<br>All other exceptions cause an HTTP 500 error status code.
-	 * 	<li class='note'>
-	 * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
-	 * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
-	 * 		overridden by the child class.
-	 * 	<li class='note'>
-	 * 		It's advisable not to mess around with the HTTP content itself since you may end up consuming the content
-	 * 		before the actual REST method has a chance to use it.
-	 * </ul>
-	 */
-	PRE_CALL,
-
-	/**
-	 * Identifies a method that gets called immediately after the <ja>@RestOp</ja> annotated method gets called.
-	 *
-	 * <p>
-	 * At this point, the output object returned by the method call has been set on the response, but
-	 * {@link RestConverter RestConverters} have not yet been executed and the response has not yet been written.
-	 *
-	 * <p>
-	 * The list of valid parameter types are the same as {@link #PRE_CALL}.
-	 *
-	 * <h5 class='figure'>Example:</h5>
-	 * <p class='bjava'>
-	 * 	<ja>@Rest</ja>(...)
-	 * 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
-	 *
-	 * 		<jc>// Log the result of the request.</jc>
-	 * 		<ja>@RestHook</ja>(<jsf>POST_CALL</jsf>)
-	 * 		<jk>public void</jk> onPostCall(RestResponse <jv>res</jv>, Logger <jv>logger</jv>) {
-	 * 			<jv>logger</jv>.fine(<js>Output {0} was set on the response."</js>, <jv>res</jv>.getOutput());
-	 * 		}
-	 * 	}
-	 * </p>
-	 *
-	 * <ul class='notes'>
-	 * 	<li class='note'>
-	 * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
-	 * 	<li class='note'>
-	 * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
-	 * 	<li class='note'>
-	 * 		Static methods can be used.
-	 * 	<li class='note'>
-	 * 		Multiple POST_CALL methods can be defined on a class.
-	 * 		<br>POST_CALL methods on parent classes are invoked before POST_CALL methods on child classes.
-	 * 		<br>The order of POST_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
-	 * 	<li class='note'>
-	 * 		The method can throw any exception, although at this point it is too late to set an HTTP error status code.
-	 * 	<li class='note'>
-	 * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
-	 * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
-	 * 		overridden by the child class.
-	 * </ul>
-	 */
-	POST_CALL,
-
-	/**
-	 * Identifies a method that gets called right before we exit the servlet service method.
-	 *
-	 * <p>
-	 * At this point, the output has been written and flushed.
-	 *
-	 * <p>
-	 * The list of valid parameter types are as follows:
-	 * <ul>
-	 * 	<li>Servlet request/response objects:
-	 * 		<ul>
-	 * 			<li>{@link HttpServletRequest}
-	 * 			<li>{@link HttpServletResponse}
-	 * 		</ul>
-	 * </ul>
-	 *
-	 * <p>
-	 * The following attributes are set on the {@link HttpServletRequest} object that can be useful for logging purposes:
-	 * <ul>
-	 * 	<li><js>"Exception"</js> - Any exceptions thrown during the request.
-	 * 	<li><js>"ExecTime"</js> - Execution time of the request.
-	 * </ul>
-	 *
-	 * <h5 class='figure'>Example:</h5>
-	 * <p class='bjava'>
-	 * 	<ja>@Rest</ja>(...)
-	 * 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
-	 *
-	 * 		<jc>// Log the time it took to execute the request.</jc>
-	 * 		<ja>@RestHook</ja>(<jsf>END_CALL</jsf>)
-	 * 		<jk>public void</jk> onEndCall(HttpServletRequest <jv>req</jv>, Logger <jv>logger</jv>) {
-	 * 			Exception <jv>exception</jv> = (Exception)<jv>req</jv>.getAttribute(<js>"Exception"</js>);
-	 * 			Long <jv>execTime</jv> = (Long)<jv>req</jv>.getAttribute(<js>"ExecTime"</js>);
-	 * 			<jk>if</jk> (<jv>exception</jv> != <jk>null</jk>)
-	 * 				<jv>logger</jv>.warn(<jv>exception</jv>, <js>"Request failed in {0}ms."</js>, <jv>execTime</jv>);
-	 * 			<jk>else</jk>
-	 * 				<jv>logger</jv>.fine(<js>"Request finished in {0}ms."</js>, <jv>execTime</jv>);
-	 * 		}
-	 * 	}
-	 * </p>
-	 *
-	 * <ul class='notes'>
-	 * 	<li class='note'>
-	 * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
-	 * 	<li class='note'>
-	 * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
-	 * 	<li class='note'>
-	 * 		Static methods can be used.
-	 * 	<li class='note'>
-	 * 		Multiple END_CALL methods can be defined on a class.
-	 * 		<br>END_CALL methods on parent classes are invoked before END_CALL methods on child classes.
-	 * 		<br>The order of END_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
-	 * 	<li class='note'>
-	 * 		The method can throw any exception, although at this point it is too late to set an HTTP error status code.
-	 * 	<li class='note'>
-	 * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
-	 * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
-	 * 		overridden by the child class.
-	 * </ul>
-	 */
-	END_CALL,
-
-	/**
-	 * Identifies a method that gets called during servlet initialization.
-	 *
-	 * <p>
-	 * This method is called from within the {@link Servlet#init(ServletConfig)} method after the {@link org.apache.juneau.rest.RestContext.Builder}
-	 * object has been created and initialized with the annotations defined on the class, but before the
-	 * {@link RestContext} object has been created.
-	 *
-	 * <p>
-	 * The only valid parameter type for this method is {@link org.apache.juneau.rest.RestContext.Builder} which can be used to configure the servlet.
-	 *
-	 * <p>
-	 * An example of this is the <c>PetStoreResource</c> class that uses an init method to perform initialization
-	 * of an internal data structure.
-	 *
-	 * <h5 class='figure'>Example:</h5>
-	 * <p class='bjava'>
-	 * 	<ja>@Rest</ja>(...)
-	 * 	<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalJenaConfig {
-	 *
-	 * 		<jc>// Our database.</jc>
-	 * 		<jk>private</jk> Map&lt;Integer,Pet&gt; <jf>petDB</jf>;
-	 *
-	 * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
-	 * 		<jk>public void</jk> onInit(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
-	 * 			<jc>// Load our database from a local JSON file.</jc>
-	 * 			<jf>petDB</jf> = JsonParser.<jsf>DEFAULT</jsf>.parse(getClass().getResourceAsStream(<js>"PetStore.json"</js>), LinkedHashMap.<jk>class</jk>, Integer.<jk>class</jk>, Pet.<jk>class</jk>);
-	 * 		}
-	 * 	}
-	 * </p>
-	 *
-	 * <ul class='notes'>
-	 * 	<li class='note'>
-	 * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
-	 * 	<li class='note'>
-	 * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
-	 * 	<li class='note'>
-	 * 		Static methods can be used.
-	 * 	<li class='note'>
-	 * 		Multiple INIT methods can be defined on a class.
-	 * 		<br>INIT methods on parent classes are invoked before INIT methods on child classes.
-	 * 		<br>The order of INIT method invocations within a class is alphabetical, then by parameter count, then by parameter types.
-	 * 	<li class='note'>
-	 * 		The method can throw any exception causing initialization of the servlet to fail.
-	 * 	<li class='note'>
-	 * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
-	 * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
-	 * 		overridden by the child class.
-	 * </ul>
-	 */
-	INIT,
-
-	/**
-	 * Identifies a method that gets called immediately after servlet initialization.
-	 *
-	 * <p>
-	 * This method is called from within the {@link Servlet#init(ServletConfig)} method after the {@link RestContext}
-	 * object has been created.
-	 *
-	 * <p>
-	 * The only valid parameter type for this method is {@link RestContext} which can be used to retrieve information
-	 * about the servlet.
-	 *
-	 * <ul class='notes'>
-	 * 	<li class='note'>
-	 * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
-	 * 	<li class='note'>
-	 * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
-	 * 	<li class='note'>
-	 * 		Static methods can be used.
-	 * 	<li class='note'>
-	 * 		Multiple POST_INIT methods can be defined on a class.
-	 * 		<br>POST_INIT methods on parent classes are invoked before POST_INIT methods on child classes.
-	 * 		<br>The order of POST_INIT method invocations within a class is alphabetical, then by parameter count, then by parameter types.
-	 * 	<li class='note'>
-	 * 		The method can throw any exception causing initialization of the servlet to fail.
-	 * 	<li class='note'>
-	 * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
-	 * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
-	 * 		overridden by the child class.
-	 * </ul>
-	 */
-	POST_INIT,
-
-	/**
-	 * Identical to {@link #POST_INIT} except the order of execution is child-resources first.
-	 *
-	 * <p>
-	 * Use this annotation if you need to perform any kind of initialization on child resources before the parent resource.
-	 *
-	 * <p>
-	 * This method is called from within the {@link Servlet#init(ServletConfig)} method after the {@link RestContext}
-	 * object has been created and after the {@link #POST_INIT} methods have been called.
-	 *
-	 * <p>
-	 * The only valid parameter type for this method is {@link RestContext} which can be used to retrieve information
-	 * about the servlet.
-	 *
-	 * <ul class='notes'>
-	 * 	<li class='note'>
-	 * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
-	 * 	<li class='note'>
-	 * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
-	 * 	<li class='note'>
-	 * 		Static methods can be used.
-	 * 	<li class='note'>
-	 * 		Multiple POST_INIT_CHILD_FIRST methods can be defined on a class.
-	 * 		<br>POST_INIT_CHILD_FIRST methods on parent classes are invoked before POST_INIT_CHILD_FIRST methods on child classes.
-	 * 		<br>The order of POST_INIT_CHILD_FIRST method invocations within a class is alphabetical, then by parameter count, then by parameter types.
-	 * 	<li class='note'>
-	 * 		The method can throw any exception causing initialization of the servlet to fail.
-	 * </ul>
-	 */
-	POST_INIT_CHILD_FIRST,
-
-	/**
-	 * Identifies a method that gets called during servlet destroy.
-	 *
-	 * <p>
-	 * This method is called from within the {@link Servlet#destroy()}.
-	 *
-	 * <p>
-	 * The only valid parameter type for this method is {@link RestContext}, although typically no arguments will
-	 * be specified.
-	 *
-	 * <h5 class='figure'>Example:</h5>
-	 * <p class='bjava'>
-	 * 	<ja>@Rest</ja>(...)
-	 * 	<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalJenaConfig {
-	 *
-	 * 		<jc>// Our database.</jc>
-	 * 		<jk>private</jk> Map&lt;Integer,Pet&gt; <jf>petDB</jf>;
-	 *
-	 * 		<ja>@RestHook</ja>(<jsf>DESTROY</jsf>)
-	 * 		<jk>public void</jk> onDestroy() {
-	 * 			<jf>petDB</jf> = <jk>null</jk>;
-	 * 		}
-	 * 	}
-	 * </p>
-	 *
-	 * <ul class='notes'>
-	 * 	<li class='note'>
-	 * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
-	 * 	<li class='note'>
-	 * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
-	 * 	<li class='note'>
-	 * 		Static methods can be used.
-	 * 	<li class='note'>
-	 * 		Multiple DESTROY methods can be defined on a class.
-	 * 		<br>DESTROY methods on child classes are invoked before DESTROY methods on parent classes.
-	 * 		<br>The order of DESTROY method invocations within a class is alphabetical, then by parameter count, then by parameter types.
-	 * 	<li class='note'>
-	 * 		In general, destroy methods should not throw any exceptions, although if any are thrown, the stack trace will be
-	 * 		printed to <c>System.err</c>.
-	 * 	<li class='note'>
-	 * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
-	 * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
-	 * 		overridden by the child class.
-	 * </ul>
-	 */
-	DESTROY
-}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroy.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroy.java
new file mode 100644
index 000000000..4f1c9cc3f
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroy.java
@@ -0,0 +1,100 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+import javax.servlet.*;
+
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.servlet.*;
+
+/**
+ * Identifies a method that gets called during servlet destroy.
+ *
+ * <p>
+ * This method is called from within the {@link Servlet#destroy()}.
+ *
+ * <p>
+ * The only valid parameter type for this method is {@link RestContext}, although typically no arguments will
+ * be specified.
+ *
+ * <h5 class='figure'>Example:</h5>
+ * <p class='bjava'>
+ * 	<ja>@Rest</ja>(...)
+ * 	<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalJenaConfig {
+ *
+ * 		<jc>// Our database.</jc>
+ * 		<jk>private</jk> Map&lt;Integer,Pet&gt; <jf>petDB</jf>;
+ *
+ * 		<ja>@RestDestroy</ja>
+ * 		<jk>public void</jk> onDestroy() {
+ * 			<jf>petDB</jf> = <jk>null</jk>;
+ * 		}
+ * 	}
+ * </p>
+ *
+ * <ul class='notes'>
+ * 	<li class='note'>
+ * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
+ * 	<li class='note'>
+ * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
+ * 	<li class='note'>
+ * 		Static methods can be used.
+ * 	<li class='note'>
+ * 		Multiple destroy methods can be defined on a class.
+ * 		<br>Destroy methods on child classes are invoked before destroy methods on parent classes.
+ * 		<br>The order of destroy method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+ * 	<li class='note'>
+ * 		In general, destroy methods should not throw any exceptions, although if any are thrown, the stack trace will be
+ * 		printed to <c>System.err</c>.
+ * 	<li class='note'>
+ * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
+ * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
+ * 		overridden by the child class.
+ * 	<li class='note'>
+ * 		The {@link RestServlet} class itself implements a method annotated with this annotation
+ * 		that can be overridden directly:
+ * 		<ul class='javatree'>
+ * 			<li class='jac'>{@link RestServlet}
+ * 			<ul>
+ * 				<li class='jm'>{@link RestServlet#onDestroy(RestContext) onDestroy(RestContext)}
+ * 			</ul>
+ * 		</ul>
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * 	<li class='link'>{@doc jrs.LifecycleHooks}
+ * 	<li class='extlink'>{@source}
+ * </ul>
+ */
+@Target({METHOD,TYPE})
+@Retention(RUNTIME)
+@Inherited
+@Repeatable(RestDestroyAnnotation.Array.class)
+public @interface RestDestroy {
+
+	/**
+	 * Dynamically apply this annotation to the specified methods.
+	 *
+	 * <ul class='seealso'>
+	 * 	<li class='link'>{@doc jm.DynamicallyAppliedAnnotations}
+	 * </ul>
+	 *
+	 * @return The annotation value.
+	 */
+	String[] on() default {};
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation.java
similarity index 81%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation.java
index d36ec77f4..dd66e57a1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation.java
@@ -20,21 +20,21 @@ import java.lang.annotation.*;
 import org.apache.juneau.annotation.*;
 
 /**
- * Utility classes and methods for the {@link RestHook @RestHook} annotation.
+ * Utility classes and methods for the {@link RestDestroy @RestDestroy} annotation.
  *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc jrs.LifecycleHooks}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class RestHookAnnotation {
+public class RestDestroyAnnotation {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/** Default value */
-	public static final RestHook DEFAULT = create().value(HookEvent.INIT).build();
+	public static final RestDestroy DEFAULT = create().build();
 
 	/**
 	 * Instantiates a new builder for this class.
@@ -58,35 +58,22 @@ public class RestHookAnnotation {
 	 */
 	public static class Builder extends TargetedAnnotationMBuilder {
 
-		HookEvent value = HookEvent.INIT;
-
 		/**
 		 * Constructor.
 		 */
 		protected Builder() {
-			super(RestHook.class);
+			super(RestDestroy.class);
 		}
 
 		/**
-		 * Instantiates a new {@link RestHook @RestHook} object initialized with this builder.
+		 * Instantiates a new {@link RestDestroy @RestDestroy} object initialized with this builder.
 		 *
-		 * @return A new {@link RestHook @RestHook} object.
+		 * @return A new {@link RestDestroy @RestDestroy} object.
 		 */
-		public RestHook build() {
+		public RestDestroy build() {
 			return new Impl(this);
 		}
 
-		/**
-		 * Sets the {@link RestHook#value()} property on this annotation.
-		 *
-		 * @param value The new value for this property.
-		 * @return This object.
-		 */
-		public Builder value(HookEvent value) {
-			this.value = value;
-			return this;
-		}
-
 		// <FluentSetters>
 
 		@Override /* GENERATED - TargetedAnnotationBuilder */
@@ -108,20 +95,12 @@ public class RestHookAnnotation {
 	// Implementation
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static class Impl extends TargetedAnnotationImpl implements RestHook {
-
-		private final HookEvent value;
+	private static class Impl extends TargetedAnnotationImpl implements RestDestroy {
 
 		Impl(Builder b) {
 			super(b);
-			this.value = b.value;
 			postConstruct();
 		}
-
-		@Override /* RestHook */
-		public HookEvent value() {
-			return value;
-		}
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -129,7 +108,7 @@ public class RestHookAnnotation {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
-	 * A collection of {@link RestHook @RestHook annotations}.
+	 * A collection of {@link RestDestroy @RestDestroy annotations}.
 	 */
 	@Documented
 	@Target({METHOD,TYPE})
@@ -142,6 +121,6 @@ public class RestHookAnnotation {
 		 *
 		 * @return The annotation value.
 		 */
-		RestHook[] value();
+		RestDestroy[] value();
 	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCall.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCall.java
new file mode 100644
index 000000000..2c58ba2f7
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCall.java
@@ -0,0 +1,114 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+import javax.servlet.http.*;
+
+import org.apache.juneau.rest.servlet.*;
+
+/**
+ * Identifies a method that gets called right before we exit the servlet service method.
+ *
+ * <p>
+ * At this point, the output has been written and flushed.
+ *
+ * <p>
+ * The list of valid parameter types are as follows:
+ * <ul>
+ * 	<li>Servlet request/response objects:
+ * 		<ul>
+ * 			<li>{@link HttpServletRequest}
+ * 			<li>{@link HttpServletResponse}
+ * 		</ul>
+ * </ul>
+ *
+ * <p>
+ * The following attributes are set on the {@link HttpServletRequest} object that can be useful for logging purposes:
+ * <ul>
+ * 	<li><js>"Exception"</js> - Any exceptions thrown during the request.
+ * 	<li><js>"ExecTime"</js> - Execution time of the request.
+ * </ul>
+ *
+ * <h5 class='figure'>Example:</h5>
+ * <p class='bjava'>
+ * 	<ja>@Rest</ja>(...)
+ * 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
+ *
+ * 		<jc>// Log the time it took to execute the request.</jc>
+ * 		<ja>@RestEndCall
+ * 		<jk>public void</jk> onEndCall(HttpServletRequest <jv>req</jv>, Logger <jv>logger</jv>) {
+ * 			Exception <jv>exception</jv> = (Exception)<jv>req</jv>.getAttribute(<js>"Exception"</js>);
+ * 			Long <jv>execTime</jv> = (Long)<jv>req</jv>.getAttribute(<js>"ExecTime"</js>);
+ * 			<jk>if</jk> (<jv>exception</jv> != <jk>null</jk>)
+ * 				<jv>logger</jv>.warn(<jv>exception</jv>, <js>"Request failed in {0}ms."</js>, <jv>execTime</jv>);
+ * 			<jk>else</jk>
+ * 				<jv>logger</jv>.fine(<js>"Request finished in {0}ms."</js>, <jv>execTime</jv>);
+ * 		}
+ * 	}
+ * </p>
+ *
+ * <ul class='notes'>
+ * 	<li class='note'>
+ * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
+ * 	<li class='note'>
+ * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
+ * 	<li class='note'>
+ * 		Static methods can be used.
+ * 	<li class='note'>
+ * 		Multiple END_CALL methods can be defined on a class.
+ * 		<br>END_CALL methods on parent classes are invoked before END_CALL methods on child classes.
+ * 		<br>The order of END_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+ * 	<li class='note'>
+ * 		The method can throw any exception, although at this point it is too late to set an HTTP error status code.
+ * 	<li class='note'>
+ * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
+ * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
+ * 		overridden by the child class.
+ * 	<li class='note'>
+ * 		The {@link RestServlet} class itself implements a convenience method annotated with this annotation
+ * 		that can be overridden directly:
+ * 		<ul class='javatree'>
+ * 			<li class='jac'>{@link RestServlet}
+ * 			<ul>
+ * 				<li class='jm'>{@link RestServlet#onEndCall(HttpServletRequest,HttpServletResponse) onEndCall(HttpServletRequest,HttpServletResponse)}
+ * 			</ul>
+ * 		</ul>
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * 	<li class='link'>{@doc jrs.LifecycleHooks}
+ * 	<li class='extlink'>{@source}
+ * </ul>
+ */
+@Target({METHOD,TYPE})
+@Retention(RUNTIME)
+@Inherited
+@Repeatable(RestEndCallAnnotation.Array.class)
+public @interface RestEndCall {
+
+	/**
+	 * Dynamically apply this annotation to the specified methods.
+	 *
+	 * <ul class='seealso'>
+	 * 	<li class='link'>{@doc jm.DynamicallyAppliedAnnotations}
+	 * </ul>
+	 *
+	 * @return The annotation value.
+	 */
+	String[] on() default {};
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation.java
similarity index 81%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation.java
index d36ec77f4..03fae8c70 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation.java
@@ -20,21 +20,21 @@ import java.lang.annotation.*;
 import org.apache.juneau.annotation.*;
 
 /**
- * Utility classes and methods for the {@link RestHook @RestHook} annotation.
+ * Utility classes and methods for the {@link RestEndCall @RestEndCall} annotation.
  *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc jrs.LifecycleHooks}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class RestHookAnnotation {
+public class RestEndCallAnnotation {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/** Default value */
-	public static final RestHook DEFAULT = create().value(HookEvent.INIT).build();
+	public static final RestEndCall DEFAULT = create().build();
 
 	/**
 	 * Instantiates a new builder for this class.
@@ -58,35 +58,22 @@ public class RestHookAnnotation {
 	 */
 	public static class Builder extends TargetedAnnotationMBuilder {
 
-		HookEvent value = HookEvent.INIT;
-
 		/**
 		 * Constructor.
 		 */
 		protected Builder() {
-			super(RestHook.class);
+			super(RestEndCall.class);
 		}
 
 		/**
-		 * Instantiates a new {@link RestHook @RestHook} object initialized with this builder.
+		 * Instantiates a new {@link RestEndCall @RestEndCall} object initialized with this builder.
 		 *
-		 * @return A new {@link RestHook @RestHook} object.
+		 * @return A new {@link RestEndCall @RestEndCall} object.
 		 */
-		public RestHook build() {
+		public RestEndCall build() {
 			return new Impl(this);
 		}
 
-		/**
-		 * Sets the {@link RestHook#value()} property on this annotation.
-		 *
-		 * @param value The new value for this property.
-		 * @return This object.
-		 */
-		public Builder value(HookEvent value) {
-			this.value = value;
-			return this;
-		}
-
 		// <FluentSetters>
 
 		@Override /* GENERATED - TargetedAnnotationBuilder */
@@ -108,20 +95,12 @@ public class RestHookAnnotation {
 	// Implementation
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static class Impl extends TargetedAnnotationImpl implements RestHook {
-
-		private final HookEvent value;
+	private static class Impl extends TargetedAnnotationImpl implements RestEndCall {
 
 		Impl(Builder b) {
 			super(b);
-			this.value = b.value;
 			postConstruct();
 		}
-
-		@Override /* RestHook */
-		public HookEvent value() {
-			return value;
-		}
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -129,7 +108,7 @@ public class RestHookAnnotation {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
-	 * A collection of {@link RestHook @RestHook annotations}.
+	 * A collection of {@link RestEndCall @RestEndCall annotations}.
 	 */
 	@Documented
 	@Target({METHOD,TYPE})
@@ -142,6 +121,6 @@ public class RestHookAnnotation {
 		 *
 		 * @return The annotation value.
 		 */
-		RestHook[] value();
+		RestEndCall[] value();
 	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHook.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHook.java
deleted file mode 100644
index 18877cb0d..000000000
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHook.java
+++ /dev/null
@@ -1,125 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-import java.lang.annotation.*;
-
-import javax.servlet.http.*;
-
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.servlet.*;
-
-/**
- * Identifies Java methods on a resource/servlet class that get invoked during particular lifecycle events of
- * the servlet or REST call.
- *
- * <p>
- * For example, if you want to add an initialization method to your resource:
- * <p class='bjava'>
- * 	<ja>@Rest</ja>(...)
- * 	<jk>public class</jk> MyResource  {
- *
- * 		<jc>// Our database.</jc>
- * 		<jk>private</jk> Map&lt;Integer,Object&gt; <jf>myDatabase</jf>;
- *
- * 		<ja>@RestHook</ja>(<jsf>INIT</jsf>)
- * 		<jk>public void</jk> initMyDatabase(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
- * 			<jf>myDatabase</jf> = <jk>new</jk> LinkedHashMap&lt;&gt;();
- * 		}
- * 	}
- * </p>
- *
- * <p>
- * Or if you want to intercept REST calls:
- * <p class='bjava'>
- * 	<ja>@Rest</ja>(...)
- * 	<jk>public class</jk> MyResource {
- *
- * 		<jc>// Add a request attribute to all incoming requests.</jc>
- * 		<ja>@RestHook</ja>(<jsf>PRE_CALL</jsf>)
- * 		<jk>public void</jk> onPreCall(RestRequest <jv>req</jv>) {
- * 			<jv>req</jv>.setAttribute(<js>"foo"</js>, <js>"bar"</js>);
- * 		}
- * 	}
- * </p>
- *
- * <p>
- * The hook events can be broken down into two categories:
- * <ul class='spaced-list'>
- * 	<li>Resource lifecycle events:
- * 		<ul>
- * 			<li>{@link HookEvent#INIT INIT} - Right before initialization.
- * 			<li>{@link HookEvent#POST_INIT POST_INIT} - Right after initialization.
- * 			<li>{@link HookEvent#POST_INIT_CHILD_FIRST POST_INIT_CHILD_FIRST} - Right after initialization, but run child methods first.
- * 			<li>{@link HookEvent#DESTROY DESTROY} - Right before servlet destroy.
- * 		</ul>
- * 	<li>REST call lifecycle events:
- * 		<ul>
- * 			<li>{@link HookEvent#START_CALL START_CALL} - At the beginning of a REST call.
- * 			<li>{@link HookEvent#PRE_CALL PRE_CALL} - Right before the <ja>@RestOp</ja> method is invoked.
- * 			<li>{@link HookEvent#POST_CALL POST_CALL} - Right after the <ja>@RestOp</ja> method is invoked.
- * 			<li>{@link HookEvent#END_CALL END_CALL} - At the end of the REST call after the response has been flushed.
- * 		</ul>
- * </ul>
- *
- * <ul class='notes'>
- * 	<li class='note'>
- * 		The {@link RestServlet} class itself implements several convenience methods annotated with this annotation
- * 		that can be overridden directly:
- * 		<ul class='javatree'>
- * 			<li class='jac'>{@link RestServlet}
- * 			<ul>
- * 				<li class='jm'>{@link RestServlet#onInit(RestContext.Builder) onInit(RestContext.Builder)}
- * 				<li class='jm'>{@link RestServlet#onPostInit(RestContext) onPostInit(RestContext)}
- * 				<li class='jm'>{@link RestServlet#onPostInitChildFirst(RestContext) onPostInitChildFirst(RestContext)}
- * 				<li class='jm'>{@link RestServlet#onDestroy(RestContext) onDestroy(RestContext)}
- * 				<li class='jm'>{@link RestServlet#onStartCall(HttpServletRequest,HttpServletResponse) onStartCall(HttpServletRequest,HttpServletResponse)}
- * 				<li class='jm'>{@link RestServlet#onPreCall(RestRequest,RestResponse) onPreCall(RestRequest,RestResponse)}
- * 				<li class='jm'>{@link RestServlet#onPostCall(RestRequest,RestResponse) onPostCall(RestRequest,RestResponse)}
- * 				<li class='jm'>{@link RestServlet#onEndCall(HttpServletRequest,HttpServletResponse) onEndCall(HttpServletRequest,HttpServletResponse)}
- * 			</ul>
- * 		</ul>
- * </ul>
- *
- * <ul class='seealso'>
- * 	<li class='link'>{@doc jrs.LifecycleHooks}
- * 	<li class='extlink'>{@source}
- * </ul>
- */
-@Target({METHOD,TYPE})
-@Retention(RUNTIME)
-@Inherited
-@Repeatable(RestHookAnnotation.Array.class)
-public @interface RestHook {
-
-	/**
-	 * Dynamically apply this annotation to the specified methods.
-	 *
-	 * <ul class='seealso'>
-	 * 	<li class='link'>{@doc jm.DynamicallyAppliedAnnotations}
-	 * </ul>
-	 *
-	 * @return The annotation value.
-	 */
-	String[] on() default {};
-
-	/**
-	 * The lifecycle event.
-	 *
-	 * @return The annotation value.
-	 */
-	HookEvent value() default HookEvent.INIT;
-}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInit.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInit.java
new file mode 100644
index 000000000..e6f92a5f2
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInit.java
@@ -0,0 +1,105 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+import javax.servlet.*;
+
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.servlet.*;
+
+/**
+ * Identifies a method that gets called during servlet initialization.
+ *
+ * <p>
+ * This method is called from within the {@link Servlet#init(ServletConfig)} method after the {@link org.apache.juneau.rest.RestContext.Builder}
+ * object has been created and initialized with the annotations defined on the class, but before the
+ * {@link RestContext} object has been created.
+ *
+ * <p>
+ * The only valid parameter type for this method is {@link org.apache.juneau.rest.RestContext.Builder} which can be used to configure the servlet.
+ *
+ * <p>
+ * An example of this is the <c>PetStoreResource</c> class that uses an init method to perform initialization
+ * of an internal data structure.
+ *
+ * <h5 class='figure'>Example:</h5>
+ * <p class='bjava'>
+ * 	<ja>@Rest</ja>(...)
+ * 	<jk>public class</jk> PetStoreResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalJenaConfig {
+ *
+ * 		<jc>// Our database.</jc>
+ * 		<jk>private</jk> Map&lt;Integer,Pet&gt; <jf>petDB</jf>;
+ *
+ * 		<ja>@RestInit</ja>
+ * 		<jk>public void</jk> onInit(RestContext.Builder <jv>builder</jv>) <jk>throws</jk> Exception {
+ * 			<jc>// Load our database from a local JSON file.</jc>
+ * 			<jf>petDB</jf> = JsonParser.<jsf>DEFAULT</jsf>.parse(getClass().getResourceAsStream(<js>"PetStore.json"</js>), LinkedHashMap.<jk>class</jk>, Integer.<jk>class</jk>, Pet.<jk>class</jk>);
+ * 		}
+ * 	}
+ * </p>
+ *
+ * <ul class='notes'>
+ * 	<li class='note'>
+ * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
+ * 	<li class='note'>
+ * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
+ * 	<li class='note'>
+ * 		Static methods can be used.
+ * 	<li class='note'>
+ * 		Multiple init methods can be defined on a class.
+ * 		<br>Init methods on parent classes are invoked before init methods on child classes.
+ * 		<br>The order of init method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+ * 	<li class='note'>
+ * 		The method can throw any exception causing initialization of the servlet to fail.
+ * 	<li class='note'>
+ * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
+ * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
+ * 		overridden by the child class.
+ * 	<li class='note'>
+ * 		The {@link RestServlet} class itself implements the following convenience method annotated with this annotation
+ * 		that can be overridden directly:
+ * 		<ul class='javatree'>
+ * 			<li class='jac'>{@link RestServlet}
+ * 			<ul>
+ * 				<li class='jm'>{@link RestServlet#onInit(RestContext.Builder) onInit(RestContext.Builder)}
+ * 			</ul>
+ * 		</ul>
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * 	<li class='link'>{@doc jrs.LifecycleHooks}
+ * 	<li class='extlink'>{@source}
+ * </ul>
+ */
+@Target({METHOD,TYPE})
+@Retention(RUNTIME)
+@Inherited
+@Repeatable(RestInitAnnotation.Array.class)
+public @interface RestInit {
+
+	/**
+	 * Dynamically apply this annotation to the specified methods.
+	 *
+	 * <ul class='seealso'>
+	 * 	<li class='link'>{@doc jm.DynamicallyAppliedAnnotations}
+	 * </ul>
+	 *
+	 * @return The annotation value.
+	 */
+	String[] on() default {};
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInitAnnotation.java
similarity index 82%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInitAnnotation.java
index d36ec77f4..208387621 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestInitAnnotation.java
@@ -20,21 +20,21 @@ import java.lang.annotation.*;
 import org.apache.juneau.annotation.*;
 
 /**
- * Utility classes and methods for the {@link RestHook @RestHook} annotation.
+ * Utility classes and methods for the {@link RestInit @RestInit} annotation.
  *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc jrs.LifecycleHooks}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class RestHookAnnotation {
+public class RestInitAnnotation {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/** Default value */
-	public static final RestHook DEFAULT = create().value(HookEvent.INIT).build();
+	public static final RestInit DEFAULT = create().build();
 
 	/**
 	 * Instantiates a new builder for this class.
@@ -58,35 +58,22 @@ public class RestHookAnnotation {
 	 */
 	public static class Builder extends TargetedAnnotationMBuilder {
 
-		HookEvent value = HookEvent.INIT;
-
 		/**
 		 * Constructor.
 		 */
 		protected Builder() {
-			super(RestHook.class);
+			super(RestInit.class);
 		}
 
 		/**
-		 * Instantiates a new {@link RestHook @RestHook} object initialized with this builder.
+		 * Instantiates a new {@link RestInit @RestInit} object initialized with this builder.
 		 *
-		 * @return A new {@link RestHook @RestHook} object.
+		 * @return A new {@link RestInit @RestInit} object.
 		 */
-		public RestHook build() {
+		public RestInit build() {
 			return new Impl(this);
 		}
 
-		/**
-		 * Sets the {@link RestHook#value()} property on this annotation.
-		 *
-		 * @param value The new value for this property.
-		 * @return This object.
-		 */
-		public Builder value(HookEvent value) {
-			this.value = value;
-			return this;
-		}
-
 		// <FluentSetters>
 
 		@Override /* GENERATED - TargetedAnnotationBuilder */
@@ -108,20 +95,12 @@ public class RestHookAnnotation {
 	// Implementation
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static class Impl extends TargetedAnnotationImpl implements RestHook {
-
-		private final HookEvent value;
+	private static class Impl extends TargetedAnnotationImpl implements RestInit {
 
 		Impl(Builder b) {
 			super(b);
-			this.value = b.value;
 			postConstruct();
 		}
-
-		@Override /* RestHook */
-		public HookEvent value() {
-			return value;
-		}
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -129,7 +108,7 @@ public class RestHookAnnotation {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
-	 * A collection of {@link RestHook @RestHook annotations}.
+	 * A collection of {@link RestInit @RestInit annotations}.
 	 */
 	@Documented
 	@Target({METHOD,TYPE})
@@ -142,6 +121,6 @@ public class RestHookAnnotation {
 		 *
 		 * @return The annotation value.
 		 */
-		RestHook[] value();
+		RestInit[] value();
 	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCall.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCall.java
new file mode 100644
index 000000000..0bc8b6b66
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCall.java
@@ -0,0 +1,175 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+import java.util.logging.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.config.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.http.header.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.converter.*;
+import org.apache.juneau.rest.httppart.*;
+import org.apache.juneau.rest.servlet.*;
+
+/**
+ * Identifies a method that gets called immediately after the <ja>@RestOp</ja> annotated method gets called.
+ *
+ * <p>
+ * At this point, the output object returned by the method call has been set on the response, but
+ * {@link RestConverter RestConverters} have not yet been executed and the response has not yet been written.
+ *
+ * <p>
+ * The list of valid parameter types are as follows:
+ * <ul>
+ * 	<li>Servlet request/response objects:
+ * 		<ul class='javatreec'>
+ * 			<li>{@link HttpServletRequest}
+ * 			<li>{@link HttpServletResponse}
+ * 		</ul>
+ * 	<li>Extended request/response objects:
+ * 		<ul class='javatreec'>
+ * 			<li>{@link RestRequest}
+ * 			<li>{@link RestResponse}
+ * 		</ul>
+ * 	<li>Header objects:
+ * 		<ul class='javatreec'>
+ * 			<li>{@link Accept}
+ * 			<li>{@link AcceptCharset}
+ * 			<li>{@link AcceptEncoding}
+ * 			<li>{@link AcceptLanguage}
+ * 			<li>{@link Authorization}
+ * 			<li>{@link CacheControl}
+ * 			<li>{@link Connection}
+ * 			<li>{@link ContentLength}
+ * 			<li>{@link ContentType}
+ * 			<li>{@link org.apache.juneau.http.header.Date}
+ * 			<li>{@link Expect}
+ * 			<li>{@link From}
+ * 			<li>{@link Host}
+ * 			<li>{@link IfMatch}
+ * 			<li>{@link IfModifiedSince}
+ * 			<li>{@link IfNoneMatch}
+ * 			<li>{@link IfRange}
+ * 			<li>{@link IfUnmodifiedSince}
+ * 			<li>{@link MaxForwards}
+ * 			<li>{@link Pragma}
+ * 			<li>{@link ProxyAuthorization}
+ * 			<li>{@link Range}
+ * 			<li>{@link Referer}
+ * 			<li>{@link TE}
+ * 			<li>{@link UserAgent}
+ * 			<li>{@link Upgrade}
+ * 			<li>{@link Via}
+ * 			<li>{@link Warning}
+ * 			<li>{@link TimeZone}
+ * 		</ul>
+ * 	<li>Other objects:
+ * 		<ul class='javatreec'>
+ * 			<li>{@link ResourceBundle}
+ * 			<li>{@link Messages}
+ * 			<li>{@link InputStream}
+ * 			<li>{@link ServletInputStream}
+ * 			<li>{@link Reader}
+ * 			<li>{@link OutputStream}
+ * 			<li>{@link ServletOutputStream}
+ * 			<li>{@link Writer}
+ * 			<li>{@link RequestHeaders}
+ * 			<li>{@link RequestQueryParams}
+ * 			<li>{@link RequestFormParams}
+ * 			<li>{@link RequestPathParams}
+ * 			<li>{@link Logger}
+ * 			<li>{@link RestContext}
+ * 			<li>{@link org.apache.juneau.parser.Parser}
+ * 			<li>{@link Locale}
+ * 			<li>{@link Swagger}
+ * 			<li>{@link RequestContent}
+ * 			<li>{@link Config}
+ * 			<li>{@link UriContext}
+ * 			<li>{@link UriResolver}
+ * 		</ul>
+ * </ul>
+ *
+ * <h5 class='figure'>Example:</h5>
+ * <p class='bjava'>
+ * 	<ja>@Rest</ja>(...)
+ * 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
+ *
+ * 		<jc>// Log the result of the request.</jc>
+ * 		<ja>@RestPostCall</ja>
+ * 		<jk>public void</jk> onPostCall(RestResponse <jv>res</jv>, Logger <jv>logger</jv>) {
+ * 			<jv>logger</jv>.fine(<js>Output {0} was set on the response."</js>, <jv>res</jv>.getOutput());
+ * 		}
+ * 	}
+ * </p>
+ *
+ * <ul class='notes'>
+ * 	<li class='note'>
+ * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
+ * 	<li class='note'>
+ * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
+ * 	<li class='note'>
+ * 		Static methods can be used.
+ * 	<li class='note'>
+ * 		Multiple post-call methods can be defined on a class.
+ * 		<br>Post-call methods on parent classes are invoked before post-call methods on child classes.
+ * 		<br>The order of post-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+ * 	<li class='note'>
+ * 		The method can throw any exception, although at this point it is too late to set an HTTP error status code.
+ * 	<li class='note'>
+ * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
+ * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
+ * 		overridden by the child class.
+ * 	<li class='note'>
+ * 		The {@link RestServlet} class itself implements a convenience method annotated with this annotation
+ * 		that can be overridden directly:
+ * 		<ul class='javatree'>
+ * 			<li class='jac'>{@link RestServlet}
+ * 			<ul>
+ * 				<li class='jm'>{@link RestServlet#onPostCall(RestRequest,RestResponse) onPostCall(RestRequest,RestResponse)}
+ * 			</ul>
+ * 		</ul>
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * 	<li class='link'>{@doc jrs.LifecycleHooks}
+ * 	<li class='extlink'>{@source}
+ * </ul>
+ */
+@Target({METHOD,TYPE})
+@Retention(RUNTIME)
+@Inherited
+@Repeatable(RestPostCallAnnotation.Array.class)
+public @interface RestPostCall {
+
+	/**
+	 * Dynamically apply this annotation to the specified methods.
+	 *
+	 * <ul class='seealso'>
+	 * 	<li class='link'>{@doc jm.DynamicallyAppliedAnnotations}
+	 * </ul>
+	 *
+	 * @return The annotation value.
+	 */
+	String[] on() default {};
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation.java
similarity index 81%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation.java
index d36ec77f4..3f435ff53 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation.java
@@ -20,21 +20,21 @@ import java.lang.annotation.*;
 import org.apache.juneau.annotation.*;
 
 /**
- * Utility classes and methods for the {@link RestHook @RestHook} annotation.
+ * Utility classes and methods for the {@link RestPostCall @RestPostCall} annotation.
  *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc jrs.LifecycleHooks}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class RestHookAnnotation {
+public class RestPostCallAnnotation {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/** Default value */
-	public static final RestHook DEFAULT = create().value(HookEvent.INIT).build();
+	public static final RestPostCall DEFAULT = create().build();
 
 	/**
 	 * Instantiates a new builder for this class.
@@ -58,35 +58,22 @@ public class RestHookAnnotation {
 	 */
 	public static class Builder extends TargetedAnnotationMBuilder {
 
-		HookEvent value = HookEvent.INIT;
-
 		/**
 		 * Constructor.
 		 */
 		protected Builder() {
-			super(RestHook.class);
+			super(RestPostCall.class);
 		}
 
 		/**
-		 * Instantiates a new {@link RestHook @RestHook} object initialized with this builder.
+		 * Instantiates a new {@link RestPostCall @RestPostCall} object initialized with this builder.
 		 *
-		 * @return A new {@link RestHook @RestHook} object.
+		 * @return A new {@link RestPostCall @RestPostCall} object.
 		 */
-		public RestHook build() {
+		public RestPostCall build() {
 			return new Impl(this);
 		}
 
-		/**
-		 * Sets the {@link RestHook#value()} property on this annotation.
-		 *
-		 * @param value The new value for this property.
-		 * @return This object.
-		 */
-		public Builder value(HookEvent value) {
-			this.value = value;
-			return this;
-		}
-
 		// <FluentSetters>
 
 		@Override /* GENERATED - TargetedAnnotationBuilder */
@@ -108,20 +95,12 @@ public class RestHookAnnotation {
 	// Implementation
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static class Impl extends TargetedAnnotationImpl implements RestHook {
-
-		private final HookEvent value;
+	private static class Impl extends TargetedAnnotationImpl implements RestPostCall {
 
 		Impl(Builder b) {
 			super(b);
-			this.value = b.value;
 			postConstruct();
 		}
-
-		@Override /* RestHook */
-		public HookEvent value() {
-			return value;
-		}
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -129,7 +108,7 @@ public class RestHookAnnotation {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
-	 * A collection of {@link RestHook @RestHook annotations}.
+	 * A collection of {@link RestPostCall @RestPostCall annotations}.
 	 */
 	@Documented
 	@Target({METHOD,TYPE})
@@ -142,6 +121,6 @@ public class RestHookAnnotation {
 		 *
 		 * @return The annotation value.
 		 */
-		RestHook[] value();
+		RestPostCall[] value();
 	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInit.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInit.java
new file mode 100644
index 000000000..7b13935e0
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInit.java
@@ -0,0 +1,95 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+import javax.servlet.*;
+
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.servlet.*;
+
+/**
+ * Identifies a method that gets called immediately after servlet initialization.
+ *
+ * <p>
+ * This method is called from within the {@link Servlet#init(ServletConfig)} method after the {@link RestContext}
+ * object has been created.
+ *
+ * <p>
+ * The only valid parameter type for this method is {@link RestContext} which can be used to retrieve information
+ * about the servlet.
+ *
+ * <ul class='notes'>
+ * 	<li class='note'>
+ * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
+ * 	<li class='note'>
+ * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
+ * 	<li class='note'>
+ * 		Static methods can be used.
+ * 	<li class='note'>
+ * 		Multiple post-init methods can be defined on a class.
+ * 		<br>Post-init methods on parent classes are invoked before post-init methods on child classes unless {@link #childFirst()} is specified.
+ * 		<br>The order of Post-init method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+ * 	<li class='note'>
+ * 		The method can throw any exception causing initialization of the servlet to fail.
+ * 	<li class='note'>
+ * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
+ * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
+ * 		overridden by the child class.
+ * 	<li class='note'>
+ * 		The {@link RestServlet} class itself implements the following convenience methods annotated with this annotation
+ * 		that can be overridden directly:
+ * 		<ul class='javatree'>
+ * 			<li class='jac'>{@link RestServlet}
+ * 			<ul>
+ * 				<li class='jm'>{@link RestServlet#onPostInit(RestContext) onPostInit(RestContext)}
+ * 				<li class='jm'>{@link RestServlet#onPostInitChildFirst(RestContext) onPostInitChildFirst(RestContext)}
+ * 			</ul>
+ * 		</ul>
+ * </ul>
+ */
+@Target({METHOD,TYPE})
+@Retention(RUNTIME)
+@Inherited
+@Repeatable(RestPostInitAnnotation.Array.class)
+public @interface RestPostInit {
+
+	/**
+	 * Execute in child-first order.
+	 *
+	 * <p>
+	 * Use this annotation if you need to perform any kind of initialization on child resources before the parent resource.
+	 *
+	 * <p>
+	 * This method is called from within the {@link Servlet#init(ServletConfig)} method after the {@link RestContext}
+	 * object has been created and after the non-child-first methods have been called.
+	 *
+	 * @return The annotation value.
+	 */
+	boolean childFirst() default false;
+
+	/**
+	 * Dynamically apply this annotation to the specified methods.
+	 *
+	 * <ul class='seealso'>
+	 * 	<li class='link'>{@doc jm.DynamicallyAppliedAnnotations}
+	 * </ul>
+	 *
+	 * @return The annotation value.
+	 */
+	String[] on() default {};
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation.java
similarity index 83%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation.java
index d36ec77f4..3578744b2 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation.java
@@ -20,21 +20,21 @@ import java.lang.annotation.*;
 import org.apache.juneau.annotation.*;
 
 /**
- * Utility classes and methods for the {@link RestHook @RestHook} annotation.
+ * Utility classes and methods for the {@link RestPostInit @RestPostInit} annotation.
  *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc jrs.LifecycleHooks}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class RestHookAnnotation {
+public class RestPostInitAnnotation {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/** Default value */
-	public static final RestHook DEFAULT = create().value(HookEvent.INIT).build();
+	public static final RestPostInit DEFAULT = create().build();
 
 	/**
 	 * Instantiates a new builder for this class.
@@ -58,32 +58,31 @@ public class RestHookAnnotation {
 	 */
 	public static class Builder extends TargetedAnnotationMBuilder {
 
-		HookEvent value = HookEvent.INIT;
+		boolean childFirst;
 
 		/**
 		 * Constructor.
 		 */
 		protected Builder() {
-			super(RestHook.class);
+			super(RestPostInit.class);
 		}
 
 		/**
-		 * Instantiates a new {@link RestHook @RestHook} object initialized with this builder.
+		 * Instantiates a new {@link RestPostInit @RestPostInit} object initialized with this builder.
 		 *
-		 * @return A new {@link RestHook @RestHook} object.
+		 * @return A new {@link RestPostInit @RestPostInit} object.
 		 */
-		public RestHook build() {
+		public RestPostInit build() {
 			return new Impl(this);
 		}
 
 		/**
-		 * Sets the {@link RestHook#value()} property on this annotation.
+		 * Sets the {@link RestPostInit#childFirst()} property on this annotation.
 		 *
-		 * @param value The new value for this property.
 		 * @return This object.
 		 */
-		public Builder value(HookEvent value) {
-			this.value = value;
+		public Builder childFirst() {
+			this.childFirst = true;
 			return this;
 		}
 
@@ -108,19 +107,19 @@ public class RestHookAnnotation {
 	// Implementation
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static class Impl extends TargetedAnnotationImpl implements RestHook {
+	private static class Impl extends TargetedAnnotationImpl implements RestPostInit {
 
-		private final HookEvent value;
+		private final boolean childFirst;
 
 		Impl(Builder b) {
 			super(b);
-			this.value = b.value;
+			this.childFirst = b.childFirst;
 			postConstruct();
 		}
 
 		@Override /* RestHook */
-		public HookEvent value() {
-			return value;
+		public boolean childFirst() {
+			return childFirst;
 		}
 	}
 
@@ -129,7 +128,7 @@ public class RestHookAnnotation {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
-	 * A collection of {@link RestHook @RestHook annotations}.
+	 * A collection of {@link RestPostInit @RestPostInit annotations}.
 	 */
 	@Documented
 	@Target({METHOD,TYPE})
@@ -142,6 +141,6 @@ public class RestHookAnnotation {
 		 *
 		 * @return The annotation value.
 		 */
-		RestHook[] value();
+		RestPostInit[] value();
 	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCall.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCall.java
new file mode 100644
index 000000000..68b7bbd46
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCall.java
@@ -0,0 +1,182 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.io.*;
+import java.lang.annotation.*;
+import java.util.*;
+import java.util.logging.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.config.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.http.header.*;
+import org.apache.juneau.http.response.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.guard.*;
+import org.apache.juneau.rest.httppart.*;
+import org.apache.juneau.rest.matcher.*;
+import org.apache.juneau.rest.servlet.*;
+
+/**
+ * Identifies a method that gets called immediately before the <ja>@RestOp</ja> annotated method gets called.
+ *
+ * <p>
+ * At this point, the {@link RestRequest} object has been fully initialized, and all {@link RestGuard} and
+ * {@link RestMatcher} objects have been called.
+ *
+ * <p>
+ * The list of valid parameter types are as follows:
+ * <ul>
+ * 	<li>Servlet request/response objects:
+ * 		<ul class='javatreec'>
+ * 			<li>{@link HttpServletRequest}
+ * 			<li>{@link HttpServletResponse}
+ * 		</ul>
+ * 	<li>Extended request/response objects:
+ * 		<ul class='javatreec'>
+ * 			<li>{@link RestRequest}
+ * 			<li>{@link RestResponse}
+ * 		</ul>
+ * 	<li>Header objects:
+ * 		<ul class='javatreec'>
+ * 			<li>{@link Accept}
+ * 			<li>{@link AcceptCharset}
+ * 			<li>{@link AcceptEncoding}
+ * 			<li>{@link AcceptLanguage}
+ * 			<li>{@link Authorization}
+ * 			<li>{@link CacheControl}
+ * 			<li>{@link Connection}
+ * 			<li>{@link ContentLength}
+ * 			<li>{@link ContentType}
+ * 			<li>{@link org.apache.juneau.http.header.Date}
+ * 			<li>{@link Expect}
+ * 			<li>{@link From}
+ * 			<li>{@link Host}
+ * 			<li>{@link IfMatch}
+ * 			<li>{@link IfModifiedSince}
+ * 			<li>{@link IfNoneMatch}
+ * 			<li>{@link IfRange}
+ * 			<li>{@link IfUnmodifiedSince}
+ * 			<li>{@link MaxForwards}
+ * 			<li>{@link Pragma}
+ * 			<li>{@link ProxyAuthorization}
+ * 			<li>{@link Range}
+ * 			<li>{@link Referer}
+ * 			<li>{@link TE}
+ * 			<li>{@link UserAgent}
+ * 			<li>{@link Upgrade}
+ * 			<li>{@link Via}
+ * 			<li>{@link Warning}
+ * 			<li>{@link TimeZone}
+ * 		</ul>
+ * 	<li>Other objects:
+ * 		<ul class='javatreec'>
+ * 			<li>{@link ResourceBundle}
+ * 			<li>{@link Messages}
+ * 			<li>{@link InputStream}
+ * 			<li>{@link ServletInputStream}
+ * 			<li>{@link Reader}
+ * 			<li>{@link OutputStream}
+ * 			<li>{@link ServletOutputStream}
+ * 			<li>{@link Writer}
+ * 			<li>{@link RequestHeaders}
+ * 			<li>{@link RequestQueryParams}
+ * 			<li>{@link RequestFormParams}
+ * 			<li>{@link RequestPathParams}
+ * 			<li>{@link Logger}
+ * 			<li>{@link RestContext}
+ * 			<li>{@link org.apache.juneau.parser.Parser}
+ * 			<li>{@link Locale}
+ * 			<li>{@link Swagger}
+ * 			<li>{@link RequestContent}
+ * 			<li>{@link Config}
+ * 			<li>{@link UriContext}
+ * 			<li>{@link UriResolver}
+ * 		</ul>
+ * </ul>
+ *
+ * <h5 class='figure'>Example:</h5>
+ * <p class='bjava'>
+ * 	<ja>@Rest</ja>(...)
+ * 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
+ *
+ * 		<jc>// Log the incoming request.</jc>
+ * 		<ja>@RestPreCall</ja>
+ * 		<jk>public void</jk> onPreCall(Accept <jv>accept</jv>, Logger <jv>logger</jv>) {
+ * 			<jv>logger</jv>.fine(<js>"Accept {0} header found."</js>, <jv>accept</jv>);
+ * 		}
+ * 	}
+ * </p>
+ *
+ * <ul class='notes'>
+ * 	<li class='note'>
+ * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
+ * 	<li class='note'>
+ * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
+ * 	<li class='note'>
+ * 		Static methods can be used.
+ * 	<li class='note'>
+ * 		Multiple pre-call methods can be defined on a class.
+ * 		<br>Pre-call methods on parent classes are invoked before pre-call methods on child classes.
+ * 		<br>The order of pre-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+ * 	<li class='note'>
+ * 		The method can throw any exception.
+ * 		<br>{@link BasicHttpException BasicHttpExceptions} can be thrown to cause a particular HTTP error status code.
+ * 		<br>All other exceptions cause an HTTP 500 error status code.
+ * 	<li class='note'>
+ * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
+ * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
+ * 		overridden by the child class.
+ * 	<li class='note'>
+ * 		It's advisable not to mess around with the HTTP content itself since you may end up consuming the content
+ * 		before the actual REST method has a chance to use it.
+ * 	<li class='note'>
+ * 		The {@link RestServlet} class itself implements a convenience method annotated with this annotation
+ * 		that can be overridden directly:
+ * 		<ul class='javatree'>
+ * 			<li class='jac'>{@link RestServlet}
+ * 			<ul>
+ * 				<li class='jm'>{@link RestServlet#onPreCall(RestRequest,RestResponse) onPreCall(RestRequest,RestResponse)}
+ * 			</ul>
+ * 		</ul>
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * 	<li class='link'>{@doc jrs.LifecycleHooks}
+ * 	<li class='extlink'>{@source}
+ * </ul>
+ */
+@Target({METHOD,TYPE})
+@Retention(RUNTIME)
+@Inherited
+@Repeatable(RestPreCallAnnotation.Array.class)
+public @interface RestPreCall {
+
+	/**
+	 * Dynamically apply this annotation to the specified methods.
+	 *
+	 * <ul class='seealso'>
+	 * 	<li class='link'>{@doc jm.DynamicallyAppliedAnnotations}
+	 * </ul>
+	 *
+	 * @return The annotation value.
+	 */
+	String[] on() default {};
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation.java
similarity index 81%
copy from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
copy to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation.java
index d36ec77f4..9dd9558ee 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation.java
@@ -20,21 +20,21 @@ import java.lang.annotation.*;
 import org.apache.juneau.annotation.*;
 
 /**
- * Utility classes and methods for the {@link RestHook @RestHook} annotation.
+ * Utility classes and methods for the {@link RestPreCall @RestPreCall} annotation.
  *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc jrs.LifecycleHooks}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class RestHookAnnotation {
+public class RestPreCallAnnotation {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/** Default value */
-	public static final RestHook DEFAULT = create().value(HookEvent.INIT).build();
+	public static final RestPreCall DEFAULT = create().build();
 
 	/**
 	 * Instantiates a new builder for this class.
@@ -58,35 +58,22 @@ public class RestHookAnnotation {
 	 */
 	public static class Builder extends TargetedAnnotationMBuilder {
 
-		HookEvent value = HookEvent.INIT;
-
 		/**
 		 * Constructor.
 		 */
 		protected Builder() {
-			super(RestHook.class);
+			super(RestPreCall.class);
 		}
 
 		/**
-		 * Instantiates a new {@link RestHook @RestHook} object initialized with this builder.
+		 * Instantiates a new {@link RestPreCall @RestPreCall} object initialized with this builder.
 		 *
-		 * @return A new {@link RestHook @RestHook} object.
+		 * @return A new {@link RestPreCall @RestPreCall} object.
 		 */
-		public RestHook build() {
+		public RestPreCall build() {
 			return new Impl(this);
 		}
 
-		/**
-		 * Sets the {@link RestHook#value()} property on this annotation.
-		 *
-		 * @param value The new value for this property.
-		 * @return This object.
-		 */
-		public Builder value(HookEvent value) {
-			this.value = value;
-			return this;
-		}
-
 		// <FluentSetters>
 
 		@Override /* GENERATED - TargetedAnnotationBuilder */
@@ -108,20 +95,12 @@ public class RestHookAnnotation {
 	// Implementation
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static class Impl extends TargetedAnnotationImpl implements RestHook {
-
-		private final HookEvent value;
+	private static class Impl extends TargetedAnnotationImpl implements RestPreCall {
 
 		Impl(Builder b) {
 			super(b);
-			this.value = b.value;
 			postConstruct();
 		}
-
-		@Override /* RestHook */
-		public HookEvent value() {
-			return value;
-		}
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -129,7 +108,7 @@ public class RestHookAnnotation {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
-	 * A collection of {@link RestHook @RestHook annotations}.
+	 * A collection of {@link RestPreCall @RestPreCall annotations}.
 	 */
 	@Documented
 	@Target({METHOD,TYPE})
@@ -142,6 +121,6 @@ public class RestHookAnnotation {
 		 *
 		 * @return The annotation value.
 		 */
-		RestHook[] value();
+		RestPreCall[] value();
 	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCall.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCall.java
new file mode 100644
index 000000000..632237d21
--- /dev/null
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCall.java
@@ -0,0 +1,106 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.*;
+
+import javax.servlet.http.*;
+
+import org.apache.juneau.http.response.*;
+import org.apache.juneau.rest.servlet.*;
+
+/**
+ * Identifies a method that is called immediately after the <c>HttpServlet.service(HttpServletRequest, HttpServletResponse)</c>
+ * method is called.
+ *
+ * <p>
+ * Note that you only have access to the raw request and response objects at this point.
+ *
+ * <p>
+ * The list of valid parameter types are as follows:
+ * <ul>
+ * 	<li>Servlet request/response objects:
+ * 		<ul>
+ * 			<li>{@link HttpServletRequest}
+ * 			<li>{@link HttpServletResponse}
+ * 		</ul>
+ * </ul>
+ *
+ * <h5 class='figure'>Example:</h5>
+ * <p class='bjava'>
+ * 	<ja>@Rest</ja>(...)
+ * 	<jk>public class</jk> MyResource <jk>extends</jk> BasicRestServlet <jk>implements</jk> BasicUniversalConfig {
+ *
+ * 		<jc>// Add a request attribute to all incoming requests.</jc>
+ * 		<ja>@RestStartCall</ja>
+ * 		<jk>public void</jk> onStartCall(HttpServletRequest <jv>req</jv>) {
+ * 			<jv>req</jv>.setAttribute(<js>"foobar"</js>, <jk>new</jk> FooBar());
+ * 		}
+ * 	}
+ * </p>
+ *
+ * <ul class='notes'>
+ * 	<li class='note'>
+ * 		The method should return <jk>void</jk> although if it does return any value, the value will be ignored.
+ * 	<li class='note'>
+ * 		The method should be <jk>public</jk> although other visibilities are valid if the security manager allows it.
+ * 	<li class='note'>
+ * 		Static methods can be used.
+ * 	<li class='note'>
+ * 		Multiple start-call methods can be defined on a class.
+ * 		<br>Start call methods on parent classes are invoked before start-call methods on child classes.
+ * 		<br>The order of start-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+ * 	<li class='note'>
+ * 		The method can throw any exception.
+ * 		<br>{@link BasicHttpException BasicHttpExceptions} can be thrown to cause a particular HTTP error status code.
+ * 		<br>All other exceptions cause an HTTP 500 error status code.
+ * 	<li class='note'>
+ * 		Note that if you override a parent method, you probably need to call <code><jk>super</jk>.parentMethod(...)</code>.
+ * 		<br>The method is still considered part of the parent class for ordering purposes even though it's
+ * 		overridden by the child class.
+ * 	<li class='note'>
+ * 		The {@link RestServlet} class itself implements a convenience method annotated with this annotation
+ * 		that can be overridden directly:
+ * 		<ul class='javatree'>
+ * 			<li class='jac'>{@link RestServlet}
+ * 			<ul>
+ * 				<li class='jm'>{@link RestServlet#onStartCall(HttpServletRequest,HttpServletResponse) onStartCall(HttpServletRequest,HttpServletResponse)}
+ * 			</ul>
+ * 		</ul>
+ * </ul>
+ *
+ * <ul class='seealso'>
+ * 	<li class='link'>{@doc jrs.LifecycleHooks}
+ * 	<li class='extlink'>{@source}
+ * </ul>
+ */
+@Target({METHOD,TYPE})
+@Retention(RUNTIME)
+@Inherited
+@Repeatable(RestStartCallAnnotation.Array.class)
+public @interface RestStartCall {
+
+	/**
+	 * Dynamically apply this annotation to the specified methods.
+	 *
+	 * <ul class='seealso'>
+	 * 	<li class='link'>{@doc jm.DynamicallyAppliedAnnotations}
+	 * </ul>
+	 *
+	 * @return The annotation value.
+	 */
+	String[] on() default {};
+}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation.java
similarity index 81%
rename from juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
rename to juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation.java
index d36ec77f4..0388ce421 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestHookAnnotation.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation.java
@@ -20,21 +20,21 @@ import java.lang.annotation.*;
 import org.apache.juneau.annotation.*;
 
 /**
- * Utility classes and methods for the {@link RestHook @RestHook} annotation.
+ * Utility classes and methods for the {@link RestStartCall @RestStartCall} annotation.
  *
  * <ul class='seealso'>
  * 	<li class='link'>{@doc jrs.LifecycleHooks}
  * 	<li class='extlink'>{@source}
  * </ul>
  */
-public class RestHookAnnotation {
+public class RestStartCallAnnotation {
 
 	//-----------------------------------------------------------------------------------------------------------------
 	// Static
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/** Default value */
-	public static final RestHook DEFAULT = create().value(HookEvent.INIT).build();
+	public static final RestStartCall DEFAULT = create().build();
 
 	/**
 	 * Instantiates a new builder for this class.
@@ -58,35 +58,22 @@ public class RestHookAnnotation {
 	 */
 	public static class Builder extends TargetedAnnotationMBuilder {
 
-		HookEvent value = HookEvent.INIT;
-
 		/**
 		 * Constructor.
 		 */
 		protected Builder() {
-			super(RestHook.class);
+			super(RestStartCall.class);
 		}
 
 		/**
-		 * Instantiates a new {@link RestHook @RestHook} object initialized with this builder.
+		 * Instantiates a new {@link RestStartCall @RestStartCall} object initialized with this builder.
 		 *
-		 * @return A new {@link RestHook @RestHook} object.
+		 * @return A new {@link RestStartCall @RestStartCall} object.
 		 */
-		public RestHook build() {
+		public RestStartCall build() {
 			return new Impl(this);
 		}
 
-		/**
-		 * Sets the {@link RestHook#value()} property on this annotation.
-		 *
-		 * @param value The new value for this property.
-		 * @return This object.
-		 */
-		public Builder value(HookEvent value) {
-			this.value = value;
-			return this;
-		}
-
 		// <FluentSetters>
 
 		@Override /* GENERATED - TargetedAnnotationBuilder */
@@ -108,20 +95,12 @@ public class RestHookAnnotation {
 	// Implementation
 	//-----------------------------------------------------------------------------------------------------------------
 
-	private static class Impl extends TargetedAnnotationImpl implements RestHook {
-
-		private final HookEvent value;
+	private static class Impl extends TargetedAnnotationImpl implements RestStartCall {
 
 		Impl(Builder b) {
 			super(b);
-			this.value = b.value;
 			postConstruct();
 		}
-
-		@Override /* RestHook */
-		public HookEvent value() {
-			return value;
-		}
 	}
 
 	//-----------------------------------------------------------------------------------------------------------------
@@ -129,7 +108,7 @@ public class RestHookAnnotation {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
-	 * A collection of {@link RestHook @RestHook annotations}.
+	 * A collection of {@link RestStartCall @RestStartCall annotations}.
 	 */
 	@Documented
 	@Target({METHOD,TYPE})
@@ -142,6 +121,6 @@ public class RestHookAnnotation {
 		 *
 		 * @return The annotation value.
 		 */
-		RestHook[] value();
+		RestStartCall[] value();
 	}
 }
\ No newline at end of file
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/DefaultArg.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/DefaultArg.java
index 5f840dac1..dcb53dc6b 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/DefaultArg.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/arg/DefaultArg.java
@@ -79,7 +79,6 @@ public class DefaultArg implements RestOpArg {
 
 	@Override /* RestOpArg */
 	public Object resolve(RestOpSession opSession) throws Exception {
-		System.err.println("beanStore2" + opSession.getBeanStore());
 		return opSession.getBeanStore().getBean(type, name).orElseThrow(()->new ArgException(paramInfo, "Could not resolve bean type {0}", type.getName()));
 	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/servlet/RestObject.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/servlet/RestObject.java
index 94a2c29e4..d258fef20 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/servlet/RestObject.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/servlet/RestObject.java
@@ -13,7 +13,6 @@
 package org.apache.juneau.rest.servlet;
 
 import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.rest.annotation.HookEvent.*;
 
 import java.text.*;
 import java.util.concurrent.atomic.*;
@@ -187,9 +186,9 @@ public abstract class RestObject {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple INIT methods can be defined on a class.
-	 * 		<br>INIT methods on parent classes are invoked before INIT methods on child classes.
-	 * 		<br>The order of INIT method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple init methods can be defined on a class.
+	 * 		<br>Init methods on parent classes are invoked before init methods on child classes.
+	 * 		<br>The order of init method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception causing initialization of the servlet to fail.
 	 * </ul>
@@ -197,7 +196,7 @@ public abstract class RestObject {
 	 * @param builder Context builder which can be used to configure the servlet.
 	 * @throws Exception Any exception thrown will cause servlet to fail startup.
 	 */
-	@RestHook(INIT)
+	@RestInit
 	public void onInit(RestContext.Builder builder) throws Exception {}
 
 	/**
@@ -211,9 +210,9 @@ public abstract class RestObject {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple POST_INIT methods can be defined on a class.
-	 * 		<br>POST_INIT methods on parent classes are invoked before POST_INIT methods on child classes.
-	 * 		<br>The order of POST_INIT method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple post-init methods can be defined on a class.
+	 * 		<br>Post-init methods on parent classes are invoked before post-init methods on child classes.
+	 * 		<br>The order of post-init method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception causing initialization of the servlet to fail.
 	 * </ul>
@@ -221,7 +220,7 @@ public abstract class RestObject {
 	 * @param context The initialized context object.
 	 * @throws Exception Any exception thrown will cause servlet to fail startup.
 	 */
-	@RestHook(POST_INIT)
+	@RestPostInit
 	public void onPostInit(RestContext context) throws Exception {}
 
 	/**
@@ -232,7 +231,7 @@ public abstract class RestObject {
 	 *
 	 * <p>
 	 * This method is called from within the {@link Servlet#init(ServletConfig)} method after the {@link RestContext}
-	 * object has been created and after the {@link HookEvent#POST_INIT} methods have been called.
+	 * object has been created and after the child-last {@link RestPostInit} methods have been called.
 	 *
 	 * <p>
 	 * The only valid parameter type for this method is {@link RestContext} which can be used to retrieve information
@@ -242,9 +241,9 @@ public abstract class RestObject {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple POST_INIT_CHILD_FIRST methods can be defined on a class.
-	 * 		<br>POST_INIT_CHILD_FIRST methods on parent classes are invoked before POST_INIT_CHILD_FIRST methods on child classes.
-	 * 		<br>The order of POST_INIT_CHILD_FIRST method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple post-init methods can be defined on a class.
+	 * 		<br>Post-init methods on parent classes are invoked before post-init methods on child classes.
+	 * 		<br>The order of post-init method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception causing initialization of the servlet to fail.
 	 * </ul>
@@ -252,7 +251,7 @@ public abstract class RestObject {
 	 * @param context The initialized context object.
 	 * @throws Exception Any exception thrown will cause servlet to fail startup.
 	 */
-	@RestHook(POST_INIT_CHILD_FIRST)
+	@RestPostInit(childFirst=true)
 	public void onPostInitChildFirst(RestContext context) throws Exception {}
 
 	/**
@@ -280,9 +279,9 @@ public abstract class RestObject {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple DESTROY methods can be defined on a class.
-	 * 		<br>DESTROY methods on child classes are invoked before DESTROY methods on parent classes.
-	 * 		<br>The order of DESTROY method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple destroy methods can be defined on a class.
+	 * 		<br>Destroy methods on child classes are invoked before destroy methods on parent classes.
+	 * 		<br>The order of destroy method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		In general, destroy methods should not throw any exceptions, although if any are thrown, the stack trace will be
 	 * 		printed to <c>System.err</c>.
@@ -291,7 +290,7 @@ public abstract class RestObject {
 	 * @param context The initialized context object.
 	 * @throws Exception Any exception thrown will cause stack trace to be printed to <c>System.err</c>.
 	 */
-	@RestHook(DESTROY)
+	@RestDestroy
 	public void onDestroy(RestContext context) throws Exception {}
 
 	/**
@@ -318,9 +317,9 @@ public abstract class RestObject {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple START_CALL methods can be defined on a class.
-	 * 		<br>START_CALL methods on parent classes are invoked before START_CALL methods on child classes.
-	 * 		<br>The order of START_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple start-call methods can be defined on a class.
+	 * 		<br>start-call methods on parent classes are invoked before start-call methods on child classes.
+	 * 		<br>The order of start-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception.
 	 * 		<br>{@link BasicHttpException HttpExceptions} can be thrown to cause a particular HTTP error status code.
@@ -331,7 +330,7 @@ public abstract class RestObject {
 	 * @param res The HTTP servlet response object.
 	 * @throws Exception Any exception.
 	 */
-	@RestHook(START_CALL)
+	@RestStartCall
 	public void onStartCall(HttpServletRequest req, HttpServletResponse res) throws Exception {}
 
 	/**
@@ -345,9 +344,9 @@ public abstract class RestObject {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple PRE_CALL methods can be defined on a class.
-	 * 		<br>PRE_CALL methods on parent classes are invoked before PRE_CALL methods on child classes.
-	 * 		<br>The order of PRE_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple pre-call methods can be defined on a class.
+	 * 		<br>Pre-call methods on parent classes are invoked before pre-call methods on child classes.
+	 * 		<br>The order of pre-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception.
 	 * 		<br>{@link BasicHttpException HttpExceptions} can be thrown to cause a particular HTTP error status code.
@@ -361,7 +360,7 @@ public abstract class RestObject {
 	 * @param res The response object.
 	 * @throws Exception Any exception.
 	 */
-	@RestHook(PRE_CALL)
+	@RestPreCall
 	public void onPreCall(RestRequest req, RestResponse res) throws Exception {}
 
 	/**
@@ -375,9 +374,9 @@ public abstract class RestObject {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple POST_CALL methods can be defined on a class.
-	 * 		<br>POST_CALL methods on parent classes are invoked before POST_CALL methods on child classes.
-	 * 		<br>The order of POST_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple post-call methods can be defined on a class.
+	 * 		<br>post-call methods on parent classes are invoked before post-call methods on child classes.
+	 * 		<br>The order of post-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception, although at this point it is too late to set an HTTP error status code.
 	 * </ul>
@@ -386,7 +385,7 @@ public abstract class RestObject {
 	 * @param res The response object.
 	 * @throws Exception Any exception.
 	 */
-	@RestHook(POST_CALL)
+	@RestPostCall
 	public void onPostCall(RestRequest req, RestResponse res) throws Exception {}
 
 	/**
@@ -406,9 +405,9 @@ public abstract class RestObject {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple END_CALL methods can be defined on a class.
-	 * 		<br>END_CALL methods on parent classes are invoked before END_CALL methods on child classes.
-	 * 		<br>The order of END_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple end-call methods can be defined on a class.
+	 * 		<br>end-call methods on parent classes are invoked before end-call methods on child classes.
+	 * 		<br>The order of end-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception, although at this point it is too late to set an HTTP error status code.
 	 * 	<li class='note'>
@@ -421,7 +420,7 @@ public abstract class RestObject {
 	 * @param res The HTTP servlet response object.
 	 * @throws Exception Any exception.
 	 */
-	@RestHook(END_CALL)
+	@RestEndCall
 	public void onEndCall(HttpServletRequest req, HttpServletResponse res) throws Exception {}
 
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/servlet/RestServlet.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/servlet/RestServlet.java
index a37cceb22..d1d6dfcde 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/servlet/RestServlet.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/servlet/RestServlet.java
@@ -17,7 +17,6 @@ import static javax.servlet.http.HttpServletResponse.*;
 import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.rest.HttpRuntimeException.*;
-import static org.apache.juneau.rest.annotation.HookEvent.*;
 
 import java.io.*;
 import java.text.*;
@@ -314,9 +313,9 @@ public abstract class RestServlet extends HttpServlet {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li>
-	 * 		Multiple INIT methods can be defined on a class.
-	 * 		<br>INIT methods on parent classes are invoked before INIT methods on child classes.
-	 * 		<br>The order of INIT method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple init methods can be defined on a class.
+	 * 		<br>Init methods on parent classes are invoked before init methods on child classes.
+	 * 		<br>The order of init method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li>
 	 * 		The method can throw any exception causing initialization of the servlet to fail.
 	 * </ul>
@@ -324,7 +323,7 @@ public abstract class RestServlet extends HttpServlet {
 	 * @param builder Context builder which can be used to configure the servlet.
 	 * @throws Exception Any exception thrown will cause servlet to fail startup.
 	 */
-	@RestHook(INIT)
+	@RestInit
 	public void onInit(RestContext.Builder builder) throws Exception {}
 
 	/**
@@ -338,9 +337,9 @@ public abstract class RestServlet extends HttpServlet {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple POST_INIT methods can be defined on a class.
-	 * 		<br>POST_INIT methods on parent classes are invoked before POST_INIT methods on child classes.
-	 * 		<br>The order of POST_INIT method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple post-init methods can be defined on a class.
+	 * 		<br>post-init methods on parent classes are invoked before post-init methods on child classes.
+	 * 		<br>The order of post-init method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception causing initialization of the servlet to fail.
 	 * </ul>
@@ -348,7 +347,7 @@ public abstract class RestServlet extends HttpServlet {
 	 * @param context The initialized context object.
 	 * @throws Exception Any exception thrown will cause servlet to fail startup.
 	 */
-	@RestHook(POST_INIT)
+	@RestPostInit
 	public void onPostInit(RestContext context) throws Exception {}
 
 	/**
@@ -359,7 +358,7 @@ public abstract class RestServlet extends HttpServlet {
 	 *
 	 * <p>
 	 * This method is called from within the {@link Servlet#init(ServletConfig)} method after the {@link RestContext}
-	 * object has been created and after the {@link HookEvent#POST_INIT} methods have been called.
+	 * object has been created and after the child-last {@link RestPostInit} methods have been called.
 	 *
 	 * <p>
 	 * The only valid parameter type for this method is {@link RestContext} which can be used to retrieve information
@@ -379,7 +378,7 @@ public abstract class RestServlet extends HttpServlet {
 	 * @param context The initialized context object.
 	 * @throws Exception Any exception thrown will cause servlet to fail startup.
 	 */
-	@RestHook(POST_INIT_CHILD_FIRST)
+	@RestPostInit(childFirst=true)
 	public void onPostInitChildFirst(RestContext context) throws Exception {}
 
 	/**
@@ -407,9 +406,9 @@ public abstract class RestServlet extends HttpServlet {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple DESTROY methods can be defined on a class.
-	 * 		<br>DESTROY methods on child classes are invoked before DESTROY methods on parent classes.
-	 * 		<br>The order of DESTROY method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple destroy methods can be defined on a class.
+	 * 		<br>Destroy methods on child classes are invoked before destroy methods on parent classes.
+	 * 		<br>The order of destroy method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		In general, destroy methods should not throw any exceptions, although if any are thrown, the stack trace will be
 	 * 		printed to <c>System.err</c>.
@@ -418,7 +417,7 @@ public abstract class RestServlet extends HttpServlet {
 	 * @param context The initialized context object.
 	 * @throws Exception Any exception thrown will cause stack trace to be printed to <c>System.err</c>.
 	 */
-	@RestHook(DESTROY)
+	@RestDestroy
 	public void onDestroy(RestContext context) throws Exception {}
 
 	/**
@@ -445,9 +444,9 @@ public abstract class RestServlet extends HttpServlet {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple START_CALL methods can be defined on a class.
-	 * 		<br>START_CALL methods on parent classes are invoked before START_CALL methods on child classes.
-	 * 		<br>The order of START_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple start-call methods can be defined on a class.
+	 * 		<br>Start-call methods on parent classes are invoked before start-call methods on child classes.
+	 * 		<br>The order of start-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception.
 	 * 		<br>{@link BasicHttpException HttpExceptions} can be thrown to cause a particular HTTP error status code.
@@ -458,7 +457,7 @@ public abstract class RestServlet extends HttpServlet {
 	 * @param res The HTTP servlet response object.
 	 * @throws Exception Any exception.
 	 */
-	@RestHook(START_CALL)
+	@RestStartCall
 	public void onStartCall(HttpServletRequest req, HttpServletResponse res) throws Exception {}
 
 	/**
@@ -472,9 +471,9 @@ public abstract class RestServlet extends HttpServlet {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple PRE_CALL methods can be defined on a class.
-	 * 		<br>PRE_CALL methods on parent classes are invoked before PRE_CALL methods on child classes.
-	 * 		<br>The order of PRE_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple pre-call methods can be defined on a class.
+	 * 		<br>Pre-call methods on parent classes are invoked before pre-call methods on child classes.
+	 * 		<br>The order of pre-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception.
 	 * 		<br>{@link BasicHttpException HttpExceptions} can be thrown to cause a particular HTTP error status code.
@@ -488,7 +487,7 @@ public abstract class RestServlet extends HttpServlet {
 	 * @param res The response object.
 	 * @throws Exception Any exception.
 	 */
-	@RestHook(PRE_CALL)
+	@RestPreCall
 	public void onPreCall(RestRequest req, RestResponse res) throws Exception {}
 
 	/**
@@ -502,9 +501,9 @@ public abstract class RestServlet extends HttpServlet {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple POST_CALL methods can be defined on a class.
-	 * 		<br>POST_CALL methods on parent classes are invoked before POST_CALL methods on child classes.
-	 * 		<br>The order of POST_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple post-call methods can be defined on a class.
+	 * 		<br>Post-call methods on parent classes are invoked before post-call methods on child classes.
+	 * 		<br>The order of post-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception, although at this point it is too late to set an HTTP error status code.
 	 * </ul>
@@ -513,7 +512,7 @@ public abstract class RestServlet extends HttpServlet {
 	 * @param res The response object.
 	 * @throws Exception Any exception.
 	 */
-	@RestHook(POST_CALL)
+	@RestPostCall
 	public void onPostCall(RestRequest req, RestResponse res) throws Exception {}
 
 	/**
@@ -533,9 +532,9 @@ public abstract class RestServlet extends HttpServlet {
 	 * 	<li class='note'>
 	 * 		The default implementation of this method is a no-op.
 	 * 	<li class='note'>
-	 * 		Multiple END_CALL methods can be defined on a class.
-	 * 		<br>END_CALL methods on parent classes are invoked before END_CALL methods on child classes.
-	 * 		<br>The order of END_CALL method invocations within a class is alphabetical, then by parameter count, then by parameter types.
+	 * 		Multiple end-call methods can be defined on a class.
+	 * 		<br>End-call methods on parent classes are invoked before end-call methods on child classes.
+	 * 		<br>The order of end-call method invocations within a class is alphabetical, then by parameter count, then by parameter types.
 	 * 	<li class='note'>
 	 * 		The method can throw any exception, although at this point it is too late to set an HTTP error status code.
 	 * 	<li class='note'>
@@ -548,7 +547,7 @@ public abstract class RestServlet extends HttpServlet {
 	 * @param res The HTTP servlet response object.
 	 * @throws Exception Any exception.
 	 */
-	@RestHook(END_CALL)
+	@RestEndCall
 	public void onEndCall(HttpServletRequest req, HttpServletResponse res) throws Exception {}
 
 	//-----------------------------------------------------------------------------------------------------------------
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation_Test.java
similarity index 86%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation_Test.java
index 291c26cc3..fd640c3a0 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestDestroyAnnotation_Test.java
@@ -20,30 +20,27 @@ import org.apache.juneau.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestHookAnnotation_Test {
+public class RestDestroyAnnotation_Test {
 
-	private static final String CNAME = RestHookAnnotation_Test.class.getName();
+	private static final String CNAME = RestDestroyAnnotation_Test.class.getName();
 
 	//------------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//------------------------------------------------------------------------------------------------------------------
 
-	RestHook a1 = RestHookAnnotation.create()
+	RestDestroy a1 = RestDestroyAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
-	RestHook a2 = RestHookAnnotation.create()
+	RestDestroy a2 = RestDestroyAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
 	@Test
 	public void a01_basic() {
 		assertObject(a1).asJson().is(""
 			+ "{"
-				+ "on:['a'],"
-				+ "value:'INIT'"
+				+ "on:['a']"
 			+ "}"
 		);
 	}
@@ -80,7 +77,7 @@ public class RestHookAnnotation_Test {
 
 	@Test
 	public void c01_otherMethods() throws Exception {
-		RestHook c4 = RestHookAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
+		RestDestroy c4 = RestDestroyAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
 
 		assertObject(c4).asJson().isContains("on:['"+CNAME+"$C1.m1()','"+CNAME+"$C2.m2()']");
 	}
@@ -89,19 +86,17 @@ public class RestHookAnnotation_Test {
 	// Comparison with declared annotations.
 	//------------------------------------------------------------------------------------------------------------------
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestDestroy(
+		on="a"
 	)
 	public static class D1 {}
-	RestHook d1 = D1.class.getAnnotationsByType(RestHook.class)[0];
+	RestDestroy d1 = D1.class.getAnnotationsByType(RestDestroy.class)[0];
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestDestroy(
+		on="a"
 	)
 	public static class D2 {}
-	RestHook d2 = D2.class.getAnnotationsByType(RestHook.class)[0];
+	RestDestroy d2 = D2.class.getAnnotationsByType(RestDestroy.class)[0];
 
 	@Test
 	public void d01_comparisonWithDeclarativeAnnotations() {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation_Test.java
similarity index 86%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation_Test.java
index 291c26cc3..55a189f29 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestEndCallAnnotation_Test.java
@@ -20,30 +20,27 @@ import org.apache.juneau.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestHookAnnotation_Test {
+public class RestEndCallAnnotation_Test {
 
-	private static final String CNAME = RestHookAnnotation_Test.class.getName();
+	private static final String CNAME = RestEndCallAnnotation_Test.class.getName();
 
 	//------------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//------------------------------------------------------------------------------------------------------------------
 
-	RestHook a1 = RestHookAnnotation.create()
+	RestEndCall a1 = RestEndCallAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
-	RestHook a2 = RestHookAnnotation.create()
+	RestEndCall a2 = RestEndCallAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
 	@Test
 	public void a01_basic() {
 		assertObject(a1).asJson().is(""
 			+ "{"
-				+ "on:['a'],"
-				+ "value:'INIT'"
+				+ "on:['a']"
 			+ "}"
 		);
 	}
@@ -80,7 +77,7 @@ public class RestHookAnnotation_Test {
 
 	@Test
 	public void c01_otherMethods() throws Exception {
-		RestHook c4 = RestHookAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
+		RestEndCall c4 = RestEndCallAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
 
 		assertObject(c4).asJson().isContains("on:['"+CNAME+"$C1.m1()','"+CNAME+"$C2.m2()']");
 	}
@@ -89,19 +86,17 @@ public class RestHookAnnotation_Test {
 	// Comparison with declared annotations.
 	//------------------------------------------------------------------------------------------------------------------
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestEndCall(
+		on="a"
 	)
 	public static class D1 {}
-	RestHook d1 = D1.class.getAnnotationsByType(RestHook.class)[0];
+	RestEndCall d1 = D1.class.getAnnotationsByType(RestEndCall.class)[0];
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestEndCall(
+		on="a"
 	)
 	public static class D2 {}
-	RestHook d2 = D2.class.getAnnotationsByType(RestHook.class)[0];
+	RestEndCall d2 = D2.class.getAnnotationsByType(RestEndCall.class)[0];
 
 	@Test
 	public void d01_comparisonWithDeclarativeAnnotations() {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHook_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHook_Test.java
deleted file mode 100644
index 1f8ea5420..000000000
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHook_Test.java
+++ /dev/null
@@ -1,603 +0,0 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.rest.annotation;
-
-import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.rest.annotation.HookEvent.*;
-import static org.junit.runners.MethodSorters.*;
-import static java.util.Collections.*;
-
-import java.util.*;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-import org.apache.juneau.collections.*;
-import org.apache.juneau.http.annotation.Content;
-import org.apache.juneau.http.header.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.RestRequest;
-import org.apache.juneau.rest.RestResponse;
-import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.httppart.*;
-import org.apache.juneau.rest.mock.*;
-import org.apache.juneau.serializer.*;
-import org.apache.juneau.testutils.*;
-import org.junit.*;
-
-@FixMethodOrder(NAME_ASCENDING)
-public class RestHook_Test {
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @RestHook(PRE_CALL)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(
-		parsers=A1.class,
-		defaultRequestAttributes={
-			"p1:sp1", // Unchanged servlet-level property.
-			"p2:sp2", // Servlet-level property overridden by onPreCall.
-			"p3:sp3", // Servlet-level property overridded by method.
-			"p4:sp4"  // Servlet-level property overridden by method then onPreCall.
-		}
-	)
-	public static class A {
-
-		@RestHook(PRE_CALL)
-		public void onPreCall(RestRequest req) {
-			RequestAttributes attrs = req.getAttributes();
-			attrs.set("p2", "xp2");
-			attrs.set("p4", "xp4");
-			attrs.set("p5", "xp5"); // New property
-			String overrideContentType = req.getHeader("Override-Content-Type").orElse(null);
-			if (overrideContentType != null)
-				req.getHeaders().set("Content-Type", overrideContentType);
-		}
-
-		@RestPut(
-			defaultRequestAttributes={
-				"p3:mp3",
-				"p4:mp4"
-			}
-		)
-		public String a(@Content String in) {
-			return in;
-		}
-
-		@RestPut
-		public String b(RestRequest req, RequestAttributes attrs) throws Exception {
-			attrs.set("p3", "pp3");
-			attrs.set("p4", "pp4");
-			return req.getContent().as(String.class);
-		}
-	}
-
-	public static class A1 extends MockReaderParser {
-		public A1(MockReaderParser.Builder b) {
-			super(b.consumes("text/a1,text/a2,text/a3").function((session,in,type)->in(session)));
-		}
-
-		private static Object in(ReaderParserSession session) {
-			JsonMap sp = session.getSessionProperties();
-			return "p1="+sp.get("p1",null)+",p2="+sp.get("p2",null)+",p3="+sp.get("p3",null)+",p4="+sp.get("p4",null)+",p5="+sp.get("p5",null);
-
-		}
-	}
-
-	@Test
-	public void a01_preCall() throws Exception {
-		RestClient a = MockRestClient.build(A.class);
-		a.put("/a", null).contentType("text/a1").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		a.put("/a", null).contentType("text/a1").header("Override-Content-Type", "text/a2").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		a.put("/b", null).contentType("text/a1").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5");
-		a.put("/b", null).contentType("text/a1").header("Override-Content-Type", "text/a2").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @RestHook(POST_CALL)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(
-		serializers=B1.class,
-		defaultRequestAttributes={
-			"p1:sp1", // Unchanged servlet-level property.
-			"p2:sp2", // Servlet-level property overridden by onPostCall.
-			"p3:sp3", // Servlet-level property overridded by method.
-			"p4:sp4"  // Servlet-level property overridden by method then onPostCall.
-		}
-	)
-	public static class B {
-
-		@RestHook(POST_CALL)
-		public void onPostCall(RestRequest req, RestResponse res) {
-			RequestAttributes attrs = req.getAttributes();
-			attrs.set("p2", "xp2");
-			attrs.set("p4", "xp4");
-			attrs.set("p5", "xp5"); // New property
-			String overrideAccept = req.getHeader("Override-Accept").orElse(null);
-			if (overrideAccept != null)
-				req.getHeaders().set("Accept", overrideAccept);
-			String overrideContentType = req.getHeader("Override-Content-Type").orElse(null);
-			if (overrideContentType != null)
-				attrs.set("Override-Content-Type", overrideContentType);
-		}
-
-		@RestPut(
-			defaultRequestAttributes={
-				"p3:mp3",
-				"p4:mp4"
-			},
-			defaultRequestHeaders="Accept: text/s2"
-		)
-		public String a() {
-			return null;
-		}
-
-		@RestPut
-		public String b(RestRequest req, RequestAttributes attrs) throws Exception {
-			attrs.set("p3", "pp3");
-			attrs.set("p4", "pp4");
-			String accept = req.getHeader("Accept").orElse(null);
-			if (accept == null || accept.isEmpty())
-				req.getHeaders().set("Accept", "text/s2");
-			return null;
-		}
-	}
-
-	public static class B1 extends MockWriterSerializer {
-		public B1(MockWriterSerializer.Builder b) {
-			super(b.produces("test/s1").accept("text/s1,text/s2,text/s3").function((s,o) -> out(s)).headers(s->headers(s)));
-		}
-		public static String out(SerializerSession s) {
-			JsonMap sp = s.getSessionProperties();
-			return "p1="+sp.get("p1",null)+",p2="+sp.get("p2",null)+",p3="+sp.get("p3",null)+",p4="+sp.get("p4",null)+",p5="+sp.get("p5",null);
-		}
-		public static Map<String,String> headers(SerializerSession s) {
-			JsonMap sp = s.getSessionProperties();
-			if (sp.containsKey("Override-Content-Type"))
-				return map("Content-Type",sp.getString("Override-Content-Type",null));
-			return emptyMap();
-		}
-	}
-
-	@Test
-	public void b01_postCall() throws Exception {
-		RestClient b = MockRestClient.build(B.class);
-		b.put("/a", null).accept("text/s1").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/a", null).accept("text/s1").header("Override-Accept", "text/s2").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/a", null).accept("text/s1").header("Override-Content-Type", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/a", null).run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/a", null).header("Override-Accept", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/a", null).header("Override-Content-Type", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
-		b.put("/b", null).accept("text/s1").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/b", null).accept("text/s1").header("Override-Accept", "text/s2").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/b", null).accept("text/s1").header("Override-Content-Type", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/b", null).run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/b", null).header("Override-Accept", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-		b.put("/b", null).header("Override-Content-Type", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @RestHook(INIT)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(children={C_Super.class,C_Sub.class})
-	public static class C {}
-
-	@Rest(path="/super")
-	public static class C_Super {
-		protected JsonList events = new JsonList();
-		@RestHook(INIT)
-		public void init1c(RestContext.Builder builder) {
-			events.add("super-1c");
-		}
-		@RestHook(INIT)
-		public void init1a(ServletConfig config) {
-			events.add("super-1a");
-		}
-		@RestHook(INIT)
-		public void init1b() {
-			events.add("super-1b");
-		}
-		@RestHook(INIT)
-		public void init2a() {
-			events.add("super-2a");
-		}
-		@RestGet
-		public JsonList getEvents() {
-			return events;
-		}
-	}
-
-	@Rest(path="/sub", children={C_Child.class})
-	public static class C_Sub extends C_Super {
-		@Override
-		@RestHook(INIT)
-		public void init1c(RestContext.Builder builder) {
-			events.add("sub-1c");
-		}
-		@Override
-		@RestHook(INIT)
-		public void init1a(ServletConfig config) {
-			events.add("sub-1a");
-		}
-		@Override
-		@RestHook(INIT)
-		public void init1b() {
-			events.add("sub-1b");
-		}
-		@RestHook(INIT)
-		public void init2b() {
-			events.add("sub-2b");
-		}
-	}
-
-	@Rest(path="/child")
-	public static class C_Child extends C_Super {
-		@Override
-		@RestHook(INIT)
-		public void init1c(RestContext.Builder builder) {
-			events.add("child-1c");
-		}
-		@RestHook(INIT)
-		public void init2b() {
-			events.add("child-2b");
-		}
-	}
-
-	@Test
-	public void c01_init() throws Exception {
-		RestClient c = MockRestClient.build(C.class);
-		c.get("/super/events").run().assertContent().is("['super-1a','super-1b','super-1c','super-2a']");
-		c.get("/sub/events").run().assertContent().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
-		c.get("/sub/child/events").run().assertContent().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @RestHook(POST_INIT)
-	//------------------------------------------------------------------------------------------------------------------
-	@Rest(children={D_Super.class,D_Sub.class})
-	public static class D {}
-
-	@Rest(path="/super")
-	public static class D_Super {
-		protected JsonList events = new JsonList();
-		@RestHook(POST_INIT)
-		public void postInit1c(RestContext context) {
-			events.add("super-1c");
-		}
-		@RestHook(POST_INIT)
-		public void postInit1a(RestContext context) {
-			events.add("super-1a");
-		}
-		@RestHook(POST_INIT)
-		public void postInit1b() {
-			events.add("super-1b");
-		}
-		@RestHook(POST_INIT)
-		public void postInit2a() {
-			events.add("super-2a");
-		}
-		@RestGet
-		public JsonList getEvents() {
-			return events;
-		}
-	}
-
-	@Rest(path="/sub",children={D_Child.class})
-	public static class D_Sub extends D_Super {
-		protected static String LAST_CALLED;
-		@Override
-		@RestHook(POST_INIT)
-		public void postInit1c(RestContext context) {
-			events.add("sub-1c");
-		}
-		@Override
-		@RestHook(POST_INIT)
-		public void postInit1a(RestContext context) {
-			events.add("sub-1a");
-		}
-		@Override
-		@RestHook(POST_INIT)
-		public void postInit1b() {
-			events.add("sub-1b");
-		}
-		@RestHook(POST_INIT)
-		public void postInit2b() {
-			events.add("sub-2b");
-		}
-		@RestHook(POST_INIT)
-		public void postInitOrderTestSub() {
-			LAST_CALLED = "PARENT";
-		}
-		@RestGet
-		public String getLastCalled() {
-			return LAST_CALLED;
-		}
-	}
-
-	@Rest(path="/child")
-	public static class D_Child extends D_Super {
-		@Override
-		@RestHook(POST_INIT)
-		public void postInit1c(RestContext context) {
-			events.add("child-1c");
-		}
-		@RestHook(POST_INIT)
-		public void postInit2b() {
-			events.add("child-2b");
-		}
-		@RestHook(POST_INIT)
-		public void postInitOrderTestSub() {
-			D_Sub.LAST_CALLED = "CHILD";
-		}
-	}
-
-	@Test
-	public void d01_postInit() throws Exception {
-		RestClient d = MockRestClient.build(D.class);
-		d.get("/super/events").run().assertContent().is("['super-1a','super-1b','super-1c','super-2a']");
-		d.get("/sub/events").run().assertContent().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
-		d.get("/sub/child/events").run().assertContent().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
-		d.get("/sub/lastCalled").run().assertContent().is("CHILD");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @RestHook(POST_INIT_CHILD_FIRST)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest(
-		children={
-			E_Super.class,
-			E_Sub.class
-		}
-	)
-	public static class E {}
-
-	@Rest(path="/super")
-	public static class E_Super {
-		protected JsonList events = new JsonList();
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst1c(RestContext context) {
-			events.add("super-1c");
-		}
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst1a(RestContext context) {
-			events.add("super-1a");
-		}
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst1b() {
-			events.add("super-1b");
-		}
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst2a() {
-			events.add("super-2a");
-		}
-		@RestGet
-		public JsonList getPostInitChildFirstEvents() {
-			return events;
-		}
-	}
-
-	@Rest(path="/sub", children={E_Child.class})
-	public static class E_Sub extends E_Super {
-		protected static String LAST_CALLED;
-		@Override
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst1c(RestContext context) {
-			events.add("sub-1c");
-		}
-		@Override
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst1a(RestContext context) {
-			events.add("sub-1a");
-		}
-		@Override
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst1b() {
-			events.add("sub-1b");
-		}
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst2b() {
-			events.add("sub-2b");
-		}
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirstOrderTestSub() {
-			LAST_CALLED = "PARENT";
-		}
-		@RestGet
-		public String getLastCalled() {
-			return LAST_CALLED;
-		}
-	}
-
-	@Rest(path="/child")
-	public static class E_Child extends E_Super {
-		@Override
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst1c(RestContext context) {
-			events.add("child-1c");
-		}
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirst2b() {
-			events.add("child-2b");
-		}
-		@RestHook(POST_INIT_CHILD_FIRST)
-		public void postInitChildFirstOrderTestSub() {
-			E_Sub.LAST_CALLED = "CHILD";
-		}
-	}
-
-	@Test
-	public void e01_postInitChildFirst() throws Exception {
-		RestClient e = MockRestClient.build(E.class);
-		e.get("/super/postInitChildFirstEvents").run().assertContent().is("['super-1a','super-1b','super-1c','super-2a']");
-		e.get("/sub/postInitChildFirstEvents").run().assertContent().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
-		e.get("/sub/child/postInitChildFirstEvents").run().assertContent().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
-		e.get("/sub/lastCalled").run().assertContent().is("PARENT");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @RestHook(START_CALL)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class F extends F_Parent {
-		private boolean start3Called;
-		@RestHook(START_CALL)
-		public void start3() {
-			start3Called = true;
-		}
-		@RestHook(START_CALL)
-		public void start4(HttpServletRequest req, HttpServletResponse res) {
-			res.setHeader("start3-called", ""+start3Called);
-			start3Called = false;
-			if (res.getHeader("start4-called") != null)
-				throw new RuntimeException("start4 called multiple times.");
-			res.setHeader("start4-called", "true");
-		}
-		@RestGet(path="/")
-		public JsonMap a(RestRequest req, RestResponse res) {
-			return JsonMap.create()
-				.append("1", res.getHeader("start1-called"))
-				.append("2", res.getHeader("start2-called"))
-				.append("3", res.getHeader("start3-called"))
-				.append("4", res.getHeader("start4-called"));
-		}
-	}
-
-	public static class F_Parent {
-		private boolean start1Called;
-		@RestHook(START_CALL)
-		public void start1() {
-			start1Called = true;
-		}
-		@RestHook(START_CALL)
-		public void start2(HttpServletRequest req, HttpServletResponse res) {
-			res.setHeader("start1-called", ""+start1Called);
-			start1Called = false;
-			if (res.getHeader("start2-called") != null)
-				throw new RuntimeException("start2 called multiple times.");
-			res.setHeader("start2-called", "true");
-		}
-	}
-
-	@Test
-	public void f01_startCall() throws Exception {
-		RestClient f = MockRestClient.build(F.class);
-		f.get("/").run().assertContent().is("{'1':'true','2':'true','3':'true','4':'true'}");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @RestHook(PRE_CALL)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class G extends G_Parent {
-		private boolean pre3Called;
-		@RestHook(PRE_CALL)
-		public void pre3() {
-			pre3Called = true;
-		}
-		@RestHook(PRE_CALL)
-		public void pre4(HttpServletRequest req, HttpServletResponse res) {
-			res.setHeader("pre3-called", ""+pre3Called);
-			pre3Called = false;
-			if (res.getHeader("pre4-called") != null)
-				throw new RuntimeException("pre4 called multiple times.");
-			res.setHeader("pre4-called", "true");
-		}
-		@RestGet(path="/")
-		public JsonMap a(RestRequest req, RestResponse res) {
-			return JsonMap.create()
-				.append("1", res.getHeader("pre1-called"))
-				.append("2", res.getHeader("pre2-called"))
-				.append("3", res.getHeader("pre3-called"))
-				.append("4", res.getHeader("pre4-called"));
-		}
-	}
-
-	public static class G_Parent {
-		private boolean pre1Called;
-		@RestHook(PRE_CALL)
-		public void pre1() {
-			pre1Called = true;
-		}
-		@RestHook(PRE_CALL)
-		public void pre2(Accept accept, RestRequest req, RestResponse res) {
-			res.setHeader("pre1-called", ""+pre1Called);
-			pre1Called = false;
-			if (res.getHeader("pre2-called") != null)
-				throw new RuntimeException("pre2 called multiple times.");
-			res.setHeader("pre2-called", "true");
-		}
-	}
-
-	@Test
-	public void g01_preCall() throws Exception {
-		RestClient g = MockRestClient.build(G.class);
-		g.get("/").run().assertContent().is("{'1':'true','2':'true','3':'true','4':'true'}");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// @RestHook(POST_CALL)
-	//------------------------------------------------------------------------------------------------------------------
-
-	@Rest
-	public static class H extends H_Parent {
-		private boolean post3Called;
-		@RestHook(POST_CALL)
-		public void post3() {
-			post3Called = true;
-		}
-		@RestHook(POST_CALL)
-		public void post4(HttpServletRequest req, HttpServletResponse res) {
-			res.setHeader("post3-called", ""+post3Called);
-			post3Called = false;
-			if (res.getHeader("post4-called") != null)
-				throw new RuntimeException("post4 called multiple times.");
-			res.setHeader("post4-called", "true");
-		}
-		@RestGet(path="/")
-		public String a() {
-			return "OK";
-		}
-	}
-
-	public static class H_Parent {
-		private boolean post1Called;
-		@RestHook(POST_CALL)
-		public void post1() {
-			post1Called = true;
-		}
-		@RestHook(POST_CALL)
-		public void post2(Accept accept, RestRequest req, RestResponse res) {
-			res.setHeader("post1-called", ""+post1Called);
-			post1Called = false;
-			if (res.getHeader("post2-called") != null)
-				throw new RuntimeException("post2 called multiple times.");
-			res.setHeader("post2-called", "true");
-		}
-	}
-
-	@Test
-	public void h01_postCall() throws Exception {
-		RestClient h = MockRestClient.build(H.class);
-		h.get("/").run()
-			.assertHeader("post1-called").is("true")
-			.assertHeader("post2-called").is("true")
-			.assertHeader("post3-called").is("true")
-			.assertHeader("post4-called").is("true");
-	}
-}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInitAnnotation_Test.java
similarity index 87%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInitAnnotation_Test.java
index 291c26cc3..e265eaec9 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInitAnnotation_Test.java
@@ -20,30 +20,27 @@ import org.apache.juneau.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestHookAnnotation_Test {
+public class RestInitAnnotation_Test {
 
-	private static final String CNAME = RestHookAnnotation_Test.class.getName();
+	private static final String CNAME = RestInitAnnotation_Test.class.getName();
 
 	//------------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//------------------------------------------------------------------------------------------------------------------
 
-	RestHook a1 = RestHookAnnotation.create()
+	RestInit a1 = RestInitAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
-	RestHook a2 = RestHookAnnotation.create()
+	RestInit a2 = RestInitAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
 	@Test
 	public void a01_basic() {
 		assertObject(a1).asJson().is(""
 			+ "{"
-				+ "on:['a'],"
-				+ "value:'INIT'"
+				+ "on:['a']"
 			+ "}"
 		);
 	}
@@ -80,7 +77,7 @@ public class RestHookAnnotation_Test {
 
 	@Test
 	public void c01_otherMethods() throws Exception {
-		RestHook c4 = RestHookAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
+		RestInit c4 = RestInitAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
 
 		assertObject(c4).asJson().isContains("on:['"+CNAME+"$C1.m1()','"+CNAME+"$C2.m2()']");
 	}
@@ -89,19 +86,17 @@ public class RestHookAnnotation_Test {
 	// Comparison with declared annotations.
 	//------------------------------------------------------------------------------------------------------------------
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestInit(
+		on="a"
 	)
 	public static class D1 {}
-	RestHook d1 = D1.class.getAnnotationsByType(RestHook.class)[0];
+	RestInit d1 = D1.class.getAnnotationsByType(RestInit.class)[0];
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestInit(
+		on="a"
 	)
 	public static class D2 {}
-	RestHook d2 = D2.class.getAnnotationsByType(RestHook.class)[0];
+	RestInit d2 = D2.class.getAnnotationsByType(RestInit.class)[0];
 
 	@Test
 	public void d01_comparisonWithDeclarativeAnnotations() {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInit_Test.java
similarity index 53%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInit_Test.java
index 96a9862c9..f572ac1f9 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestInit_Test.java
@@ -12,93 +12,92 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.annotation;
 
-import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
 
+import javax.servlet.*;
+
+import org.apache.juneau.collections.*;
 import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.client.*;
 import org.apache.juneau.rest.mock.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class Rest_Context_Test {
+public class RestInit_Test {
 
-	public static class X1 extends RestContext {
-		public X1(RestContext.Builder builder) throws Exception {
-			super(builder);
-		}
-	}
+	//------------------------------------------------------------------------------------------------------------------
+	// @RestInit
+	//------------------------------------------------------------------------------------------------------------------
 
-	@Rest
-	public static class A1 {
+	@Rest(children={A_Super.class,A_Sub.class})
+	public static class A {}
+
+	@Rest(path="/super")
+	public static class A_Super {
+		protected JsonList events = new JsonList();
+		@RestInit
+		public void init1c(RestContext.Builder builder) {
+			events.add("super-1c");
+		}
+		@RestInit
+		public void init1a(ServletConfig config) {
+			events.add("super-1a");
+		}
+		@RestInit
+		public void init1b() {
+			events.add("super-1b");
+		}
+		@RestInit
+		public void init2a() {
+			events.add("super-2a");
+		}
 		@RestGet
-		public String get(RestContext context) {
-			return context.getClass().getSimpleName();
+		public JsonList getEvents() {
+			return events;
 		}
 	}
 
-	@Test
-	public void a01_default() throws Exception {
-		MockRestClient a1 = client(A1.class);
-		a1.get().run().assertContent().is("RestContext");
-	}
-
-	@Rest(contextClass=X1.class)
-	public static class A2 extends A1 {}
-
-	@Test
-	public void a02_custom() throws Exception {
-		MockRestClient a2 = client(A2.class);
-		a2.get().run().assertContent().is("X1");
-	}
-
-	@Rest
-	public static class A3 extends A2 {}
-
-	@Test
-	public void a03_notOverriddenByChild() throws Exception {
-		MockRestClient a3 = client(A3.class);
-		a3.get().run().assertContent().is("X1");
-	}
-
-	@Rest
-	public static class A4 extends A1 {
-		 @RestHook(HookEvent.INIT)
-		 public void init(RestContext.Builder builder) throws Exception {
-			 builder.type(X1.class);
-		 }
-	}
-
-	@Test
-	public void a04_definedInBuilder() throws Exception {
-		MockRestClient a4 = client(A4.class);
-		a4.get().run().assertContent().is("X1");
-	}
-
-
-	public static class X2 extends RestContext {
-		public X2() throws Exception {
-			super(null);
+	@Rest(path="/sub", children={A_Child.class})
+	public static class A_Sub extends A_Super {
+		@Override
+		@RestInit
+		public void init1c(RestContext.Builder builder) {
+			events.add("sub-1c");
+		}
+		@Override
+		@RestInit
+		public void init1a(ServletConfig config) {
+			events.add("sub-1a");
+		}
+		@Override
+		@RestInit
+		public void init1b() {
+			events.add("sub-1b");
+		}
+		@RestInit
+		public void init2b() {
+			events.add("sub-2b");
 		}
 	}
 
-	@Rest(contextClass=X2.class)
-	public static class A5 {
-		@RestGet
-		public String get(RestContext context) {
-			return context.getClass().getSimpleName();
+	@Rest(path="/child")
+	public static class A_Child extends A_Super {
+		@Override
+		@RestInit
+		public void init1c(RestContext.Builder builder) {
+			events.add("child-1c");
+		}
+		@RestInit
+		public void init2b() {
+			events.add("child-2b");
 		}
 	}
 
 	@Test
-	public void a05_invalidConstructor() throws Exception {
-		assertThrown(()->client(A5.class)).asMessages().isContains("Could not instantiate RestContext.");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Helper methods
-	//------------------------------------------------------------------------------------------------------------------
-
-	private static MockRestClient client(Class<?> c) {
-		return MockRestClient.create(c).build();
+	public void a01_init() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/super/events").run().assertContent().is("['super-1a','super-1b','super-1c','super-2a']");
+		a.get("/sub/events").run().assertContent().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
+		a.get("/sub/child/events").run().assertContent().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation_Test.java
similarity index 86%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation_Test.java
index 291c26cc3..437ec1fad 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostCallAnnotation_Test.java
@@ -20,30 +20,27 @@ import org.apache.juneau.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestHookAnnotation_Test {
+public class RestPostCallAnnotation_Test {
 
-	private static final String CNAME = RestHookAnnotation_Test.class.getName();
+	private static final String CNAME = RestPostCallAnnotation_Test.class.getName();
 
 	//------------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//------------------------------------------------------------------------------------------------------------------
 
-	RestHook a1 = RestHookAnnotation.create()
+	RestPostCall a1 = RestPostCallAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
-	RestHook a2 = RestHookAnnotation.create()
+	RestPostCall a2 = RestPostCallAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
 	@Test
 	public void a01_basic() {
 		assertObject(a1).asJson().is(""
 			+ "{"
-				+ "on:['a'],"
-				+ "value:'INIT'"
+				+ "on:['a']"
 			+ "}"
 		);
 	}
@@ -80,7 +77,7 @@ public class RestHookAnnotation_Test {
 
 	@Test
 	public void c01_otherMethods() throws Exception {
-		RestHook c4 = RestHookAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
+		RestPostCall c4 = RestPostCallAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
 
 		assertObject(c4).asJson().isContains("on:['"+CNAME+"$C1.m1()','"+CNAME+"$C2.m2()']");
 	}
@@ -89,19 +86,17 @@ public class RestHookAnnotation_Test {
 	// Comparison with declared annotations.
 	//------------------------------------------------------------------------------------------------------------------
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestPostCall(
+		on="a"
 	)
 	public static class D1 {}
-	RestHook d1 = D1.class.getAnnotationsByType(RestHook.class)[0];
+	RestPostCall d1 = D1.class.getAnnotationsByType(RestPostCall.class)[0];
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestPostCall(
+		on="a"
 	)
 	public static class D2 {}
-	RestHook d2 = D2.class.getAnnotationsByType(RestHook.class)[0];
+	RestPostCall d2 = D2.class.getAnnotationsByType(RestPostCall.class)[0];
 
 	@Test
 	public void d01_comparisonWithDeclarativeAnnotations() {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostCall_Test.java
similarity index 52%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostCall_Test.java
index 96a9862c9..b43154e83 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostCall_Test.java
@@ -12,93 +12,68 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.annotation;
 
-import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
 
-import org.apache.juneau.rest.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.http.header.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.RestResponse;
+import org.apache.juneau.rest.client.*;
 import org.apache.juneau.rest.mock.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class Rest_Context_Test {
+public class RestPostCall_Test {
 
-	public static class X1 extends RestContext {
-		public X1(RestContext.Builder builder) throws Exception {
-			super(builder);
-		}
-	}
+	//------------------------------------------------------------------------------------------------------------------
+	// @RestPostCall
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest
-	public static class A1 {
-		@RestGet
-		public String get(RestContext context) {
-			return context.getClass().getSimpleName();
+	public static class A extends A_Parent {
+		private boolean post3Called;
+		@RestPostCall
+		public void post3() {
+			post3Called = true;
 		}
-	}
-
-	@Test
-	public void a01_default() throws Exception {
-		MockRestClient a1 = client(A1.class);
-		a1.get().run().assertContent().is("RestContext");
-	}
-
-	@Rest(contextClass=X1.class)
-	public static class A2 extends A1 {}
-
-	@Test
-	public void a02_custom() throws Exception {
-		MockRestClient a2 = client(A2.class);
-		a2.get().run().assertContent().is("X1");
-	}
-
-	@Rest
-	public static class A3 extends A2 {}
-
-	@Test
-	public void a03_notOverriddenByChild() throws Exception {
-		MockRestClient a3 = client(A3.class);
-		a3.get().run().assertContent().is("X1");
-	}
-
-	@Rest
-	public static class A4 extends A1 {
-		 @RestHook(HookEvent.INIT)
-		 public void init(RestContext.Builder builder) throws Exception {
-			 builder.type(X1.class);
-		 }
-	}
-
-	@Test
-	public void a04_definedInBuilder() throws Exception {
-		MockRestClient a4 = client(A4.class);
-		a4.get().run().assertContent().is("X1");
-	}
-
-
-	public static class X2 extends RestContext {
-		public X2() throws Exception {
-			super(null);
+		@RestPostCall
+		public void post4(HttpServletRequest req, HttpServletResponse res) {
+			res.setHeader("post3-called", ""+post3Called);
+			post3Called = false;
+			if (res.getHeader("post4-called") != null)
+				throw new RuntimeException("post4 called multiple times.");
+			res.setHeader("post4-called", "true");
+		}
+		@RestGet(path="/")
+		public String a() {
+			return "OK";
 		}
 	}
 
-	@Rest(contextClass=X2.class)
-	public static class A5 {
-		@RestGet
-		public String get(RestContext context) {
-			return context.getClass().getSimpleName();
+	public static class A_Parent {
+		private boolean post1Called;
+		@RestPostCall
+		public void post1() {
+			post1Called = true;
+		}
+		@RestPostCall
+		public void post2(Accept accept, RestRequest req, RestResponse res) {
+			res.setHeader("post1-called", ""+post1Called);
+			post1Called = false;
+			if (res.getHeader("post2-called") != null)
+				throw new RuntimeException("post2 called multiple times.");
+			res.setHeader("post2-called", "true");
 		}
 	}
 
 	@Test
-	public void a05_invalidConstructor() throws Exception {
-		assertThrown(()->client(A5.class)).asMessages().isContains("Could not instantiate RestContext.");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Helper methods
-	//------------------------------------------------------------------------------------------------------------------
-
-	private static MockRestClient client(Class<?> c) {
-		return MockRestClient.create(c).build();
+	public void a01_postCall() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/").run()
+			.assertHeader("post1-called").is("true")
+			.assertHeader("post2-called").is("true")
+			.assertHeader("post3-called").is("true")
+			.assertHeader("post4-called").is("true");
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation_Test.java
similarity index 85%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation_Test.java
index 291c26cc3..529e08f9a 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostInitAnnotation_Test.java
@@ -20,30 +20,30 @@ import org.apache.juneau.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestHookAnnotation_Test {
+public class RestPostInitAnnotation_Test {
 
-	private static final String CNAME = RestHookAnnotation_Test.class.getName();
+	private static final String CNAME = RestPostInitAnnotation_Test.class.getName();
 
 	//------------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//------------------------------------------------------------------------------------------------------------------
 
-	RestHook a1 = RestHookAnnotation.create()
+	RestPostInit a1 = RestPostInitAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
+		.childFirst()
 		.build();
 
-	RestHook a2 = RestHookAnnotation.create()
+	RestPostInit a2 = RestPostInitAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
+		.childFirst()
 		.build();
 
 	@Test
 	public void a01_basic() {
 		assertObject(a1).asJson().is(""
 			+ "{"
-				+ "on:['a'],"
-				+ "value:'INIT'"
+				+ "childFirst:true,"
+				+ "on:['a']"
 			+ "}"
 		);
 	}
@@ -80,7 +80,7 @@ public class RestHookAnnotation_Test {
 
 	@Test
 	public void c01_otherMethods() throws Exception {
-		RestHook c4 = RestHookAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
+		RestPostInit c4 = RestPostInitAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
 
 		assertObject(c4).asJson().isContains("on:['"+CNAME+"$C1.m1()','"+CNAME+"$C2.m2()']");
 	}
@@ -89,19 +89,19 @@ public class RestHookAnnotation_Test {
 	// Comparison with declared annotations.
 	//------------------------------------------------------------------------------------------------------------------
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestPostInit(
+		childFirst=true,
+		on="a"
 	)
 	public static class D1 {}
-	RestHook d1 = D1.class.getAnnotationsByType(RestHook.class)[0];
+	RestPostInit d1 = D1.class.getAnnotationsByType(RestPostInit.class)[0];
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestPostInit(
+		childFirst=true,
+		on="a"
 	)
 	public static class D2 {}
-	RestHook d2 = D2.class.getAnnotationsByType(RestHook.class)[0];
+	RestPostInit d2 = D2.class.getAnnotationsByType(RestPostInit.class)[0];
 
 	@Test
 	public void d01_comparisonWithDeclarativeAnnotations() {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostInit_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostInit_Test.java
new file mode 100644
index 000000000..83befee14
--- /dev/null
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPostInit_Test.java
@@ -0,0 +1,209 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.client.*;
+import org.apache.juneau.rest.mock.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class RestPostInit_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @RestPostInit
+	//------------------------------------------------------------------------------------------------------------------
+	@Rest(children={A_Super.class,A_Sub.class})
+	public static class A {}
+
+	@Rest(path="/super")
+	public static class A_Super {
+		protected JsonList events = new JsonList();
+		@RestPostInit
+		public void postInit1c(RestContext context) {
+			events.add("super-1c");
+		}
+		@RestPostInit
+		public void postInit1a(RestContext context) {
+			events.add("super-1a");
+		}
+		@RestPostInit
+		public void postInit1b() {
+			events.add("super-1b");
+		}
+		@RestPostInit
+		public void postInit2a() {
+			events.add("super-2a");
+		}
+		@RestGet
+		public JsonList getEvents() {
+			return events;
+		}
+	}
+
+	@Rest(path="/sub",children={A_Child.class})
+	public static class A_Sub extends A_Super {
+		protected static String LAST_CALLED;
+		@Override
+		@RestPostInit
+		public void postInit1c(RestContext context) {
+			events.add("sub-1c");
+		}
+		@Override
+		@RestPostInit
+		public void postInit1a(RestContext context) {
+			events.add("sub-1a");
+		}
+		@Override
+		@RestPostInit
+		public void postInit1b() {
+			events.add("sub-1b");
+		}
+		@RestPostInit
+		public void postInit2b() {
+			events.add("sub-2b");
+		}
+		@RestPostInit
+		public void postInitOrderTestSub() {
+			LAST_CALLED = "PARENT";
+		}
+		@RestGet
+		public String getLastCalled() {
+			return LAST_CALLED;
+		}
+	}
+
+	@Rest(path="/child")
+	public static class A_Child extends A_Super {
+		@Override
+		@RestPostInit
+		public void postInit1c(RestContext context) {
+			events.add("child-1c");
+		}
+		@RestPostInit
+		public void postInit2b() {
+			events.add("child-2b");
+		}
+		@RestPostInit
+		public void postInitOrderTestSub() {
+			A_Sub.LAST_CALLED = "CHILD";
+		}
+	}
+
+	@Test
+	public void a01_postInit() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/super/events").run().assertContent().is("['super-1a','super-1b','super-1c','super-2a']");
+		a.get("/sub/events").run().assertContent().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
+		a.get("/sub/child/events").run().assertContent().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
+		a.get("/sub/lastCalled").run().assertContent().is("CHILD");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @RestPostInit(childFirst=true)
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(
+		children={
+			B_Super.class,
+			B_Sub.class
+		}
+	)
+	public static class B {}
+
+	@Rest(path="/super")
+	public static class B_Super {
+		protected JsonList events = new JsonList();
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst1c(RestContext context) {
+			events.add("super-1c");
+		}
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst1a(RestContext context) {
+			events.add("super-1a");
+		}
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst1b() {
+			events.add("super-1b");
+		}
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst2a() {
+			events.add("super-2a");
+		}
+		@RestGet
+		public JsonList getPostInitChildFirstEvents() {
+			return events;
+		}
+	}
+
+	@Rest(path="/sub", children={B_Child.class})
+	public static class B_Sub extends B_Super {
+		protected static String LAST_CALLED;
+		@Override
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst1c(RestContext context) {
+			events.add("sub-1c");
+		}
+		@Override
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst1a(RestContext context) {
+			events.add("sub-1a");
+		}
+		@Override
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst1b() {
+			events.add("sub-1b");
+		}
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst2b() {
+			events.add("sub-2b");
+		}
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirstOrderTestSub() {
+			LAST_CALLED = "PARENT";
+		}
+		@RestGet
+		public String getLastCalled() {
+			return LAST_CALLED;
+		}
+	}
+
+	@Rest(path="/child")
+	public static class B_Child extends B_Super {
+		@Override
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst1c(RestContext context) {
+			events.add("child-1c");
+		}
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirst2b() {
+			events.add("child-2b");
+		}
+		@RestPostInit(childFirst=true)
+		public void postInitChildFirstOrderTestSub() {
+			B_Sub.LAST_CALLED = "CHILD";
+		}
+	}
+
+	@Test
+	public void b01_postInitChildFirst() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
+		b.get("/super/postInitChildFirstEvents").run().assertContent().is("['super-1a','super-1b','super-1c','super-2a']");
+		b.get("/sub/postInitChildFirstEvents").run().assertContent().is("['sub-1a','sub-1b','sub-1c','super-2a','sub-2b']");
+		b.get("/sub/child/postInitChildFirstEvents").run().assertContent().is("['super-1a','super-1b','child-1c','super-2a','child-2b']");
+		b.get("/sub/lastCalled").run().assertContent().is("PARENT");
+	}
+}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation_Test.java
similarity index 86%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation_Test.java
index 291c26cc3..1a84d69a9 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPreCallAnnotation_Test.java
@@ -20,30 +20,27 @@ import org.apache.juneau.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestHookAnnotation_Test {
+public class RestPreCallAnnotation_Test {
 
-	private static final String CNAME = RestHookAnnotation_Test.class.getName();
+	private static final String CNAME = RestPreCallAnnotation_Test.class.getName();
 
 	//------------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//------------------------------------------------------------------------------------------------------------------
 
-	RestHook a1 = RestHookAnnotation.create()
+	RestPreCall a1 = RestPreCallAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
-	RestHook a2 = RestHookAnnotation.create()
+	RestPreCall a2 = RestPreCallAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
 	@Test
 	public void a01_basic() {
 		assertObject(a1).asJson().is(""
 			+ "{"
-				+ "on:['a'],"
-				+ "value:'INIT'"
+				+ "on:['a']"
 			+ "}"
 		);
 	}
@@ -80,7 +77,7 @@ public class RestHookAnnotation_Test {
 
 	@Test
 	public void c01_otherMethods() throws Exception {
-		RestHook c4 = RestHookAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
+		RestPreCall c4 = RestPreCallAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
 
 		assertObject(c4).asJson().isContains("on:['"+CNAME+"$C1.m1()','"+CNAME+"$C2.m2()']");
 	}
@@ -89,19 +86,17 @@ public class RestHookAnnotation_Test {
 	// Comparison with declared annotations.
 	//------------------------------------------------------------------------------------------------------------------
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestPreCall(
+		on="a"
 	)
 	public static class D1 {}
-	RestHook d1 = D1.class.getAnnotationsByType(RestHook.class)[0];
+	RestPreCall d1 = D1.class.getAnnotationsByType(RestPreCall.class)[0];
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestPreCall(
+		on="a"
 	)
 	public static class D2 {}
-	RestHook d2 = D2.class.getAnnotationsByType(RestHook.class)[0];
+	RestPreCall d2 = D2.class.getAnnotationsByType(RestPreCall.class)[0];
 
 	@Test
 	public void d01_comparisonWithDeclarativeAnnotations() {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPreCall_Test.java
similarity index 52%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPreCall_Test.java
index 96a9862c9..a39312939 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestPreCall_Test.java
@@ -12,93 +12,69 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.annotation;
 
-import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
 
-import org.apache.juneau.rest.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.http.header.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.RestResponse;
+import org.apache.juneau.rest.client.*;
 import org.apache.juneau.rest.mock.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class Rest_Context_Test {
+public class RestPreCall_Test {
 
-	public static class X1 extends RestContext {
-		public X1(RestContext.Builder builder) throws Exception {
-			super(builder);
-		}
-	}
+	//------------------------------------------------------------------------------------------------------------------
+	// @RestPreCall
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest
-	public static class A1 {
-		@RestGet
-		public String get(RestContext context) {
-			return context.getClass().getSimpleName();
+	public static class A extends A_Parent {
+		private boolean pre3Called;
+		@RestPreCall
+		public void pre3() {
+			pre3Called = true;
 		}
-	}
-
-	@Test
-	public void a01_default() throws Exception {
-		MockRestClient a1 = client(A1.class);
-		a1.get().run().assertContent().is("RestContext");
-	}
-
-	@Rest(contextClass=X1.class)
-	public static class A2 extends A1 {}
-
-	@Test
-	public void a02_custom() throws Exception {
-		MockRestClient a2 = client(A2.class);
-		a2.get().run().assertContent().is("X1");
-	}
-
-	@Rest
-	public static class A3 extends A2 {}
-
-	@Test
-	public void a03_notOverriddenByChild() throws Exception {
-		MockRestClient a3 = client(A3.class);
-		a3.get().run().assertContent().is("X1");
-	}
-
-	@Rest
-	public static class A4 extends A1 {
-		 @RestHook(HookEvent.INIT)
-		 public void init(RestContext.Builder builder) throws Exception {
-			 builder.type(X1.class);
-		 }
-	}
-
-	@Test
-	public void a04_definedInBuilder() throws Exception {
-		MockRestClient a4 = client(A4.class);
-		a4.get().run().assertContent().is("X1");
-	}
-
-
-	public static class X2 extends RestContext {
-		public X2() throws Exception {
-			super(null);
+		@RestPreCall
+		public void pre4(HttpServletRequest req, HttpServletResponse res) {
+			res.setHeader("pre3-called", ""+pre3Called);
+			pre3Called = false;
+			if (res.getHeader("pre4-called") != null)
+				throw new RuntimeException("pre4 called multiple times.");
+			res.setHeader("pre4-called", "true");
+		}
+		@RestGet(path="/")
+		public JsonMap a(RestRequest req, RestResponse res) {
+			return JsonMap.create()
+				.append("1", res.getHeader("pre1-called"))
+				.append("2", res.getHeader("pre2-called"))
+				.append("3", res.getHeader("pre3-called"))
+				.append("4", res.getHeader("pre4-called"));
 		}
 	}
 
-	@Rest(contextClass=X2.class)
-	public static class A5 {
-		@RestGet
-		public String get(RestContext context) {
-			return context.getClass().getSimpleName();
+	public static class A_Parent {
+		private boolean pre1Called;
+		@RestPreCall
+		public void pre1() {
+			pre1Called = true;
+		}
+		@RestPreCall
+		public void pre2(Accept accept, RestRequest req, RestResponse res) {
+			res.setHeader("pre1-called", ""+pre1Called);
+			pre1Called = false;
+			if (res.getHeader("pre2-called") != null)
+				throw new RuntimeException("pre2 called multiple times.");
+			res.setHeader("pre2-called", "true");
 		}
 	}
 
 	@Test
-	public void a05_invalidConstructor() throws Exception {
-		assertThrown(()->client(A5.class)).asMessages().isContains("Could not instantiate RestContext.");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Helper methods
-	//------------------------------------------------------------------------------------------------------------------
-
-	private static MockRestClient client(Class<?> c) {
-		return MockRestClient.create(c).build();
+	public void a01_preCall() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/").run().assertContent().is("{'1':'true','2':'true','3':'true','4':'true'}");
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation_Test.java
similarity index 86%
rename from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
rename to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation_Test.java
index 291c26cc3..72caff8e1 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestHookAnnotation_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestStartCallAnnotation_Test.java
@@ -20,30 +20,27 @@ import org.apache.juneau.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class RestHookAnnotation_Test {
+public class RestStartCallAnnotation_Test {
 
-	private static final String CNAME = RestHookAnnotation_Test.class.getName();
+	private static final String CNAME = RestStartCallAnnotation_Test.class.getName();
 
 	//------------------------------------------------------------------------------------------------------------------
 	// Basic tests
 	//------------------------------------------------------------------------------------------------------------------
 
-	RestHook a1 = RestHookAnnotation.create()
+	RestStartCall a1 = RestStartCallAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
-	RestHook a2 = RestHookAnnotation.create()
+	RestStartCall a2 = RestStartCallAnnotation.create()
 		.on("a")
-		.value(HookEvent.INIT)
 		.build();
 
 	@Test
 	public void a01_basic() {
 		assertObject(a1).asJson().is(""
 			+ "{"
-				+ "on:['a'],"
-				+ "value:'INIT'"
+				+ "on:['a']"
 			+ "}"
 		);
 	}
@@ -80,7 +77,7 @@ public class RestHookAnnotation_Test {
 
 	@Test
 	public void c01_otherMethods() throws Exception {
-		RestHook c4 = RestHookAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
+		RestStartCall c4 = RestStartCallAnnotation.create().on(C1.class.getMethod("m1")).on(C2.class.getMethod("m2")).build();
 
 		assertObject(c4).asJson().isContains("on:['"+CNAME+"$C1.m1()','"+CNAME+"$C2.m2()']");
 	}
@@ -89,19 +86,17 @@ public class RestHookAnnotation_Test {
 	// Comparison with declared annotations.
 	//------------------------------------------------------------------------------------------------------------------
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestStartCall(
+		on="a"
 	)
 	public static class D1 {}
-	RestHook d1 = D1.class.getAnnotationsByType(RestHook.class)[0];
+	RestStartCall d1 = D1.class.getAnnotationsByType(RestStartCall.class)[0];
 
-	@RestHook(
-		on="a",
-		value=HookEvent.INIT
+	@RestStartCall(
+		on="a"
 	)
 	public static class D2 {}
-	RestHook d2 = D2.class.getAnnotationsByType(RestHook.class)[0];
+	RestStartCall d2 = D2.class.getAnnotationsByType(RestStartCall.class)[0];
 
 	@Test
 	public void d01_comparisonWithDeclarativeAnnotations() {
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestStartCall_Test.java
similarity index 52%
copy from juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
copy to juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestStartCall_Test.java
index 96a9862c9..fe306a606 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/RestStartCall_Test.java
@@ -12,93 +12,68 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.annotation;
 
-import static org.apache.juneau.assertions.Assertions.*;
 import static org.junit.runners.MethodSorters.*;
 
-import org.apache.juneau.rest.*;
+import javax.servlet.http.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.RestResponse;
+import org.apache.juneau.rest.client.*;
 import org.apache.juneau.rest.mock.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
-public class Rest_Context_Test {
+public class RestStartCall_Test {
 
-	public static class X1 extends RestContext {
-		public X1(RestContext.Builder builder) throws Exception {
-			super(builder);
-		}
-	}
+	//------------------------------------------------------------------------------------------------------------------
+	// @RestStartCall
+	//------------------------------------------------------------------------------------------------------------------
 
 	@Rest
-	public static class A1 {
-		@RestGet
-		public String get(RestContext context) {
-			return context.getClass().getSimpleName();
+	public static class A extends A_Parent {
+		private boolean start3Called;
+		@RestStartCall
+		public void start3() {
+			start3Called = true;
 		}
-	}
-
-	@Test
-	public void a01_default() throws Exception {
-		MockRestClient a1 = client(A1.class);
-		a1.get().run().assertContent().is("RestContext");
-	}
-
-	@Rest(contextClass=X1.class)
-	public static class A2 extends A1 {}
-
-	@Test
-	public void a02_custom() throws Exception {
-		MockRestClient a2 = client(A2.class);
-		a2.get().run().assertContent().is("X1");
-	}
-
-	@Rest
-	public static class A3 extends A2 {}
-
-	@Test
-	public void a03_notOverriddenByChild() throws Exception {
-		MockRestClient a3 = client(A3.class);
-		a3.get().run().assertContent().is("X1");
-	}
-
-	@Rest
-	public static class A4 extends A1 {
-		 @RestHook(HookEvent.INIT)
-		 public void init(RestContext.Builder builder) throws Exception {
-			 builder.type(X1.class);
-		 }
-	}
-
-	@Test
-	public void a04_definedInBuilder() throws Exception {
-		MockRestClient a4 = client(A4.class);
-		a4.get().run().assertContent().is("X1");
-	}
-
-
-	public static class X2 extends RestContext {
-		public X2() throws Exception {
-			super(null);
+		@RestStartCall
+		public void start4(HttpServletRequest req, HttpServletResponse res) {
+			res.setHeader("start3-called", ""+start3Called);
+			start3Called = false;
+			if (res.getHeader("start4-called") != null)
+				throw new RuntimeException("start4 called multiple times.");
+			res.setHeader("start4-called", "true");
+		}
+		@RestGet(path="/")
+		public JsonMap a(RestRequest req, RestResponse res) {
+			return JsonMap.create()
+				.append("1", res.getHeader("start1-called"))
+				.append("2", res.getHeader("start2-called"))
+				.append("3", res.getHeader("start3-called"))
+				.append("4", res.getHeader("start4-called"));
 		}
 	}
 
-	@Rest(contextClass=X2.class)
-	public static class A5 {
-		@RestGet
-		public String get(RestContext context) {
-			return context.getClass().getSimpleName();
+	public static class A_Parent {
+		private boolean start1Called;
+		@RestStartCall
+		public void start1() {
+			start1Called = true;
+		}
+		@RestStartCall
+		public void start2(HttpServletRequest req, HttpServletResponse res) {
+			res.setHeader("start1-called", ""+start1Called);
+			start1Called = false;
+			if (res.getHeader("start2-called") != null)
+				throw new RuntimeException("start2 called multiple times.");
+			res.setHeader("start2-called", "true");
 		}
 	}
 
 	@Test
-	public void a05_invalidConstructor() throws Exception {
-		assertThrown(()->client(A5.class)).asMessages().isContains("Could not instantiate RestContext.");
-	}
-
-	//------------------------------------------------------------------------------------------------------------------
-	// Helper methods
-	//------------------------------------------------------------------------------------------------------------------
-
-	private static MockRestClient client(Class<?> c) {
-		return MockRestClient.create(c).build();
+	public void a01_startCall() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.get("/").run().assertContent().is("{'1':'true','2':'true','3':'true','4':'true'}");
 	}
 }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
index 96a9862c9..4fb6bc0e6 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Context_Test.java
@@ -62,10 +62,10 @@ public class Rest_Context_Test {
 
 	@Rest
 	public static class A4 extends A1 {
-		 @RestHook(HookEvent.INIT)
-		 public void init(RestContext.Builder builder) throws Exception {
-			 builder.type(X1.class);
-		 }
+		@RestInit
+		public void init(RestContext.Builder builder) throws Exception {
+			builder.type(X1.class);
+		}
 	}
 
 	@Test
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_DefaultRequestAttributes_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_DefaultRequestAttributes_Test.java
new file mode 100644
index 000000000..1d5384287
--- /dev/null
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_DefaultRequestAttributes_Test.java
@@ -0,0 +1,184 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.annotation;
+
+import static java.util.Collections.*;
+import static org.apache.juneau.internal.CollectionUtils.*;
+import static org.junit.runners.MethodSorters.*;
+
+import java.util.*;
+
+import org.apache.juneau.collections.*;
+import org.apache.juneau.http.annotation.Content;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.rest.RestRequest;
+import org.apache.juneau.rest.RestResponse;
+import org.apache.juneau.rest.client.*;
+import org.apache.juneau.rest.httppart.*;
+import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.testutils.*;
+import org.junit.*;
+
+@FixMethodOrder(NAME_ASCENDING)
+public class Rest_DefaultRequestAttributes_Test {
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @RestPreCall
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(
+		parsers=A1.class,
+		defaultRequestAttributes={
+			"p1:sp1", // Unchanged servlet-level property.
+			"p2:sp2", // Servlet-level property overridden by onPreCall.
+			"p3:sp3", // Servlet-level property overridded by method.
+			"p4:sp4"  // Servlet-level property overridden by method then onPreCall.
+		}
+	)
+	public static class A {
+
+		@RestPreCall
+		public void onPreCall(RestRequest req) {
+			RequestAttributes attrs = req.getAttributes();
+			attrs.set("p2", "xp2");
+			attrs.set("p4", "xp4");
+			attrs.set("p5", "xp5"); // New property
+			String overrideContentType = req.getHeader("Override-Content-Type").orElse(null);
+			if (overrideContentType != null)
+				req.getHeaders().set("Content-Type", overrideContentType);
+		}
+
+		@RestPut(
+			defaultRequestAttributes={
+				"p3:mp3",
+				"p4:mp4"
+			}
+		)
+		public String a(@Content String in) {
+			return in;
+		}
+
+		@RestPut
+		public String b(RestRequest req, RequestAttributes attrs) throws Exception {
+			attrs.set("p3", "pp3");
+			attrs.set("p4", "pp4");
+			return req.getContent().as(String.class);
+		}
+	}
+
+	public static class A1 extends MockReaderParser {
+		public A1(MockReaderParser.Builder b) {
+			super(b.consumes("text/a1,text/a2,text/a3").function((session,in,type)->in(session)));
+		}
+
+		private static Object in(ReaderParserSession session) {
+			JsonMap sp = session.getSessionProperties();
+			return "p1="+sp.get("p1",null)+",p2="+sp.get("p2",null)+",p3="+sp.get("p3",null)+",p4="+sp.get("p4",null)+",p5="+sp.get("p5",null);
+
+		}
+	}
+
+	@Test
+	public void a01_preCall() throws Exception {
+		RestClient a = MockRestClient.build(A.class);
+		a.put("/a", null).contentType("text/a1").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		a.put("/a", null).contentType("text/a1").header("Override-Content-Type", "text/a2").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		a.put("/b", null).contentType("text/a1").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5");
+		a.put("/b", null).contentType("text/a1").header("Override-Content-Type", "text/a2").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=pp4,p5=xp5");
+	}
+
+	//------------------------------------------------------------------------------------------------------------------
+	// @RestPostCall
+	//------------------------------------------------------------------------------------------------------------------
+
+	@Rest(
+		serializers=B1.class,
+		defaultRequestAttributes={
+			"p1:sp1", // Unchanged servlet-level property.
+			"p2:sp2", // Servlet-level property overridden by onPostCall.
+			"p3:sp3", // Servlet-level property overridded by method.
+			"p4:sp4"  // Servlet-level property overridden by method then onPostCall.
+		}
+	)
+	public static class B {
+
+		@RestPostCall
+		public void onPostCall(RestRequest req, RestResponse res) {
+			RequestAttributes attrs = req.getAttributes();
+			attrs.set("p2", "xp2");
+			attrs.set("p4", "xp4");
+			attrs.set("p5", "xp5"); // New property
+			String overrideAccept = req.getHeader("Override-Accept").orElse(null);
+			if (overrideAccept != null)
+				req.getHeaders().set("Accept", overrideAccept);
+			String overrideContentType = req.getHeader("Override-Content-Type").orElse(null);
+			if (overrideContentType != null)
+				attrs.set("Override-Content-Type", overrideContentType);
+		}
+
+		@RestPut(
+			defaultRequestAttributes={
+				"p3:mp3",
+				"p4:mp4"
+			},
+			defaultRequestHeaders="Accept: text/s2"
+		)
+		public String a() {
+			return null;
+		}
+
+		@RestPut
+		public String b(RestRequest req, RequestAttributes attrs) throws Exception {
+			attrs.set("p3", "pp3");
+			attrs.set("p4", "pp4");
+			String accept = req.getHeader("Accept").orElse(null);
+			if (accept == null || accept.isEmpty())
+				req.getHeaders().set("Accept", "text/s2");
+			return null;
+		}
+	}
+
+	public static class B1 extends MockWriterSerializer {
+		public B1(MockWriterSerializer.Builder b) {
+			super(b.produces("test/s1").accept("text/s1,text/s2,text/s3").function((s,o) -> out(s)).headers(s->headers(s)));
+		}
+		public static String out(SerializerSession s) {
+			JsonMap sp = s.getSessionProperties();
+			return "p1="+sp.get("p1",null)+",p2="+sp.get("p2",null)+",p3="+sp.get("p3",null)+",p4="+sp.get("p4",null)+",p5="+sp.get("p5",null);
+		}
+		public static Map<String,String> headers(SerializerSession s) {
+			JsonMap sp = s.getSessionProperties();
+			if (sp.containsKey("Override-Content-Type"))
+				return map("Content-Type",sp.getString("Override-Content-Type",null));
+			return emptyMap();
+		}
+	}
+
+	@Test
+	public void b01_postCall() throws Exception {
+		RestClient b = MockRestClient.build(B.class);
+		b.put("/a", null).accept("text/s1").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).accept("text/s1").header("Override-Accept", "text/s2").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).accept("text/s1").header("Override-Content-Type", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).header("Override-Accept", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/a", null).header("Override-Content-Type", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=mp3,p4=xp4,p5=xp5");
+		b.put("/b", null).accept("text/s1").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).accept("text/s1").header("Override-Accept", "text/s2").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).accept("text/s1").header("Override-Content-Type", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).header("Override-Accept", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+		b.put("/b", null).header("Override-Content-Type", "text/s3").run().assertContent().is("p1=sp1,p2=xp2,p3=pp3,p4=xp4,p5=xp5");
+	}
+}
diff --git a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
index 04c566b6b..3802ac335 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Rest_Messages_Test.java
@@ -101,10 +101,10 @@ public class Rest_Messages_Test {
 	}
 
 	public static class B3 extends B1 {
-		 @RestHook(HookEvent.INIT)
-		 public void init(RestContext.Builder builder) throws Exception {
-			 builder.messages().location(null, "B2x").location(B1.class, "B1x");
-		 }
+		@RestInit
+		public void init(RestContext.Builder builder) throws Exception {
+			builder.messages().location(null, "B2x").location(B1.class, "B1x");
+		}
 	}
 
 	@Test