# 1.0.0-Beta2

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

## Bug

[BL-140](https://ortussolutions.atlassian.net/browse/BL-140) `Writedump` expanded collapsed support

[BL-141](https://ortussolutions.atlassian.net/browse/BL-141) `Writedump` `top` support

[BL-193](https://ortussolutions.atlassian.net/browse/BL-193) `listdeleteAt` returns a list with multiple delimiters as a list with whole delimiters

[BL-231](https://ortussolutions.atlassian.net/browse/BL-231) `StructNew` with `localeSensitive` flag throws error

[BL-235](https://ortussolutions.atlassian.net/browse/BL-235) `structKeyTranslate` returns `void`

[BL-241](https://ortussolutions.atlassian.net/browse/BL-241) `StructGet` does not create struct when missing

[BL-245](https://ortussolutions.atlassian.net/browse/BL-245) `StructFindValue` returning null owner

[BL-246](https://ortussolutions.atlassian.net/browse/BL-246) no named applications not auto creating name

[BL-247](https://ortussolutions.atlassian.net/browse/BL-247) application listener requests interception points not registered

[BL-248](https://ortussolutions.atlassian.net/browse/BL-248) ambiguous if statements when not using curly braces

[BL-249](https://ortussolutions.atlassian.net/browse/BL-249) `this.javasettings` not expanding / to correct pathing

[BL-250](https://ortussolutions.atlassian.net/browse/BL-250) `this.javasettings` ignores paths to actual jars and classes

[BL-257](https://ortussolutions.atlassian.net/browse/BL-257) `cfdirectory` fails on centos, converting datetime

[BL-263](https://ortussolutions.atlassian.net/browse/BL-263) `dateAdd`() modifies its argument!

[BL-265](https://ortussolutions.atlassian.net/browse/BL-265) \``toString`\` not formatting doubles correctly

[BL-266](https://ortussolutions.atlassian.net/browse/BL-266) Attempt to cast instead of expecting strings inside \``isValid`\`

[BL-270](https://ortussolutions.atlassian.net/browse/BL-270) Regression on JSON serialization of box classes with JSON exclude annotations

## New Features

### [BL-128](https://ortussolutions.atlassian.net/browse/BL-128) Encryption module

We have created the `bx-password-encrypt` module so you can use it for password encryption. Find out much more here: <https://forgebox.io/view/bx-password-encrypt>

This will collaborate several new BIFs and components:

* `ArgonHash`: Returns a secure input hash of the given string using the Argon2 hashing algorithm. ( Alias: `GenerateArgon2Hash` )
* `ArgonVerify`: Performs a Argon2 verification on the given string against the hashed value. ( Alias: `Argon2CheckHash` )
* `BCryptHash`: Returns a secure input hash of the given string using the BCrypt hashing algorithm.( Alias: `GenerateBCryptHash` )
* `BCryptVerify`: Performs a BCrypt verification on the given string against the hashed value. ( Alias: `BCryptCheckHash` )
* `SCryptHash`: Returns a secure input hash of the given string using the SCrypt hashing algorithm.( Alias: `GenerateSCryptHash` )
* `SCryptVerify`: Performs a SCrypt verification on the given string against the hashed value. ( Alias: `SCryptCheckHash` )
* `GeneratePBKDFKey`: Generates a PDFK key from the given password and salt.

### [BL-251](https://ortussolutions.atlassian.net/browse/BL-251) New event: ON\_REQUEST\_FLUSH\_BUFFER

You can now listen to when the engine flushes the output buffer and intercepts it. This will allow you to collaborate content to the buffer before it's sent to the output destination. The data received is:

* `context` - The execution context
* `output` - The string output to send to the buffer. This can be text or HTML

### [BL-258](https://ortussolutions.atlassian.net/browse/BL-258) Ability to coerce BoxLang functions, lambdas, and UDFs, to well-known functional interfaces for Java interop

This is one of our biggest tickets for this release to continue to close the Java interop cycle in BoxLang. This will allow BoxLang lambdas/closures/udfs to be coerced to Java Functional Interfaces at runtime. This means that ANY Java library that offers functional interfaces (lambdas) can be used natively in BoxLang. This means that using streams, completable futures, and Java lambdas are now native to BoxLang.

```java
fruits = [ "apple", "banana", "cherry", "ananas", "elderberry", "apricot", "avocado", "almond", "acorn", "banana", "cherry", "ananas", "elderberry", "apricot", "avocado", "almond", "acorn" ];
result = fruits
  .parallelStream()
  .filter(  fruit -> fruit.startsWith( "a" ) )
  .toList();
  
  
// Call a Java class that accepts a Runnable lambda with a BoxLang lambda
myJavaclass.runAsync( () -> "Hello from BoxLang" )
// Call a Java class that accepts a Runnable lambda with a BoxLang closure
myJavaclass.runAsync( () => processMyClosureData() )
```

This can also be used to tap into high concurrency constructs in Java. You can combine the usage of BoxLang pure functions (lambdas) or context-aware closures.

```java
import java.util.concurrent.CompletableFuture

// Build out an async BoxLang task using native Java Interop
function main( args = [] ) {
    // Define closures to fetch data from APIs 
    // (can be replaced with actual API calls)
    data1Future = CompletableFuture.supplyAsync( () => simulateApiCall("API 1") )
    data2Future = CompletableFuture.supplyAsync( () => simulateApiCall("API 2") )

    // Combine futures (waits for both to complete)
    // With a BoxLang lambda
    data1Future.thenAcceptBoth( data2Future, (data1, data2) -> {
        println("Data from API 1: " + data1);
        println("Data from API 2: " + data2);
        println("Combined data: " + data1 + " " + data2);
    });

    // Wait for all futures to complete
    CompletableFuture.allOf( data1Future, data2Future ).get();
}

private static simulateApiCall( apiName ) {
    try {
        sleep(1000); // Simulate API call delay
        println("Fetching data from " + apiName);
        return "Data from #apiName#"
    } catch (InterruptedException e) {
        println( e )
    }
}
```

### [BL-260](https://ortussolutions.atlassian.net/browse/BL-260) Add parallel streams from BoxLang arrays

All BoxLang arrays have native stream support, and you get native parallel support as well.

```java
result = fruits
  .parallelStream()
  .filter(  fruit -> fruit.startsWith( "a" ) )
  .toList();
```

### [BL-264](https://ortussolutions.atlassian.net/browse/BL-264) Truthy / Falsey completion for boolean caster

Our truthy/false evaluations for arrays, structs, queries, Java lists, and collections are complete.

### [BL-268](https://ortussolutions.atlassian.net/browse/BL-268) New Fluent Attempt bif and class

This is inspired by Java Optionals for BoxLang. We have introduced a new class called `Attempt()`, which allows you to create fluent and functional code to work with values or delay attempts at code execution. Then, you can interact with the result of your attempt using our functional methods.

Another important aspect of attempts is that they evaluate that the seeded value is not `null` but also truthy. This means you can use it to evaluate that the value is truthy or false, not only null. You can also pass in a closure/lambda to be the value and once you request to evaluate the result, it will do it asynchronously and delayed.

```cfscript
attempt( userService.get( rc.id ).isLoaded() )
    .ifPresent( user -> populate( user ).save() )
    .orThrow( "UserNotFoundException" )
    
// A delayed attempt
userDataAttempt = attempt( () -> userData.getData() )
    .toMatchRegex( "^myRegex" )

....

return userDataAttempt
    .orElse( "" )
    
```

Here are the current functions available to you in this beta. There are more coming to make it more fluent.

{% embed url="<https://s3.amazonaws.com/apidocs.ortussolutions.com/boxlang/1.0.0-beta2/ortus/boxlang/runtime/dynamic/Attempt.html>" %}

* `get():any` - Get the value or throw an exception if null or falsey
* `empty():Attempt` - Produce a new empty attempt
* `of( value ):Attempt` - Produce a new attempt with the passed value
* `ofFunction( context, function/closure/lambda ):Attempt` - Produce a new attempt with a closure or lambda.
* `isEmpty():boolean` - Is the value falsey or null
* `isPresent():boolean` - Is the value present
* `ifPresent( consumer ):Attempt` - Call the consumer lambda/closure if the value is present
* `ifPresentOrElse( consumer, action ):Attempt` - Call the consumer lambda/closure if present or the action lambda/closure if not.
* `ifEmpty( consumer ):Attempt` - Call the consumer if the value is not present
* `or( supplier ):Attempt` - If the value is present it returns itself, if not, it calls the supplier closure/lambda to produce a new attempt.
* `orElse( other ):any`- Get the value if present, or otherwise return the other value passed
* `orElseGet( supplier ):any` - Get the value if present, otherwise call the supplier closure/lambda to produce the value you want to return.
* `map( mapper ): Attempt` - Maps the value of the attempt if it exists, else returns the same attempt with no value.
* `filter( predicate )` - If the value is present it will call your predicate closure/lambda so you can run tests on the value. If the return is true it will return the same attempt, else an empty attempt.
* `orThrow():any` - Returns the value if it exists or throws an exception
* `orThrow( message ):any` - Returns the value if it exists or throws an exception with your custom message
* `orThrow( exception ):any` - Returns the value if it exists or throws your custom exception
* `stream():Stream` - If the value exists returns a stream with the value else an empty stream
* `toString():String` - Gives you a string representation of the value
* `isValid():Boolean` - If the value is present it will try to validate it with the registered validation schemas, if any.
* `toBeValid( closure or lambda ):Attempt` - This allows you to register a lambda/closure to validate the data if any. When calling `isValid()` it will call this function if registered.
* `toBeBetween( min, max ):Attempt` - This allows you to register a min and max numerical values to test the value. It must be in range to be valid.
* `toMatchRegex( regex ):Attempt` - This allows you to register a regular expression to match against the value.

### [BL-269](https://ortussolutions.atlassian.net/browse/BL-269) Add the ability to add member methods to BoxLang classes

This was something we always wanted to do. This allows module and BoxLang developers to contribute member methods to ANY BoxLang class. So now, you can serialize any Class to JSON natively using our BoxLang Class to JSON native serialization. Let's build a `Person` class:

```cfscript
/**
 * My Person 
 */
@jsonExclude "anotherprop, anotherProp2"
class Person{

	property String name;
	property String surname;
	property numeric age;
	property Date createdDate;
	property Date modifiedDate;
	property boolean isActive;
	property Array tags;
	@jsonExclude
	property any javaSystem;
	property anotherProp;
	property anotherProp2;

	function init(){
		variables.name = "John";
		variables.surname = "Doe";
		variables.age = 30;
		variables.createdDate = now();
		variables.modifiedDate = now();
		variables.isActive = true;
		variables.tags = ["tag1", "tag2"];
		variables.test = CreateObject( "java", "java.lang.System" );
		variables.anotherProp = "hello";
		variables.anotherProp2 = "hello";

		return this;
	}

	function sayHello(){
		return "Hello " & variables.name;
	}

}

```

As you can see, we have introduced a few annotations for JSON serialization based on our experience with the ColdBox mementifier project. You can tag properties to be excluded from serialization using the `jsonExclude` annotation. You can exclude a list of properties from the class annotation as well. Now, let's get some JSON data out using the `toJSON()` member function, which delegates it to the `jsonSerialize()` bif.

```cfscript
function main( args={} ){
    return new Person()
        .setName( "Luis" )
        .setSurname( "Majano" )
        .toJSON()
}
```

This will allow framework developers to collaborate with first-class methods in any BoxLang class.

### [BL-271](https://ortussolutions.atlassian.net/browse/BL-271) new static helper on Array class: \`fromString( list, delimiter )\` to create quick BoxLang arrays from strings

This is an internal convenience method for creating BoxLang arrays from strings.

### [BL-272](https://ortussolutions.atlassian.net/browse/BL-272) new BIFS for registered interceptors into the request pool and the global pool: BoxRegisterREquestInterceptor, BoxRegisterInterceptor

BoxLang is an event-driven language. It announces tons of events during the software life cycle. You can now listen to any global event via the new `BoxRegisterInterceptor()` bif. This will allow you to register classes, lambdas, or closures.

```cfscript
boxRegisterInterceptor( ()=> listenToRequestStarts(), "onServerScopeCreation" )
```

However, BoxLang also offers interceptors at the request level via the internal application listener. This means that you can listen to a specific request life-cycle by using the `boxRegisterRequestInterceptor()` bif.

```cfscript
boxRegisterRequestInterceptor( ()=> listenToRequestStarts(), "onRequestStart" )
```

### [BL-274](https://ortussolutions.atlassian.net/browse/BL-274) writedump abort support

More work towards compatibility is completed.

### [BL-275](https://ortussolutions.atlassian.net/browse/BL-275) writeoutput on complex BoxLang types should call the \`toString()\` on it

This has been a heached in current CFML engines. We now detect what you send in to the `writeOutput() or echo()` commands and we will convert them to string if they are complex objects or classes.

```cfscript
fruits = [ "apple", "banana", "cherry", "ananas", "elderberry", "apricot", "avocado", "almond", "acorn", "banana", "cherry", "ananas", "elderberry", "apricot", "avocado", "almond", "acorn" ];BL-277 implements BIFs GenerateSecretKey, Encrypt, Decrypt

writeoutput( fruits )
writeOutput( server )
```

### Native Encrypt, Decrypt and GenerateSecretKey()

We now support all encryption and decryption algorithms natively in BoxLang without ANY third-party library. Secure by default and with 3 BIFS created for this. Supported algorithms:

* `AES`
* `ARCFOUR`
* `Blowfish`
* `ChaCha20`
* `DES`
* `DESede`
* `HmacMD5`
* `HmacSHA1`
* `HmacSHA224`
* `HmacSHA256`
* `HmacSHA384`
* `HmacSHA512`
* `HmacSHA3-224`
* `HmacSHA3-256`
* `HmacSHA3-384`
* `HmacSHA3-512`


---

# 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-beta2.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.
