# 1.0.0-Beta5

BoxLang Betas are released weekly. This is our fifth beta marker. Here are the release notes.

## New Features

### [BL-319](https://ortussolutions.atlassian.net/browse/BL-319) Ability to call on \`navigate( String... paths)\` on the \`Configuration\` to create data navigators

The entire `boxlang.json` has now been updated to match the [CFConfig](https://cfconfig.ortusbooks.com/) project as much as it can. This ticket introduces a new method on the `Configuration` object that the core team and module developers can use to navigate the configuration structures fluently. The `navigate()` method produces a BoxLang [DataNavigator](https://s3.amazonaws.com/apidocs.ortussolutions.com/boxlang/1.0.0-beta5/ortus/boxlang/runtime/util/DataNavigator.Navigator.html) object, which allows you to navigate in, get keys, cast them, do defaults, and so much more.

```java
Configuration
    .navigate( "modules" )
    .ifPresent( "security", value -> this.name = Key.of( value ) );
```

Check out our data [navigator](/boxlang-language/syntax/data-navigators.md) docs for further information.

### [BL-320](https://ortussolutions.atlassian.net/browse/BL-320) Store the original last configuration seeded into the runtime as \`originalConfig\`

The configuration object also stores the original configuration struct from the last loaded boxlang.json. You can navigate it or retrieve it from anywhere within the BoxLang code. This is great for module developers, so they can have any setting they can retrieve later.

```cfscript
var renderInHtml = Configuration
    .navigate( "originalConfig", "modules", "pdf" )
    .getAsBoolean( "htmlREnder", false )
```

### [BL-322](https://ortussolutions.atlassian.net/browse/BL-322) New StringBind() bif and member function to bind a string with placeholder replacements using the \`${key}\`

We use this methodology everywhere in BoxLang core, so we now expose it as a BIF and member method for strings. The `stringBind()` allows you to pass in a string template, and bind it with a map of variables for you as long as it adheres to the binding pattern of: `${key:defaultValue}`

You can use it for mail merging, data merging, string templates, and so much more.

```cfscript
function renderMail(){
    myTemplate = """
    Hello ${name},
    
    I hope you have an awesome ${action} using BoxLang v${version:snapshot}
    """
    
    return stringBind( myTemplate, { 
        name : "Luis Majano",
        action : "Day"
    } );
}

function renderMail(){
    return """
    Hello ${name},
    
    I hope you have an awesome ${action} using BoxLang v${version:snapshot}
    """.bind( { 
        name : "Luis Majano",
        action : "Day"
    } );
}
```

### [BL-324](https://ortussolutions.atlassian.net/browse/BL-324) attempts now have an isNull() to explicitly determine if the value is null

We have just started talking about our Attempt class in BoxLang, a Java Optional on Steroids. It allows you to track values and act upon them depending on whether they exists or truthy/falsey. It provides many functional methods to produce fluent DSLs and is easier to work with any attempt at external resources or other things. The core will be moving towards returning attempts whenever it makes sense.

```cfscript
var userFound = attempt( userService.findBy( rc.id ) ).isNull()
```

Please see our docs on [Attempts](/boxlang-language/syntax/attempts.md) for further information.

### [BL-325](https://ortussolutions.atlassian.net/browse/BL-325) Allows Java methods to be referenced and passed around as a variable and invoked later like UDFs

### [BL-338](https://ortussolutions.atlassian.net/browse/BL-338) Allow Java functional interfaces and SAMs to be wrapped and used as functions

We’ve added more goodies to our BoxLang Java interop, this time around method references and high-order functions. BoxLang already allows you to grab a reference to a UDF or closure as a variable, pass it around, and invoke it.

```js
myInstance = new myClass();
myInstanceMethod = myInstance.myMethod;
myInstanceMethod();
```

BL also allows you to grab a reference to a **static** method from a Box class as well using the `::` notation.

```js
myStaticUDF = src.test.java.TestCases.phase3.StaticTest::sayHello;
myStaticUDF();
```

Now, in BoxLang, we’ve elevated Java methods, both instance and static also to be objects you can pass around, invoke, and send into a higher-order function (a function that accepts functions).

When you reference a method on a Java class without the parenthesis (just like our BL examples above), you will get a special Function instance that wraps up the Java method, allowing it to be treated as a function, passed into any argument which is typed as a function, and invoked headlessly.

Here, we capture the static value of the Java String class `valueOf()` method from and place it into a variable, where we invoke it.

```js
import java:java.lang.String;
javaStaticMethod = java.lang.String::valueOf;
result = javaStaticMethod( "test" ) // New string of "test"
```

This example captures the `toUpperCase` method from a String instance. Note the method is still bound to the original String instance and, when invoked, will be invoked against that original instance

```js
javaInstanceMethod = "my string".toUpperCase
result = javaInstanceMethod() // "MY STRING"
```

And finally, here we use a Java method to pass directly in place of a UDF or Closure to a higher order function.

```js
import java.util.Collections;
// Use the compare method from the Java reverse order comparator to sort a BL array
[ 1, 7, 3, 99, 0 ].sort( Collections.reverseOrder().compare  ) // [ 99, 7, 3, 1, 0 ]
```

We grab the `compare` method from Java’s reverse order comparator and pass it directly into the array sort method in BoxLang, reversing our array! Stay tuned, as more features are coming on Java interop.

### [BL-326](https://ortussolutions.atlassian.net/browse/BL-326) New Application global defaults in the boxlang.json

Our configuration is now solid leveraging cfconfig and we have now added several configuration items that will be used as defaults for all applications running under BoxLang. You will find this in the `boxlang.json`

```json
// The default timezone for the runtime; defaults to the JVM timezone if empty
// Please use the IANA timezone database values
"timezone": "",
// The default locale for the runtime; defaults to the JVM locale if empty
// Please use the IETF BCP 47 language tag values
"locale": "",
// If true, you can call implicit accessors/mutators on object properties. By default it is enabled
// You can turn it on here for all applications or in the Application.cfc
"invokeImplicitAccessor": true,
// Use Timespan syntax: "days, hours, minutes, seconds"
"applicationTimeout": "0,0,0,0",
// The request timeout for a request in seconds; 0 means no timeout
"requestTimeout": "0,0,0,0",
// The session timeout: 30 minutes
"sessionTimeout": "0,0,30,0",
// Where sessions will be stored by default.  This has to be a name of a registered cache
// or the keyword "memory" to indicate our auto-created cache.
// This will apply to ALL applications unless overridden in the Application.cfc
"sessionStorage": "memory",
// Set client cookies on applications
"setClientCookies" : true,
// Set domain cookies on applications
"setDomainCookies" : true,
// A collection of BoxLang mappings, the key is the prefix and the value is the directory
"mappings": {
	"/": "${user-dir}"
},
// A collection of BoxLang custom tag directories, they must be absolute paths
"customTagsDirectory": [
	"${boxlang-home}/customTags"
],
// A collection of directories we will class load all Java *.jar files from
"javaLibraryPaths": [
	"${boxlang-home}/lib"
],
// You can assign a global default datasource to be used in the language
"defaultDasource": "",
// The registered global datasources in the language
// The key is the name of the datasource and the value is a struct of the datasource settings
"datasources": {
	// "testDB": {
	// 	  "driver": "derby",
	//    "connectionString": "jdbc:derby:memory:testDB;create=true"
	// }
	// "testdatasource": {
	// 	  "driver": "derby",
	// 	  "host": "localhost",
	// 	  "port": 3306,
	// 	  "database": "test"
	// }
},
```

### [BL-330](https://ortussolutions.atlassian.net/browse/BL-330) new interception points when a session get's created and destroyed

We have introduced two new global interception points that modules can listen to:

<table><thead><tr><th width="241">Event</th><th width="126">Data</th><th>Description</th></tr></thead><tbody><tr><td><strong>onSessionCreated</strong></td><td>Session</td><td>When a new session is created and registered</td></tr><tr><td><strong>onSessionDestroyed</strong></td><td>Session</td><td>When a session is about to be destroyed</td></tr></tbody></table>

### [BL-339](https://ortussolutions.atlassian.net/browse/BL-339) All locations in the cache that returned optionals, now returns BoxLang Attempts

We have now moved internally from Optionals to Attemps in order to have consistency in our APIs. I am sure there are more things to do, but all cache interfaces and operations now rely on BoxLang Attempts.

```cfscript
return getBoxCache()
    .get( "maybeExists" )
    .orElse( "not found" );
```

### [BL-340](https://ortussolutions.atlassian.net/browse/BL-340) `getAsAttempt`() on the IStruct default methods for convenience

This is mostly for internal usage, where we can add native Java casting to struct operations to attempts.

### [BL-341](https://ortussolutions.atlassian.net/browse/BL-341) BoxCacheProviders now have a localized interceptor pool alongside the runtime pool

The BoxLang Cache now has a localized interception pool so it can also announce events locally and globally to the runtime. This allows you to have interceptors that can listen only at specific caches instead of all caches. We use this for example, to listen when sessions expire in applications:

```java
// Register the session cleanup interceptor
this.sessionsCache.getInterceptorPool()
    .register( data -> {
	    ICacheProvider targetCache = ( ICacheProvider ) data.get( "cache" );
	    String		key			= ( String ) data.get( "key" );

	    logger.debug( "Session cache interceptor [{}] cleared key [{}]", targetCache.getName(), key );

	    targetCache
	        .get( key )
	        .ifPresent( session -> ( ( Session ) session ).shutdown( this.startingListener ) );

	    return false;
    }, BoxEvent.BEFORE_CACHE_ELEMENT_REMOVED.key() );
```

Which brings about the next ticket:

[BL-342](https://ortussolutions.atlassian.net/browse/BL-342) Sessions are now monitored by cache interceptors to detect removals so as to shutdown the sessions before removal

### [BL-343](https://ortussolutions.atlassian.net/browse/BL-343) application, session, request timeouts in the boxlang.json are now string timespans

We have now added the capability to influence the application, request and session timeouts in configuration using the cfconfig standard of a string timespan:

```json
// Use Timespan syntax: "days, hours, minutes, seconds"
"applicationTimeout": "0,0,0,0",
// The request timeout for a request in seconds; 0 means no timeout
"requestTimeout": "0,0,0,0",
// The session timeout: 30 minutes
"sessionTimeout": "0,0,30,0",
```

### [BL-344](https://ortussolutions.atlassian.net/browse/BL-344) App Timeouts are now working

The default timeout for applications in BoxLang is `0`, which means they live forever. If you want to change it, then you will change it at the `boxlang.json` level or in the `Application.bx/cfc`

## Improvements

[BL-209](https://ortussolutions.atlassian.net/browse/BL-209) Combine config settings into a single struct

[BL-318](https://ortussolutions.atlassian.net/browse/BL-318) Allow optional attribute delimiters in ACF tag-in-script syntax

[BL-321](https://ortussolutions.atlassian.net/browse/BL-321) Refactor dump loading of CSS to use caching again

[BL-323](https://ortussolutions.atlassian.net/browse/BL-323) Refactor page pool to be per-mapping

[BL-329](https://ortussolutions.atlassian.net/browse/BL-329) **jsessionID** is the internal standard for boxlang sessions, move to this instead of cfid

[BL-332](https://ortussolutions.atlassian.net/browse/BL-332) `getOrSet`() in the cache should return the object not an optional

## Bugs Squashed

[BL-164](https://ortussolutions.atlassian.net/browse/BL-164) BL Compat module should coerce null values to empty string

[BL-252](https://ortussolutions.atlassian.net/browse/BL-252) MSSQL DROP TABLE throws 'The statement must be executed before any results can be obtained'

[BL-306](https://ortussolutions.atlassian.net/browse/BL-306) Adobe Compatibility: Missing support for new java() and new component()

[BL-308](https://ortussolutions.atlassian.net/browse/BL-308) cfinvoke does not support params as attribute-value pairs

[BL-316](https://ortussolutions.atlassian.net/browse/BL-316) If the global runtime \`javaLibraryPaths\` is already a jar/class location, then use it, else it breaks

[BL-317](https://ortussolutions.atlassian.net/browse/BL-317) allow "var" before CF catch variable in script

[BL-331](https://ortussolutions.atlassian.net/browse/BL-331) ResetSession on the scripting request context was invalidating the new session instead of the old session

[BL-333](https://ortussolutions.atlassian.net/browse/BL-333) Session creation if the default timeout is not a duration, it should treat it as seconds, not milliseconds

[BL-334](https://ortussolutions.atlassian.net/browse/BL-334) Session object was not serializable

[BL-335](https://ortussolutions.atlassian.net/browse/BL-335) Cache was evicting items without reaping

[BL-336](https://ortussolutions.atlassian.net/browse/BL-336) DateTime toString() not accounting for formatter being null

[BL-337](https://ortussolutions.atlassian.net/browse/BL-337) sessionRotate() not copying over old keys due to nullification of keys when invalidating the old session


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://boxlang.ortusbooks.com/readme/release-history/beta-stage/1.0.0-beta5.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
