boxlang-core-dev-bif-development
BoxLang BIF Development
Overview
Built-in functions (BIFs) are globally available functions in BoxLang — no imports
needed. When placed in a module's bifs/ directory, they are automatically
discovered and registered at module load time. BIFs can be implemented in either
BoxLang or Java.
BoxLang BIF
Minimal Example
// bifs/Greet.bx
// File name = function name (case-insensitive: greet, Greet, GREET all work)
@BoxBIF
class {
function invoke( required string name ) {
return "Hello, #arguments.name#!"
}
}
// Usage anywhere in BoxLang (no import)
greet( "Ada" ) // "Hello, Ada!"
Full-Featured BoxLang BIF
// bifs/StringTitleCase.bx
@BoxBIF
class {
/**
* Converts a string to title case.
*
* @str The input string
* @delimiters Word delimiters (default: space)
* @return Title-cased string
*/
string function invoke(
required string str,
string delimiters = " "
) {
if ( !len( arguments.str ) ) return ""
var words = listToArray( arguments.str, arguments.delimiters )
return words
.map( (w) -> uCase( left(w,1) ) & lCase( mid(w,2,len(w)) ) )
.toList( arguments.delimiters )
}
}
Java BIF
For performance-critical functions or when you need deep JVM access:
// src/main/java/com/example/bifs/StringTitleCase.java
package com.example.bifs;
import ortus.boxlang.runtime.bifs.BIF;
import ortus.boxlang.runtime.bifs.BoxBIF;
import ortus.boxlang.runtime.bifs.BoxMember;
import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.scopes.ArgumentsScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.types.BoxLangType;
@BoxBIF
// Optional: also register as a member function on String
@BoxMember( type = BoxLangType.STRING, name = "titleCase" )
public class StringTitleCase extends BIF {
// Declare argument metadata
public StringTitleCase() {
super();
declaredArguments = new Argument[] {
new Argument( true, "string", Key.of( "str" ) ),
new Argument( false, "string", Key.of( "delimiters" ), " " )
};
}
/**
* @param context Current execution context
* @param arguments Function arguments scope
*/
@Override
public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
String str = arguments.getAsString( Key.of( "str" ) );
String delimiters = arguments.getAsString( Key.of( "delimiters" ) );
if ( str == null || str.isEmpty() ) return "";
String[] words = str.split( "[" + delimiters + "]" );
StringBuilder sb = new StringBuilder();
for ( int i = 0; i < words.length; i++ ) {
if ( i > 0 ) sb.append( delimiters.charAt( 0 ) );
if ( !words[i].isEmpty() ) {
sb.append( Character.toUpperCase( words[i].charAt(0) ) );
sb.append( words[i].substring(1).toLowerCase() );
}
}
return sb.toString();
}
}
With @BoxMember, the BIF is also callable as a member function:
"hello world".titleCase() // "Hello World"
titleCase( "hello world" ) // "Hello World" (BIF style)
Key Java Classes for BIF Development
| Class/Interface | Package | Purpose |
|---|---|---|
BIF |
ortus.boxlang.runtime.bifs |
Base class for all BIFs |
@BoxBIF |
ortus.boxlang.runtime.bifs |
Marks a class as a BIF |
@BoxMember |
ortus.boxlang.runtime.bifs |
Registers as member function |
IBoxContext |
ortus.boxlang.runtime.context |
Current execution context |
ArgumentsScope |
ortus.boxlang.runtime.scopes |
Typed argument access |
Key |
ortus.boxlang.runtime.scopes |
String key interning |
Argument |
ortus.boxlang.runtime.types |
Argument descriptor |
BoxLangType |
ortus.boxlang.runtime.types |
Enum of BoxLang types |
BoxRuntime |
ortus.boxlang.runtime |
Runtime singleton |
Accessing BoxRuntime Services From a BIF
import ortus.boxlang.runtime.BoxRuntime;
import ortus.boxlang.runtime.cache.providers.ICacheProvider;
import ortus.boxlang.runtime.services.CacheService;
@BoxBIF
public class CachedFetch extends BIF {
private BoxRuntime runtime = BoxRuntime.getInstance();
@Override
public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
String url = arguments.getAsString( Key.of( "url" ) );
CacheService cacheService = runtime.getCacheService();
ICacheProvider cache = cacheService.getDefaultCache();
Object cached = cache.get( Key.of( url ) );
if ( cached != null ) return cached;
// Fetch data...
Object result = fetchFromUrl( url );
cache.set( Key.of( url ), result, 300L, 0L ); // 300s TTL
return result;
}
}
Accessing Context Services
@Override
public Object invoke( IBoxContext context, ArgumentsScope arguments ) {
// Get the current request scope
IScope requestScope = context.getScopeNearby( RequestScope.name );
// Get the application scope
IScope appScope = context.getScopeNearby( ApplicationScope.name );
// Get the session scope
IScope sessionScope = context.getScopeNearby( SessionScope.name );
// Resolve a variable
Object val = context.scopeFindNearby( Key.of( "myVar" ), null ).value();
// Invoke another function
Object result = context.invokeFunction( Key.of( "len" ), new Object[]{ "hello" } );
return result;
}
BoxLang BIF with Runtime Access
// bifs/GetAppSetting.bx
@BoxBIF
class {
function invoke( required string key, any defaultValue = "" ) {
// Access the BoxRuntime
var runtime = boxRuntime
var appScope = getApplicationScope() // available in web context
return appScope.keyExists( arguments.key )
? appScope[ arguments.key ]
: arguments.defaultValue
}
}
Registering a BIF Alias
// Register under multiple names via multiple @BoxBIF annotations
@BoxBIF
@BoxBIF( alias = "strTitleCase" )
@BoxBIF( alias = "toTitleCase" )
public class StringTitleCase extends BIF { ... }
Member Function Registration
Member functions are BIFs callable on a specific type using dot notation:
@BoxBIF
@BoxMember( type = BoxLangType.ARRAY, name = "shuffle" ) // array.shuffle()
@BoxMember( type = BoxLangType.STRING, name = "toSlug" ) // str.toSlug()
@BoxMember( type = BoxLangType.STRUCT, name = "deepMerge" ) // struct.deepMerge()
public class MyBIF extends BIF { ... }
[3,1,2].shuffle()
"Hello World".toSlug() // "hello-world"
config.deepMerge( overrides )
BIF Argument Types
// Argument types available in ortus.boxlang.runtime.types.Argument
new Argument( required, type, key )
new Argument( required, type, key, defaultValue )
// Types: "any", "string", "numeric", "boolean", "array", "struct",
// "query", "date", "function", "closure", "lambda", "class"
Testing Your BIF
// tests/specs/MyBIFTest.bx
class extends="testbox.system.BaseSpec" {
function run() {
describe( "greet BIF", function() {
it( "should greet a person by name", function() {
expect( greet("Ada") ).toBe( "Hello, Ada!" )
})
it( "should handle empty name", function() {
expect( greet("") ).toBe( "Hello, !" )
})
it( "should be callable as member function", function() {
expect( "Ada".titleCase() ).toBe( "Ada" )
expect( "hello world".titleCase() ).toBe( "Hello World" )
})
})
}
}
box testbox run
Discovering Registered BIFs
// List all registered BIFs (including your custom ones)
writeDump( getFunctionList() )
// Check if a specific BIF exists
if ( structKeyExists( getFunctionList(), "greet" ) ) {
writeOutput( "greet BIF is registered!" )
}
References
More from ortus-boxlang/skills
boxlang-functional-programming
Use this skill when working with BoxLang lambdas, closures, arrow functions, higher-order functions, functional array/struct pipelines (map, filter, reduce, flatMap, groupBy, etc.), destructuring, or spread syntax.
10boxlang-code-reviewer
Use this skill when reviewing BoxLang code for quality, correctness, security vulnerabilities, performance issues, style violations, or when providing structured code review feedback following BoxLang best practices and security guidelines.
9boxlang-best-practices
Use this skill when writing, reviewing, or improving BoxLang code to ensure it follows community best practices for naming, structure, scoping, error handling, performance, and maintainability.
9boxlang-classes-and-oop
Use this skill when writing BoxLang classes, components, interfaces, inheritance hierarchies, annotations, properties, constructors, or applying object-oriented design patterns in BoxLang.
9boxlang-web-development
Use this skill when building BoxLang web applications: Application.bx lifecycle, request/response handling, sessions, forms, REST APIs, HTTP clients, routing, CSRF protection, Server-Sent Events, or configuring CommandBox/MiniServer.
8boxlang-configuration
Use this skill when configuring BoxLang runtime settings via boxlang.json, setting environment variables for config overrides, configuring datasources, caches, executors, modules, logging, security, or schedulers — or when helping someone understand the BoxLang configuration system.
8