Package com.mastfrog.acteur
Class Acteur
java.lang.Object
com.mastfrog.acteurbase.AbstractActeur<Response,com.mastfrog.acteur.ResponseImpl,State>
com.mastfrog.acteur.Acteur
- Direct Known Subclasses:
AuthenticationActeur,CheckIfModifiedSinceHeader,CheckIfNoneMatchHeader,CheckIfUnmodifiedSinceHeader,DeferredComputationResultActeur,InstallChunkHandler,WebSocketUpgradeActeur
public abstract class Acteur
extends AbstractActeur<Response,com.mastfrog.acteur.ResponseImpl,State>
A single piece of logic which can
- Reject an HTTP request
- Validate an HTTP request and allow the next Acteur in the chain to process it
- Initiate an HTTP response
Page. All of an Acteur's work
happens either in its constructor, prior to a call to setState(), or in its
overridden getState() method. The state determines whether processing of the
current list of Acteurs will continue, or if not, what happens to it.
Acteurs are constructed by Guice - in fact, what a Page has is usually just a
list of classes. Objects they need, such as the current request
HttpEvent can simply be constructor parameters if the constructor is
annotated with Guice's @Inject.
An Acteur may construct some objects which will then be included in the set
of objects the next Acteur in the chain can request for injection in its
constructor parameters.
A number of inner classes are provided which can be used as standard states.
Acteurs may be - in fact, are likely to be - called asynchronously. For a
given page, they will always be called in the sequence that page lists them
in, but there is no guarantee that any two adjacent Acteurs will be called on
the same thread. Any shared state should take the form of objects put into
the context when the output State is created.
This makes it possible to incrementally respond to a request, for example,
doing just enough computation to determine if a NOT MODIFIED response is
possible without computing the complete response (which in that case would be
thrown away).
Their asynchronous nature means that many requests can be handled
simultaneously and run small bits of logic, interleaved, on fewer threads,
for maximum throughput.
Support for asynchronous computation
Acteurs are asynchronous in nature, but by default the framework assumes they can be run one after the other. In the case an Acteur needs to call out to some library (perhaps an asynchronous database driver) which will asynchronously do some work and invoke a callback on another thread, there are a number of options to defer execution of further acteurs until the result is ready. With support for Java 8, a variety of flexible ways to do that are available (the original mechanism, requesting injection of aDeferral
object is also still supported):
- Use
then()to pass in aCompletableFuturewhose result object will be serialized as the response. - Use
continueAfter()to pass one or moreCompletableFutures and have all of their results available for injection into subsequent acteurs in the chain - Use
defer()to pause the chain and get back an instance ofCompletableFuturewhich you can callcomplete()orcompleteExceptionally()on once the work is complete or an error has occurred - Use
deferThenRespond()to pause the chain and get back an instance ofCompletableFuturewhose contents will be marshalled into the response once you callcomplete()orcompleteExceptionally().
next() -
the framework takes care of that (with an injected Deferral
instance, you did). In all cases, if a CompletableFuture
completes exceptionally, an error response is generated and no subsequent
Acteurs are run.
With either of the methods which return a CompletableFuture, you
must call complete() or completeExceptionally()
no matter what happens or your application will suffer from
"request dropped on the floor" bugs where the connection is held open but no
response is ever sent.- Author:
- Tim Boudreau
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected classprotected classState indicating that this acteur chain is taking responsibility for responding to the request.static interfaceIf you write an acteur which delegates to another one, implement this so that that other one's changes to the response will be picked up.protected classA state indicating the acteur neither accepts nor definitively refuses a request.classA shorthand state for responding with a particular http response code and optional message, which if non-string, will be rendered as JSON. -
Field Summary
Fields inherited from class com.mastfrog.acteurbase.AbstractActeur
creationStackTrace -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedActeur()Create an acteur; subclasses should simply list objects they need for processing the request as arguments, and they will be injected by Guice, either from bindings the application was set up with, or objects provided by other Acteurs which have already been run for this request. -
Method Summary
Modifier and TypeMethodDescriptionprotected <T> Acteuradd(HeaderValueType<T> decorator, T value) protected final Acteurprotected final ActeurbadRequest(Object msg) protected final ActeurcontinueAfter(boolean unwrapArrays, CompletionStage<?>... stages) Continue the Acteur chain, running any subsequent acteurs, once the passed CompletionStages (e.g.protected final <T> ActeurcontinueAfter(com.mastfrog.function.throwing.ThrowingConsumer<EnhCompletableFuture<T>> c) Continue the acteur chain once the completable future passed to the passed consumer is consumed.protected final ActeurcontinueAfter(CompletionStage<?>... stages) Continue the Acteur chain, running any subsequent acteurs, once the passed CompletionStages (e.g.protected final <T> EnhCompletableFuture<T>defer()Pause the Acteur chain until external code completes the returned CompletableFuture, then restart the acteur chain with the result of the computation available for injection into subsequent acteurs.protected final <T> EnhCompletableFuture<T>Pause the Acteur chain until external code completes the returned CompletableFuture, then use the result of that computation as the response (JSON or whatever the application is configured to marshal responses to).protected final <T> EnhCompletableFuture<T>deferThenRespond(io.netty.handler.codec.http.HttpResponseStatus successStatus) Pause the Acteur chain until external code completes the returned CompletableFuture, then use the result of that computation as the response (JSON or whatever the application is configured to marshal responses to).protected final com.mastfrog.giulius.DependenciesvoiddescribeYourself(Map<String, Object> into) Provide a description used in help-page generation.protected <T> Tget(HeaderValueType<T> header) Object[]protected com.mastfrog.acteur.ResponseImplprotected StategetState()protected final Acteurprotected final Acteurprotected final ActeurnotFound()protected final Acteurprotected final Acteurok()protected final Acteurprotected final Acteurreject()protected final Acteurprotected final Acteurreply(io.netty.handler.codec.http.HttpResponseStatus status) protected final Acteurprotected final Responseresponse()final ActeursetChunked(boolean chunked) final ActeursetMessage(Object message) final ActeursetResponseBodyWriter(io.netty.channel.ChannelFutureListener listener) Set a ChannelFutureListener which will be called after headers are written and flushed to the socket; prefersetResponseWriter()to this method unless you are not using chunked encoding and want to stream your response (in which case, be sure to chunked(false) or you will have encoding errors).protected final <T extends io.netty.channel.ChannelFutureListener>
ActeursetResponseBodyWriter(Class<T> type) Set a ChannelFutureListener which will be called after headers are written and flushed to the socket; prefersetResponseWriter()to this method unless you are not using chunked encoding and want to stream your response (in which case, be sure to setChunked(false) or you will have encoding errors).final ActeursetResponseCode(io.netty.handler.codec.http.HttpResponseStatus status) protected final <T extends ResponseWriter>
ActeursetResponseWriter(Class<T> writerType) Set a response writer which can iteratively be called back until the response is completed.protected final <T extends ResponseWriter>
ActeursetResponseWriter(T writer) Set a response writer which can iteratively be called back until the response is completed.protected final Acteurthen(com.mastfrog.function.throwing.ThrowingConsumer<Deferral.Resumer> cons) Defer the acteur chain, allowing the passed ThrowingConsumer to run any amount of asynchonous logic, and callResumer.resume()with objects to be available for injection into subsequent Acteurs.protected final <T> Acteurthen(CompletionStage<T> c) Pass a CompletionStage (for example, CompletableFuture) which will execute asynchronously.protected final <T> Acteurthen(CompletionStage<T> c, io.netty.handler.codec.http.HttpResponseStatus successStatus) Pass a CompletionStage (for example, CompletableFuture) which will execute asynchronously.static ActeurMethods inherited from class com.mastfrog.acteurbase.AbstractActeur
setState
-
Constructor Details
-
Acteur
protected Acteur()Create an acteur; subclasses should simply list objects they need for processing the request as arguments, and they will be injected by Guice, either from bindings the application was set up with, or objects provided by other Acteurs which have already been run for this request.- Parameters:
async- If true, the framework should prefer to run the next action asynchronously
-
-
Method Details
-
getState
- Overrides:
getStatein classAbstractActeur<Response,com.mastfrog.acteur.ResponseImpl, State>
-
getContextContribution
-
add
-
getResponse
protected com.mastfrog.acteur.ResponseImpl getResponse()- Overrides:
getResponsein classAbstractActeur<Response,com.mastfrog.acteur.ResponseImpl, State>
-
get
-
setResponseCode
-
setMessage
-
setChunked
-
response
- Overrides:
responsein classAbstractActeur<Response,com.mastfrog.acteur.ResponseImpl, State>
-
describeYourself
Provide a description used in help-page generation. Acteurs which are instantiated declaratively need not override this, as information will be generated from the annotations on the acteur and any description provided- Parameters:
into- A map to put key/value pairs into
-
noContent
-
badRequest
-
badRequest
-
notFound
-
notFound
-
ok
-
ok
-
reply
-
reply
-
reply
-
reject
-
next
-
continueAfter
Continue the Acteur chain, running any subsequent acteurs, once the passed CompletionStages (e.g. CompletableFuture) have completed - this makes it possible to run ad-hoc asynchronous logic with the acteur chain paused, and automatically resume it when finished.- Parameters:
stages- One or more CompletionStage instances.- Returns:
- This acteur
- Since:
- 2.1.0
-
continueAfter
protected final <T> Acteur continueAfter(com.mastfrog.function.throwing.ThrowingConsumer<EnhCompletableFuture<T>> c) Continue the acteur chain once the completable future passed to the passed consumer is consumed. The consumer is guaranteed not to be called until after the acteur constructor has exited.- Type Parameters:
T- The type of result that will be provided asynchronously to subsequent acteurs- Parameters:
c- A consumer which will receive the future- Returns:
- this
- Since:
- 2.4.1
-
continueAfter
Continue the Acteur chain, running any subsequent acteurs, once the passed CompletionStages (e.g. CompletableFuture) have completed - this makes it possible to run ad-hoc asynchronous logic with the acteur chain paused, and automatically resume it when finished.- Parameters:
unwrapArrays- If the object placed in a completion stage is an array, put all of its elements into context for the subsequent Acteurs, rather than the array itselfstages- One or more CompletionStage instances.- Returns:
- This acteur
- Since:
- 2.2.2
-
deferThenRespond
Pause the Acteur chain until external code completes the returned CompletableFuture, then use the result of that computation as the response (JSON or whatever the application is configured to marshal responses to).- Type Parameters:
T- The type parameter for the returned CompletableFuture.- Returns:
- A CompletableFuture
- Since:
- 2.1.0
-
deferThenRespond
protected final <T> EnhCompletableFuture<T> deferThenRespond(io.netty.handler.codec.http.HttpResponseStatus successStatus) Pause the Acteur chain until external code completes the returned CompletableFuture, then use the result of that computation as the response (JSON or whatever the application is configured to marshal responses to).- Type Parameters:
T- The type parameter for the returned CompletableFuture.- Parameters:
successStatus- The HTTP status to respond with if the result is completed normally- Returns:
- A CompletableFuture
- Since:
- 2.2.2
-
defer
Pause the Acteur chain until external code completes the returned CompletableFuture, then restart the acteur chain with the result of the computation available for injection into subsequent acteurs.- Type Parameters:
T- The type parameter for the returned CompletableFuture.- Returns:
- A CompletableFuture
- Since:
- 2.1.0
-
then
Defer the acteur chain, allowing the passed ThrowingConsumer to run any amount of asynchonous logic, and callResumer.resume()with objects to be available for injection into subsequent Acteurs.- Parameters:
cons- The consumer- Returns:
- This acteur
- Since:
- 2.1.0
-
then
Pass a CompletionStage (for example, CompletableFuture) which will execute asynchronously. The acteur chain will be paused until the stage completes; if it completes exceptionally, the usual handling for thrown exceptions will generate the response; if it completes normally, it will be encoded as the response object (by default, to JSON).- Type Parameters:
T- The return type of the completion stage- Parameters:
c- A completion stage- Returns:
- This acteur
- Since:
- 2.1.0
-
then
protected final <T> Acteur then(CompletionStage<T> c, io.netty.handler.codec.http.HttpResponseStatus successStatus) Pass a CompletionStage (for example, CompletableFuture) which will execute asynchronously. The acteur chain will be paused until the stage completes; if it completes exceptionally, the usual handling for thrown exceptions will generate the response; if it completes normally, it will be encoded as the response object (by default, to JSON).- Type Parameters:
T- The return type of the completion stage- Parameters:
c- The completion stagesuccessStatus- An HttpResponseStatus to use if the stage completes normally- Returns:
- This acteur
- Since:
- 2.1.0
-
setResponseWriter
Set a response writer which can iteratively be called back until the response is completed. The writer will be created dynamically but any object currently in scope can be injected into it.- Type Parameters:
T- The type of writer- Parameters:
writerType- The writer class
-
setResponseWriter
Set a response writer which can iteratively be called back until the response is completed.- Type Parameters:
T- The type of writer- Parameters:
writer- The writer
-
setResponseBodyWriter
protected final <T extends io.netty.channel.ChannelFutureListener> Acteur setResponseBodyWriter(Class<T> type) Set a ChannelFutureListener which will be called after headers are written and flushed to the socket; prefersetResponseWriter()to this method unless you are not using chunked encoding and want to stream your response (in which case, be sure to setChunked(false) or you will have encoding errors). This method will dynamically construct the passed listener type using Guice, and including all of the contents of the scope in which this call was made.- Type Parameters:
T- a type- Parameters:
type- The type of listener
-
dependencies
protected final com.mastfrog.giulius.Dependencies dependencies() -
setResponseBodyWriter
Set a ChannelFutureListener which will be called after headers are written and flushed to the socket; prefersetResponseWriter()to this method unless you are not using chunked encoding and want to stream your response (in which case, be sure to chunked(false) or you will have encoding errors).- Parameters:
listener-
-
wrap
-