# 1.0.0-Beta3

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

## New Features

### [BL-256](https://ortussolutions.atlassian.net/browse/BL-256) Implement query cache ability

Thanks to our enterprise cache engine and aggregator built into BoxLang, you can now use it to cache queries via its `options` configuration structure using `cfquery` or `queryExecute`. Here are the query caching properties you can use:

* `cache:boolean` - To turn on caching, this must be `true`. The default is `false`
* `cacheTimeout:timespan` - Optional timeout of the query in the cache. By default, is uses whatever the default timeout of items the cache has been configured with.
* `cacheLastAcccessTimeout:timespan` - Optional last access or idle timeout of the query in the cache. By default, is uses whatever the default timeout of items the cache has been configured with. This means that if this query is NOT used or requested in this timespan, it will be marked for eviction.
* `cacheProvider:string` - The name of the cache provider to store the queries. By default, we use the `DEFAULT` cache in BoxLang.

```cfscript
queryExecute(
    "SELECT * FROM developers WHERE role = ?",
    [ "Developer" ],
    { cache: true }
);
```

By default, queries will use [the default Boxlang CacheProvider](https://github.com/ortus-boxlang/BoxLang/blob/development/src/main/resources/config/boxlang.json), which has default timeouts and `lastAccessTimeout` values set.

To specify a custom caching provider, you can use the `cacheProvider` query option:

```cfscript
queryExecute(
    "SELECT * FROM developers WHERE role = ?",
    [ "Developer" ],
    { cache: true, cacheProvider : "redis" }
);
```

To specify custom cache entry timeouts, use `cacheTimeout` or `cacheLastAccessTimeout`:

```cfscript
queryExecute(
    "SELECT * FROM developers WHERE role = ?",
    [ "Developer" ],
    {
        cache: true,
        cacheTimeout : createTimespan( 0, 0, 0, 30 ),
        cacheLastAccessTimeout : createTimespan( 0, 0, 0, 30 )
    }
);
```

{% hint style="warning" %}
Note that the `bx-compat-cfml` module will take care of implementing [the historical `cachedWithin` and `cachedAfter` query options](https://cfdocs.org/cfquery).
{% endhint %}

#### Metadata

All query metadata will also have the cache information available to you as well. So you if get dump the query metadata you will see a ton of debugging information about the query:

```cfscript
writedump( myQuery.$bx.meta )
```

#### Interacting With The Cache

Please note that this leverages the BoxLang cache. This means you have full access to the cache provider and you can interrogate it for queries, clear all of them, or clear one of them. The default prefix used for all cached queries is: `BL_QUERY`

```cfscript
// Clear everything in the default cache
getBoxCache()
    .clearAll()

// Clear only the cached queries
getBoxCache()
    .clearAll( key-> key.getName().startsWith( "BL_QUERY" ) )

// Get a list of all cached queries
getBoxCache()
    .getKeys( key-> key.getName().startsWith( "BL_QUERY" ) )

// Get a stream of all the cached queries
getBoxCache()
    .getKeysStream( key-> key.getName().startsWith( "BL_QUERY" ) )
```

### [BL-261](https://ortussolutions.atlassian.net/browse/BL-261) coerce java SAMs from BoxLang function interfaces

This is another major milestone in the Java interop features of BoxLang. This allows us to coerce any BoxLang Lambda/Closure/UDF or even Classes to ANY, yes, ANY Java Functional Interface or Java SAM (Single Abstract Method Interface).

```cfscript
// Build your own Java comparators with BoxLang
Collections.sort(
    myArray or Java Array,
    (s1, s2) -> compareNoCase( s1, s2 )
)

// Create your own threads and completable futures
CompletableFuture.supplyAsync( () -> println( "Running in a thread" ) )

// Java predicates
arrayOfNumbers = [1,22,3,34,34,556]
arrayOfNumbers.stream()
    .filter( n -> n % 2 == 0 )
    .toList()
```

### [BL-281](https://ortussolutions.atlassian.net/browse/BL-281) AsyncService support for Virtual Thread Executors (create/manage)

Virtual Threads are now available to BoxLang via executors. You can choose the new `VIRTUAL` executor for schedulers or when creating schedulers via our AsyncService. This will treat all tasks and schedules to use virtual threads.

```cfscript
// Create, register and return
getBoxRuntime().getAsyncService()
    .newVirtualExecutor( "MyVirtualExecutor" )
```

More entry points to access this executor will be provided in the coming betas, alongside our very own `runAsync()` and the ability to create virtual threads as well.

### [BL-284](https://ortussolutions.atlassian.net/browse/BL-284) Bifs for module info: getModuleList() getModuleInfo( module )

As more modules are being developed for BoxLang, you now have the ability to know which modules have been loaded and activated in the language. As well as specific information about a module if needed. This is great for inter-dependencies and checking if modules have loaded from BoxLang.

```cfscript
writedump( getModuleList() )
writeDump( getModuleInfo( "bx-image" ) )
```

<figure><img src="https://1598982152-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4ENvvb4b3Cmrr1qKj7y4%2Fuploads%2Fgit-blob-69febbd92cb7e79de4b5f84824f54e239ca961cc%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

### [BL-285](https://ortussolutions.atlassian.net/browse/BL-285) Dumping of Java Classes now includes a dump of the \`toString()\` value to visualize values better

This is a developer eye-candy, so when you dump any Java class, you can actually see the value of the class instance data via the `toString()` method.

<figure><img src="https://1598982152-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4ENvvb4b3Cmrr1qKj7y4%2Fuploads%2Fgit-blob-75984ddee19ce4b740dcfaed620bdfc317c0f792%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

### [BL-289](https://ortussolutions.atlassian.net/browse/BL-289) New dump template for BL Functions

The dumping of BoxLang Functions (Closures, Lambdas, UDFs), either standalone or from a class, has great visibility now. You can see even the class used to generate the function, the function annotations, and much more.

<figure><img src="https://1598982152-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4ENvvb4b3Cmrr1qKj7y4%2Fuploads%2Fgit-blob-3aadc37bd8a30a79d98e394ed80c3c1d2e5540cb%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

### [BL-292](https://ortussolutions.atlassian.net/browse/BL-292) Allow the `createDynamicProxy` bif to support the request class loader so it can load classes from loaded libraries in the application.bx, runtime and more.

If you use `createDynamicProxy()` to make a BoxLang class look like a Java class, you can continue to do so now, but it accounts for all class loaders in the application. If you come from a CFML engine, this is impossible and is always a pain and limitation.

In BoxLang, your context matters. So depending on where you create the dynamic proxy, it will account for the surrounding class loaders to be able to create the appropriate Java proxies.

```cfscript
createDynamicProxy( myclass, [ array of interfaces ] )
createDynamicProxy( myclass, interface path )
```

### [BL-298](https://ortussolutions.atlassian.net/browse/BL-298) New Script Binaries for `bxCFTranspiler`, `bxCompiler`, `bxFeatureAudit` tools in the distribution bin folder

We have introduced Windows and Mac/Linux binaries for running several CLI tools. You no longer need to refer to the docs with extra-long options. You can now use the provided binaries to call the appropriate CLI tool.

If you use the quick installer, all these binaries will be installed for you.

<figure><img src="https://1598982152-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4ENvvb4b3Cmrr1qKj7y4%2Fuploads%2Fgit-blob-dc94b4a959512bea497201569a512ebf4f5e2301%2Fimage.png?alt=media" alt=""><figcaption></figcaption></figure>

## Improvements

[BL-254](https://ortussolutions.atlassian.net/browse/BL-254) Refactor JDBC connection retrieval out of the QueryOptions class

[BL-280](https://ortussolutions.atlassian.net/browse/BL-280) Dynamic method matching discovery algorithms updated to do 2 pass algorithm: exact, loose coercion matching

[BL-283](https://ortussolutions.atlassian.net/browse/BL-283) Improvement of cache service and cache provider methods for easier boxlang interactions

[BL-290](https://ortussolutions.atlassian.net/browse/BL-290) Refactored the dump css to \`resources/dump/html/Dump.css\`

[BL-291](https://ortussolutions.atlassian.net/browse/BL-291) Migrate dynamic proxies to native java implementation from the JDK

[BL-296](https://ortussolutions.atlassian.net/browse/BL-296) passing the session id to the onsessionstart listener

[BL-297](https://ortussolutions.atlassian.net/browse/BL-297) Give better warnings if the sessionStorage is not a valid string

## Bug

[BL-198](https://ortussolutions.atlassian.net/browse/BL-198) attributecollection not handled properly on cfthrow

[BL-278](https://ortussolutions.atlassian.net/browse/BL-278) Left in system out calls that need to be removed

[BL-279](https://ortussolutions.atlassian.net/browse/BL-279) JSR ScriptEngine starting runtime without debug flag if passed

[BL-282](https://ortussolutions.atlassian.net/browse/BL-282) Creating a default cache was not setting the right name and a "default" already registered exception was being thrown

[BL-286](https://ortussolutions.atlassian.net/browse/BL-286) Default argument values not always checked for type

[BL-287](https://ortussolutions.atlassian.net/browse/BL-287) Implements missing from Box Class metadata

[BL-288](https://ortussolutions.atlassian.net/browse/BL-288) Static Scope missing from metadata
