Interceptors
BoxLang is an event-driven language and you can not only listen, but register and announce events.
BoxLang is an event-driven language and it emits events throughout many different life-cycles. The entire framework for events is also extensible and can be used not only by Module developers but by anybody using the language in either BoxLang or Java. There are several core events that are emitted and you can register your own events we call interception points.

Event Driven Programming
The way that interceptors are used is usually referred to as event-driven programming, which can be very familiar if you are already doing any Nodejs or observer/observable coding. You can listen and execute intercepting points anywhere you like in your application, you can even produce content whenever you announce these events.
Events have unique names like: onRequestStart, onHTTPRequest, onParse

Event Emitters aka Interceptor Pools

BoxLang has 3 interceptor pools that will emit events:
Global Runtime
- The entire BoxLang runtimeApplication.bx Request Listener
- The request listener for an applicationCacheProviders
- The BoxCache providers
When you register interceptors, they will be registered within any of these pools.
Interceptors
In BoxLang, listeners are referred to as Interceptors. These can be built in Java or BoxLang as classes or closures/lambdas. If they are classes they can listen to multiple interception points and have a configure
method.
class{
function configure(){
// Any code to setup the interceptor
}
// Any methods that are the same name as the events
function onHTTPRequest( struct event ){
}
function preFunctionInvoke( struct event ){
}
}
If they are closures, they will have the following format:
( event ) => {
// Closure listener
}
( event ) -> {
// Lambda listener
}
Registration
Interceptors can be registered via the following approaches into the different pools
A module
Registers into the global runtime
ModuleConfig.bx
interceptors
arrayA Java class via Service Loader
BIFs
boxRegisterInterceptor()
- Register into the global runtimeboxRegisterRequestInterceptor()
- Register into the request listener
Java
InterceptorService
The interceptor service has several registration method according to different types. The
InterceptorService
is the global runtime.register( IInterceptor )
register( IInterceptor, properties )
register( IClassRunnable )
register( DynamicObject, states... )
register( IInterceptorLambda, states... )
CacheProvider specific poool
Each cache provider (BoxCache) has a
getInterceptorPool()
method which you can invoke and then you can use all of the pool methods for registration above.
ModuleConfig.bx
You can create an interceptors
array for registration inside the ModuleConfig.bx
// Interceptors registration
interceptors = [
{
class : "#moduleRecord.invocationPath#.interceptors.Listener"
properties : {
// configuration
}
}
];
BIFs
boxRegisterInterceptor( interceptor, [states=[]] )
boxRegisterRequestInterceptor( interceptor, [states=[]] )
The states
are the interception points to SPECICALLY register an interceptor to. If you omit it, then we will scan the interceptor for interception point states.
A closure/lambda when registered REQUIRES to which states to register to.
// Register an interceptor class in all discovered states
boxRegisterInterceptor( new MyInterceptor() )
// Register an interceptor class in all the passed states
// If those states have not been registered, register them
Configure()
The configure()
method in the interceptor can be used to bootstrap anything you might need once the interceptor is loaded and registered by the runtime. The Java counterparts have a BaseInterceptor
class and the configurations can have a structure of setup properties
.
function configure(){
}
Properties
Interceptors when defined in a module can be defined using a structure of properties which are passed to (Java) and injected (BoxLang).
interceptors = [
{
class : "#moduleRecord.invocationPath#.interceptors.Listener",
properties : {
createdOn : now(),
by : "Luis Majano"
}
}
];
Injections
If you are building BoxLang interceptors then you get a set of injections into your class' variables
scope.
name
The name of the interceptor, if any
properties
The structure of properties
log
A BoxLang logger that maps to the runtime
log file
interceptorService
A reference to the Interceptor Service
boxRuntime
A refernce to the Box Runtime class.
moduleRecord
If this interceptor belongs to a module, a reference to the modules record class will be injected as well.
Resources
For what can I use them
Below are just a few applications of BoxLang Interceptors:
Security
Event based Security
Method Tracing
AOP Interceptions
Publisher/Consumer operations
Implicit chain of events
Content Appending or Pre-Pending
View Manipulations
Custom SES support
Cache advices on insert and remove
Much much more...
Last updated
Was this helpful?