Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created July 31, 2019 11:50
Using The Safe-Navigation Operator To Safely Clean Up Resources In Lucee 5.3.2.77
<cfscript>
message = (
"In the year of our Lord 1314, patriots of Scotland, starving and outnumbered, " &
"charged the fields of Bannockburn. They fought like warrior poets. They fought " &
"like Scotsmen and they won their freedom."
);
try {
outputStream = createObject( "java", "java.io.ByteArrayOutputStream" ).init();
gzipOutputStream = createObject( "java","java.util.zip.GZIPOutputStream" ).init( outputStream );
// Write the message to the GZIP output stream.
messageBytes = charsetDecode( message, "utf-8" );
gzipOutputStream.write( messageBytes, 0, arrayLen( messageBytes ) );
gzipOutputStream.finish();
// Persist the GZIP binary data to a flat file.
fileWrite( "./quote.txt.gzip", outputStream.toByteArray() );
} finally {
// Close all streams once we are done.
// --
// NOTE: In this case, it is extremely unlikely that these objects wouldn't
// exist. However, this is a usage-pattern that I am starting to embrace - using
// the SAFE NAVIGATION OPERATOR to safely close objects that were created within
// the bounds of a try-block.
gzipOutputStream?.close();
outputStream?.close();
}
// FUN SIDE NOTE: You can easily extract this GZIP data using the extract() function:
// --
// extract( "gzip", "./quote.txt.gzip", "./quote.txt" );
</cfscript>
<cfscript>
// ....
try {
jedis = jedisPool.getResource();
jedis.set( "hello", "world" );
} finally {
// Once we are done interacting with Redis, we have to close the Jedis resource
// or it won't be returned to the connection pool. Jedis will be NULL if a
// resource could not be obtained from the connection pool.
// --
// NOTE: We are using the safe-navigation operator to safely close the resource
// even if it wasn't obtained.
jedis?.close();
}
</cfscript>
<cfscript>
try {
distributedLock = getLock( "myLock" );
// ... do some complicated stuff within this globally-synchronized block.
echo( "Done." );
} catch ( "DistributedLock.LockError" error ) {
echo( "Someone else is already doing this thing!" );
} finally {
// Release the distributed lock once we are done with the synchronized work.
// --
// NOTE: We are using the safe-navigation operator so that we can safely call
// this line of code even if we failed to obtain the distributed lock.
distributedLock?.release();
}
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
/**
* I obtain a mock distributed-lock.
*
* @name I am the name of the lock being obtained.
*/
public any function getLock( required string name ) {
if ( randRange( 0, 1 ) ) {
throw( type = "DistributedLock.LockError" );
}
return({
release: () => {
// ... this is just a mock lock.
}
});
}
</cfscript>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment