Interceptors
BoxLang is an event-driven language and you can not only listen, but register and announce events.
Last updated
Was this helpful?
BoxLang is an event-driven language and you can not only listen, but register and announce events.
Last updated
Was this helpful?
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.
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
BoxLang has 3 interceptor pools that will emit events:
Global Runtime
- The entire BoxLang runtime
Application.bx Request Listener
- The request listener for an application
CacheProviders
- The BoxCache providers
When you register interceptors, they will be registered within any of these pools.
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.
If they are closures, they will have the following format:
Interceptors can be registered via the following approaches into the different pools
A module
Registers into the global runtime
ModuleConfig.bx interceptors
array
A Java class via Service Loader
BIFs
boxRegisterInterceptor()
- Register into the global runtime
boxRegisterRequestInterceptor()
- 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.
You can create an interceptors
array for registration inside the ModuleConfig.bx
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.
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
.
Interceptors when defined in a module can be defined using a structure of properties which are passed to (Java) and injected (BoxLang).
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.
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...