Releases: atlanhq/atlan-java
v1.3.1
βοΈ Deprecations
- Deprecates the
LineageRequest
-based lineage operations.- The methods are still there, only marked deprecated, to avoid any existing code compilation breakages.
- However, be advised that any code that still relies on these deprecated methods may no longer work in the near future (or indeed already).
- Instead, use the
LineageListRequest
-based lineage operations, which offer equivalent functionality with improved performance.
π Bug fixes
- Adds an API token check as part of cache refreshes. Previously an expired or otherwise no-longer-valid API token would silently create empty caches, causing knock-on effects related to things like Atlan tags and custom metadata not being found. Now such tokens will be immediately identified and raised during the cache refresh process rather than silently failing.
- Fixes deserialization of string-encoded primitives in JSON response payloads.
π₯ QOL improvements
- Enumerates the out-of-the-box Atlan packages, for use in searching for workflows to rerun using
WorkflowSearchRequest.findByType()
v1.3.0
π New features
- Adds models for new asset types:
- Matillion
- (Experimental) MongoDB
- Adds query shortcuts for searchable relationships
- (Experimental) Enhancements to provide the foundation for using the Java SDK for workflows (custom packages):
- Adds user impersonation capability
- Adds ability to include custom headers (at
AtlanClient
-level and asRequestOptions
)
π₯ QOL improvements
- Improves error message passthrough
- Adds handling for
www-form-urlencoded
requests - Adds further options for defining custom metadata attributes
v1.2.2
βοΈ Deprecations
- Deprecates the ability to activate or deactivate users programmatically. This can no longer be achieved using an API token, so will be removed from the SDKs.
- The methods are still there, only marked deprecated, to avoid any existing code compilation breakages.
- However, be advised that any code that still relies on these deprecated methods will always receive an error at runtime now due to back-end changes.
π Bug fixes
- Uses explicit column projections for user listing API to reduce latency
- Fixes deserialization of empty values (now treats
null
and""
as equivalent)
π₯ QOL improvements
- Adds option to further configure bucket aggregation, specifically to return the actual value of the field used for bucketing and control how many buckets to create
- Extends the options that can be used for filtering entities in lineage beyond only
CONTAINS
v1.2.1
v1.2.0
π New features
- Allows API tokens to be assigned as connection admins, query collection editors and viewers
π Bug fixes
- Parameterizes and defaults page size to 20 for users, groups and API tokens
- Fixes bug where a number of the
updater()
helper methods did not include placeholder GUIDs
π₯ QOL improvements
- Adds more reusable approach to serde
v1.1.0
π New features
Fluent search
FluentSearch
further simplifies searches. You can access the simplified searching using a new select()
method in the same way you can use the all()
method in v1.0.0. However, fluent search further simplifies and validates searches:
- All attributes and search index fields are now defined as constants, so you no longer need to remember or deal with string values directly.
- The predicates you can use to search a particular field are now accessible directly on these constants β and are restricted to those that apply to that kind of field. No more mistakenly using a
gt
to search on a boolean field, for example, or astartsWith
on a numeric field. (These validations are also applied to custom metadata attributes, but only at runtime due to the runtime nature of custom metadata.) - You can now also directly get a count of results to a query using
count()
at the end of a fluent search chain, or directly translate the criteria defined in the chain into a search request usingtoRequest()
. (All existingAssetFilter
mechanisms also still apply to fluent searches: streaming, parallel streaming, etc.) - You no longer need to use or statically import the
QueryFactory
class β this has been replaced by a newCompoundQuery
class that has static query helpers defined within it. - Aggregations are available within fluent searches.
- The field constants also contain methods for sorting results by those fields, and for creating aggregations based on those fields.
For example, with an AssetFilter
you would previously have written:
Column.all()
.filter(QueryFactory.where(KeywordFields.QUALIFIED_NAME).startsWith("default/snowflake"))
.batch(100)
.attribute("description")
.sort(QueryFactory.Sort.by(KeywordFields.NAME, SortOrder.Asc))
.stream()
.forEach(c -> {
log.info("Column: {}", c);
});
With the new FluentSearch
you can now write the same as:
Column.select()
.where(Column.QUALIFIED_NAME.startsWith("default/snowflake"))
.pageSize(100)
.includeOnResults(Column.DESCRIPTION)
.sort(Column.NAME.order(SortOrder.Asc))
.stream()
.forEach(c -> {
log.info("Column: {}", c);
});
π Bug fixes
- Changes internal
AssetBatch
structures to be thread-safe - Fixes criteria for listing users to avoid an infinite loop
πͺ« Deprecations
- The existing
AssetFilter
search simplification, itsall()
method, and theQueryFactory
class all still exist, but they have all been marked as deprecated (and will be removed in the next major release).
v1.0.0
π Our official initial release of the Java SDK!
From here on out, we'll be using https://semver.org for releases, so you can expect more stability in your own dependency management going forward.
π New features
- Adds models:
- Airflow
- Soda
- Adds helpers to
AssetMutationResponse
to more easily retrieve information: subsets of assets by type, the mutation operation that occurred given a specific asset, and directly retrieving the result of a specific asset. - Adds placeholder GUIDs to all
creator()
methods, so it is now actually possible to use a single bulk assetsave()
that contains related assets (including parents and children). - Adds a parallel streaming option for iterating through indexsearch results that can greatly speed up algorithms that need to iterate through a large number of (large) results.
- Adds new ability to attach and detach terms to assets as part of purpose policies.
βοΈ Breaking changes
GlossaryCategory.findByName()
now returns multiple categories, since a category name is not unique.- This release removes the ability to delete users. This functionality was problematic in that it did not fully remove a user and could result in knock-on impacts such as failing future workflow runs and leaving dangling references. We will reinstate a similar method once available.
π Bug fixes
- Fixes an issue where a
CategoryHierarchy
class that contained only top-level categories may not have been fully initialized. - Fixes default sorting of index search results, when no other sorting has been applied.
- Fixes issues where the default client would always be used, even if an alternative client is provided.
π₯ QOL improvements
- Lowers the default retry limit to
3
and only adds extra retries for blocking async mutation operations. Note that this means if you are not using theblock()
call on these async operations already, it will be your responsibility to add any extra retries or confirmation logic that the operations (and their async policies) are completed. - Adds operations that will explicitly update, and not create, assets.
- Adds helper to the
CategoryHierarchy
class to retrieve any arbitrary category from the structure.
v0.9.0
π New features
- Asset filters to pipeline bulk query and update operations directly and efficiently
- Search for terms by their categories and categories by their parent category
- Search and retrieve logged administrative events, such as user logins
- Models for:
- Azure Event Hub
- Functions
- StarredBy details
- DbtTag
- Adds a unique
X-Atlan-Request-Id
header to every call that can be used for tracing requests all the way through Atlan's back-end operations
βοΈ Breaking changes
- Replaces the
retrieveFull()
,retrieveMinimal()
,retrieveByGuid()
andretrieveByQualifiedName()
methods with a single overloadedget()
method:- From any asset you can now retrieve an instance using
get()
, for example:Table.get()
. The SDK will automatically detect whether you are retrieving the asset by GUID or qualifiedName and act accordingly. To retrieve the minimal version (without relationships) simply pass an optional argument offalse
to not include the relationships. - For dynamic typing, you can use
Asset.get()
in place ofAsset.retrieveFull()
andAsset.retrieveMinimal()
.
- From any asset you can now retrieve an instance using
- The
builder()
method of assets was only ever intended for internal use. As such, it has now been renamed_internal()
to make this more apparent. Unless explicitly mentioned in developer.atlan.com, you should always usecreator()
,updater()
, ortrimToRequired()
rather than directly accessing_internal()
to construct an asset. - The SDK now supports running against multiple tenants in a single JVM. To enable this, we've:
- Added a mandatory
AtlanClient
parameter when creating anAssetBatch
. (You can passAtlan.getDefaultClient()
to retain the existing behavior.) - Removed the ability to directly access the
Serde.mapper
ObjectMapper β instead now use the.readValue()
and.writeValueAsString()
operations on anAtlanClient
. (For example:Atlan.getDefaultClient().readValue()
.) - Related to above,
toJson()
on any asset now requires a client β if you were using this directly, you can now call.toJson(Atlan.getDefaultClient())
to retain the existing behavior. - Removed the ability to directly access the various
...Endpoint
classes. These are now only available through anAtlanClient
, for example:Atlan.getDefaultClient().assets.save(List.of(asset1, asset2), false)
rather thanBulkEntityEndpoint.upsert(List.of(asset1, asset2), false)
. - Removed static caches β caches are now client-specific:
- Anywhere you previously did something like
RoleCache.getIdForName()
you will now need to useAtlan.getDefaultClient().getRoleCache().getIdForName()
. - Note that this pattern applies to all caches (
RoleCache
,CustomMetadataCache
,AtlanTagCache
,EnumCache
,UserCache
andGroupCache
).
- Anywhere you previously did something like
- Added a mandatory
- The static
getBaseUrlSafe()
method has been removed, as thegetBaseUrl()
method no longer throws a checked exception and can therefore be used directly instead. - The
upsert()
operation has been deprecated, replaced by asave()
operation that takes the same arguments and behaves in the same way.
(Note: we're reserving the right to make breaking changes to the SDK prior to a 1.0.0 release, without incrementing the major version. Once we hit 1.0.0, we'll adhere to https://semver.org)
π Bug fixes
- Fixes an
IndexOutOfBoundsException
that could occur when trying to retrieve a non-existent API token by its name. - Fixes an issue with the default page size used for asset filters, so they should now work even if no page size is explicitly set.
- Marks all API-operable objects as serializable.
- Replaces the
toString()
method that produced JSON output with an object-nativetoString()
. While this may feel less readable, it removes any dependency on tenant-specific information for the serialization process, and should avoid hiding any transformation or translations that would occur through such a serialization. - Adds a missing
PURGED
status that can exist in some circumstances on deleted instances of metadata. - No longer fails if custom metadata that no longer exists is encountered, but instead uses a value of
(DELETED)
and logs. - Fixes blocking check on asset deletion.
π₯ QOL improvements
- Asset instance retrieval has been simplified to a single
get()
method that works for both GUIDs and qualifiedNames. - The
findByName()
method that exists for various assets (connections, glossary objects, etc) no longer requires an attributes argument (if none is provided it will default to the minimal set of attributes now). - With asset filters you can now quickly query assets of a given type, without needing to build or run a separate
IndexSearchRequest
. For example:Table.all().filter(...).stream().forEach(a -> log.info("Found asset: {}", a));
- All operations that you can invoke against an endpoint now have variants that can take an (optional)
RequestOptions
object. When provided, these allow you to override default client settings for that individual request β timeouts, max retries, etc. - Bumps all library dependencies to their latest stable versions.
v0.8.0
π New features
- Adds the ability to manage arbitrary files as assets
- Adds an abstraction layer for easing implementation of real-time event-processing through webhooks, in particular when implemented using AWS Lambda functions
- Index searches have been simplified through their
builder()
method, defaults for paging, and providing other shortcut factory methods (likeof()
for the DSL) - Lineage listings have been simplified through their
builder()
method and defaults for parameters - Index search and lineage listing responses now provide
Iterable<Asset>
and.stream()
interfaces to simplify iterating through results. These make looping much simpler while simultaneously more efficient β In both cases the next pages of results are automatically fetched as-needed, lazily, so you can always break-out early without retrieving unnecessary results.
βοΈ Breaking changes
- Search builders now have a required argument (the DSL or query to search), rather than starting blank.
- Lineage list builders now have a required argument (the GUID of the asset to start from), rather than starting blank.
- AssetBatch operations now throw any checked exceptions rather than swallowing and logging them.
- Implements multi-inheritance polymorphism for assets.
- This means a given asset type can now inherit its full set of attributes and relationships (across multiple supertypes).
- However, it means we have removed the abstract classes that represented supertypes of assets and replaced these with interfaces. For example, there is no longer a
SQL
or aCatalog
class, but anISQL
and anICatalog
interface. - Anywhere you previously were checking an asset using
if (a instanceof Catalog)
with such an abstract class, you'll now need to do the same check against the interface instead (e.g.if (a instanceof ICatalog)
). - The benefit of this change is that the asset types in the SDK now accurately reflect multi-inheritance of Atlan itself. So a
SnowflakeTag
for example will be bothinstanceof ITag
andinstanceof ISQL
. (With class-based inheritance, we had to choose just one of these to extend.) - Relationships are all now specified using their interface rather than their class, so for example
getAssignedTerms()
will now returnIGlossaryTerm
s rather thanGlossaryTerm
s. As long as you are accessing instance methods for your operations, this should be a transparent change for you in almost all cases, as the interface has all the same (non-static) methods defined on it that exist on the class.
(Note: we're reserving the right to make breaking changes to the SDK prior to a 1.0.0 release, without incrementing the major version. Once we hit 1.0.0, we'll adhere to https://semver.org)
π Bug fixes
- Fixes an issue introduced in the last release where the
assignedTerms
relationship was missing from generated test classes. - Fixes an issue that required an
attributes.csv
file to be present for injecting descriptions into generated POJOs β this is now optional as part of the code generation. - Fixes an issue for
TableauDatasource
objects, which can now return both calculated fields and datasource fields through the singlefields
relationship. - Fixes the level of caching attempted for roles β previously every role was cached, whereas now only the workspace-roles will be cached.
π₯ QOL improvements
- The
Iterable<Asset>
interface provided by index search and lineage listing responses allow you to:- Use a simple for-each loop:
for (Asset a : response) { ... }
- Use a
forEach()
lambda:response.forEach(a -> { ... });
- Use a simple for-each loop:
- The
.stream()
interface provides the results as a stream, allowing you to:- Use chain-able stream operations, such as:
response.stream().filter(...).limit(n).forEach(a -> {...}).collect()
- Use chain-able stream operations, such as:
- When the retry limit is reached for automated retries, any underlying exceptions or response body should now be logged in addition to the fact that the retry limit was reached.
- Every snapshot build and release now uploads a
lambda-layer.zip
file that can be uploaded directly as an AWS Lambda layer, providing the full Java SDK (and its dependencies). You can then implement any of your own logic through the abstraction layer and simply upload that minimal code directly, without needing to re-package the entire SDK and its dependencies. (This allows you to upload and manage the SDK layer independently of possibly many event handlers implemented on top of it.)
v0.7.0
π New features
- Adds higher-performance lineage list API
- Adds ability to manage an icon or image for tags (classifications)
- Adds new type definitions for:
- MicroStrategy objects
- Renames "classification" to "tag" to align with UI changes
- Adds new persona/purpose/policy management
βοΈ Breaking changes
- Renames "classifications" to "tags". Back-end payloads remain unchanged, but any properties or methods that referred to
classification
will now refer toatlanTag
. For example:mappedClassificationName
->mappedAtlanTagName
purposeClassifications
->purposeAtlanTags
ClassificationCache
->AtlanTagCache
Classification
->AtlanTag
ClassificationDef
->AtlanTagDef
classifications
->atlanTags
classificationNames
->atlanTagNames
appendClassifications
->appendAtlanTags
addClassifications
->addAtlanTags
- Updates persona, purpose and policy management to use new optimized internal changes. As a result, the specific objects and methods needed to manage personas, purposes and policies have changed:
Persona
andPurpose
have moved intocom.atlan.model.assets
- These now directly provide
createMetadataPolicy
andcreateDataPolicy
(andcreateGlossaryPolicy
inPersona
) helpers to manage the policies AuthPolicy
is the new base object for all policies (the helpers above now createAuthPolicy
objects)- Policy management is now more consistent across the two mechanisms, and policies can now be created in bulk for both as well
(Note: we're reserving the right to make breaking changes to the SDK prior to a 1.0.0 release, without incrementing the major version. Once we hit 1.0.0, we'll adhere to https://semver.org)
π₯ QOL improvements
- Refactors the code generators used to build the SDK, so that they can be reused to create "extended" SDKs. All generated code is now also annotated (
javax.annotation.Generated
) for easier identification and simplifying common tasks like excluding generated code from coverage tests.
(Note: this is really just a re-issue of the v0.7.0 release that fixes a JavaDoc error that caused publishing to Maven Central to fail.)