Package com.mastfrog.acteur
package com.mastfrog.acteur
Acteur
This is a lightweight web framework that sits on top of Netty, the asynchronous Java NIO server framework. Its goal is to solve a specific problem that must be addressed to make asynchronous frameworks usable for non-trivial tasks: That most back-end APIs in Java are synchronous. It's wonderful that you can write a non-blocking, asynchronous web server that can handle thousands of connections at a time with a single thread. But as soon as that server needs to talk to something else - say a database, or even just a file, all of that scalability goes away and you have a single-threaded server which is offline until its done having a conversation with something else. In other words, asynchronous is only useful if the entire stack is asynchronous. One of the wonderful things about Java is the amount of libraries available, and most of them expect to do blocking I/O. So you need, at the least, some sort of threading model that lets you pretend your blocking back-end calls are actually non-blocking. The standard way to do asynchronous programming is callbacks. That is how you do it in popular frameworks such as Node.js. But that creates its own problem: Such programs usually have deeply nested callback structures which are hard to read and harder to reuse; and in a language like javascript, it is easy to have bugs by doing things like referencing a loop variable from a callback that runs long after the loop completed. The Java equivalent would have you writing scads of deeply nested inner classes - which you can do, but that tends not to result in readable or maintainable code. So we have a few problems to solve:- People like to think about programming as linear sequences of events, not callbacks
- The closest Java comes to function objects are anonymous inner classes, and they are verbose
- Deeply nested inline callbacks, even if they do something useful, are painful to extract into actually reusable logic
Acteurs
The name comes from Jaroslav Tulach's observation that this library is more-or-less the Actor pattern, but looks a little strange. So, an Acteur is an Actor...but slightly foreign :-) An Acteur does all of its work either in its constructor, culminating in a call tosetState(), or in its override of getState().
You bundle together a list of Acteurs in a Page - a Page is really a list
of Acteurs to run to validate a request and set up a response, and an aggregation
point for things like response headers and whatever will write response data.
Acteurs are instantiated by Google Guice - in fact, you assemble a page largely
by giving it a list of Acteur subclasses; they will be instantiated as
needed.
In particular, each Acteur only plays one role. Say that the logic involved
in loading a page involves:
- Check that the URL requested is legal
- Check the request cache header IF_MODIFIED_SINCE, and if present and its condition holds, respond with NOT_MODIFIED
- Authenticate the user
- Find the object expressed by the URL
- Write it into the response
AuthenticateBasicActeur
actually does:
public class AuthenticateBasicActeur extends Acteur {
-
ClassDescriptionA 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 Acteurs are aggregated into a list in a
Page.If 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.Factory for standard Acteur implementations, mainly used to determine if a request is valid (matches a URL, is using a supported HTTP method, etc.).A test which can be performed on a request, for example, to decide about branchingA web application.Processes the page annotations in com.mastfrog.acteur.preconditions and adds acteurs to the list appropriately.Convenience Acteur which compares the current Page's Date against the current request's If-Modified-Since header and returns a 304 response if the browser's cached version is current.Convenience Acteur which compares the current Page's ETag against the current request's If-None-Match header and returns a 304 response if the browser's cached version is current.Subclasses of this can be used from the @Early annotation to provide an object that will process inbound HTTP chunks.A registry of resources (for example, streams or JDBC objects) which should be closed if the connection terminates while a response is being processed.Converts byte buffers and maps to objectsDecorates cors responses.Encapsulates either an object indicating success, or a throwable indicating failure, which is written to a response using DeferredComputationResultActeur (added automatically to the chain if you useActeur.then(CompletableFuture).Event<T>An HTTP request or similar, which is passed to Pages for their Acteurs to respond to.Bind in guice to customize 404 not found responses, and failures that cannot be handled by ErrorRenderer (i.e.If this annotation appears on an Application, it automatically makes a Help page available.Generates JSON help for the application; HelpPage converts this into HTML.Allows code to be plugged in to contribute to the help page information about specific types of annotation.Deprecated.- With Acteur 1.5 and ServerBuilder, you are not subclassing application anymore, so this class is less useful as it can only appear on the application class.Interface which, if present, will be invoked before entering request scope and can provide a set of objects to make available in the request scope, which will be consistent regardless of the page/acteur chain which eventually handles responding to the request (if any).Really an aggregation of Acteurs and a place to set header values; in recent versions of Acteur it is rarely necessary to implement this - instead, simply annotate your entry-point Acteur with @HttpCall and one will be generated for you under-the-hood, and use @Precursors and @Concluders to specify Acteurs that should run before/after that one.Logger which can be injected, which takes care of actually logging each request and response.Abstraction for a responseAbstraction over Netty's channel/ByteBuf to insulate from changes there.The output condition of anActeur.