Skip to content

v4.0.0

Compare
Choose a tag to compare
@cmgrote cmgrote released this 04 Dec 11:33

⛑️ Breaking changes

  • Removes a number of static objects, in particular the "default" Atlan client that was accessible through Atlan.getDefaultClient() by @cmgrote in #1072. Every operation that interacts with Atlan (ultimately sending it an API request) must now be explicitly passed an AtlanClient. This change was made for two primary reasons:
    1. It makes explicit which operations will interact with Atlan (those that require an AtlanClient to be passed) vs those that only operate on information locally in-memory (those that do not require an AtlanClient to be passed).
    2. It removes concurrency limitations and risks with shared static resources across the entire JVM (including all threads therein). This applies not only to the default client but also to some of the caches that were being automatically managed.
  • Packages developed using this release of the package toolkit will now need to make use of a broader PackageContext object that similarly encapsulates the client and any extra caches specific to packages.

🧪 Experimental

  • Adds limited ability to configure an SSO provider by @cmgrote in #1069

🐞 Bug fixes

📦 Packages

  • Adds multi-pass handling of cyclical relationships to asset import package by @cmgrote in #1061
  • Fixes Python outputs generated by package toolkit by @ErnestoLoma in #1068
  • Adds the ability in the package toolkit to set default values into the configuration objects by defining a fallback for any inputs in the package.pkl by @cmgrote in #1072

🥗 QOL improvements

  • Migrates bulk streaming of search to use search_after by @cmgrote in #1060

Full Changelog: v3.1.2...v4.0.0

AtlanClient changes

As mentioned in the breaking changes, this release introduces a complete revamp of the way the AtlanClient is managed and passed around to operations that actually call Atlan APIs behind-the-scenes.

Resource-isolated

Previously the client itself and some caches were managed statically across the entire JVM. This could cause non-obvious and very difficult reproduce issues when heavy concurrency exists. With this release, all caches are managed within the AtlanClient directly, and there is no longer a JVM-wide static client. Instead, you can create a new client and have it "live" only for as long as you need it:

try (AtlanClient client = new AtlanClient()) {
    // Do anything you need against Atlan within this block
}
// Once you exit the block, the client and all its internal caches will be removed

Must be explicitly passed

Furthermore, any operation that actually interacts with Atlan directly (ultimately via its APIs behind-the-scenes) must now be explicitly passed such a client:

GlossaryTerm term = GlossaryTerm.findByName(client, "A", "B");
term.trimToRequired().userDescription("Hi there!").build().save(client);

This means there is an extensive set of changes to many of the methods across the SDK — if you're planning to adopt this release (and higher), rather than reading a huge list of such operations it'll probably be simplest to update your dependency to this latest release in your codebase and then look for any compilation breakages. The explicit AtlanClient is almost always expected as the new first parameter in any methods that now require it.

Package toolkit

Introduction of PackageContext

In the same way we have resource-isolated the client and its caches for the SDK, we have resource-isolated the context of a running package and its further caches in this release. The full context needed for running a package is now bundled into an object called a PackageContext, which can be created from a package's configuration using Utils.initializeContext() and passing it te configuration. Where you previously may have just used this pattern:

@JvmStatic
fun main(args: Array<String>) {
    val config = Utils.setPackageOps<OpenAPISpecLoaderCfg>()
    // Receive inputs from the config to decide what to do in your logic
}

You should now use this pattern:

@JvmStatic
fun main(args: Array<String>) {
    Utils.initializeContext<OpenAPISpecLoaderCfg>().use { ctx ->
        // Receive inputs from the config to decide what to do in your logic
        val url = ctx.config.specUrl // config items will be available nested under ctx.config
        val client = ctx.client // the AtlanClient will be nested under ctx.client
        val termCache = ctx.termCache // a number of lazy-load-managed caches are also available in the context
    }
}