Releases: launchdarkly/java-server-sdk
4.14.2
[4.14.2] - 2020-09-01
Fixed:
- Updated the version of OkHttp contained within the SDK from 3.12.10 to 3.14.9, to address multiple known issues including an incompatibility with OpenJDK 8.0.252 under some conditions. (#204)
5.0.3
4.14.1
[4.14.1] - 2020-08-04
Fixed:
- Deserializing
LDUser
from JSON using Gson resulted in an object that had nulls in some fields where nulls were not expected, which could cause null pointer exceptions later. While there was no defined behavior for deserializing users in the 4.x SDK (it is supported in 5.0 and above), it was simple to fix. Results of deserializing with any other JSON framework are undefined. (#199)
5.0.2
[5.0.2] - 2020-06-25
Changed:
- It is no longer necessary to set
StreamingDataSourceBuilder.pollingBaseURI
if you are also settingbaseURI
. This is due to a change in how the LaunchDarkly streaming service works. The setter method still exists, but no longer has any effect and will be deprecated in a future release.
Fixed:
- In polling mode, if a poll request failed due to a temporary network problem but then a subsequent request succeeded,
DataSourceStatusProvider
was continuing to report the status asINTERRUPTED
when it should have been restored toVALID
. - In polling mode, the SDK was unnecessarily re-storing the flag data in the data store even if it had not changed since the last poll request. This would cause unnecessary updates when using a database.
- In polling mode, temporary files used for HTTP caching (in the system temporary directory) were not being cleaned up when the client was closed.
- Fixed incorrect sample code in the documentation comment for
FlagValueChangeListener
.
5.0.1
[5.0.1] - 2020-06-19
Fixed:
- Fixed a bug that could cause worker threads for the EventSource stream to persist after closing the client, if the client had shut down the stream due to detecting an invalid SDK key.
5.0.0
[5.0.0] - 2020-06-02
This is a major rewrite that introduces a cleaner API design, adds new features, and makes the SDK code easier to maintain and extend. See the Java 4.x to 5.0 migration guide for an in-depth look at the changes in this version; the following is a summary.
(For early adopters who have used the the 5.0.0-rc2 beta release: some things have changed between 5.0.0-rc2 and this full release. The 5.0.0-rc2 release notes have been updated with a section describing these changes.)
Added:
- You can tell the SDK to notify you whenever a feature flag's configuration has changed (either in general, or in terms of its result for a specific user), using
LDClient.getFlagTracker()
. (#83) - You can monitor the status of the SDK's data source (which normally means the streaming connection to the LaunchDarkly service) with
LDClient.getDataSourceStatusProvider()
. This allows you to check the current connection status, and to be notified if this status changes. (#184) - You can monitor the status of a persistent data store with
LDClient.getDataStoreStatusProvider()
. This allows you to check whether database updates are succeeding, to be notified if this status changes, and to get caching statistics. - The
FileData
tool now supports reading flag data from a classpath resource as if it were a data file. SeeFileDataSourceBuilder.classpathResources()
. (#193) LDConfig.Builder.logging()
is a new configuration category for options related to logging. Currently the only such option isescalateDataSourceOutageLoggingAfter
, which controls the new connection failure logging behavior described below.LDConfig.Builder.threadPriority()
allows you to set the priority for worker threads created by the SDK.- The
UserAttribute
class provides a less error-prone way to refer to user attribute names in configuration, and can also be used to get an arbitrary attribute from a user. - The
LDGson
andLDJackson
classes allow SDK classes likeLDUser
to be easily converted to or from JSON using the popular Gson and Jackson frameworks.
Changed (requirements/dependencies/build):
- The minimum supported Java version is now 8.
- The SDK no longer exposes a Gson dependency or any Gson types.
- Third-party libraries like Gson, Guava, and OkHttp that are used internally by the SDK have been updated to newer versions since Java 7 compatibility is no longer required. (#158)
- Code coverage reports and JMH benchmarks are now generated in every build. Unit test coverage of the entire SDK codebase has been greatly improved.
Changed (API changes):
- Package names have changed: the main SDK classes are now in
com.launchdarkly.sdk
andcom.launchdarkly.sdk.server
. - Many rarely-used classes and interfaces have been moved out of the main SDK package into
com.launchdarkly.sdk.server.integrations
andcom.launchdarkly.sdk.server.interfaces
. - The type
java.time.Duration
is now used for configuration properties that represent an amount of time, instead of using a number of milliseconds or seconds. LDClient.initialized()
has been renamed toisInitialized()
.LDClient.intVariation()
anddoubleVariation()
now returnint
anddouble
, not the nullableInteger
andDouble
.EvaluationDetail.getVariationIndex()
now returnsint
instead ofInteger
.EvaluationReason
is now a single concrete class rather than an abstract base class.- The component interfaces
FeatureStore
andUpdateProcessor
have been renamed toDataStore
andDataSource
. The factory interfaces for these components now receive SDK configuration options in a different way that does not expose other components' configurations to each other. - The
PersistentDataStore
interface for creating your own database integrations has been simplified by moving all of the serialization and caching logic into the main SDK code.
Changed (behavioral changes):
- SLF4J logging now uses a simpler, more stable set of logger names instead of using the names of specific implementation classes that are subject to change. General messages are logged under
com.launchdarkly.sdk.server.LDClient
, while messages about specific areas of functionality are logged under that name plus.DataSource
(streaming, polling, file data, etc.),.DataStore
(database integrations),.Evaluation
(unexpected errors during flag evaluations), or.Events
(analytics event processing). - If analytics events are disabled with
Components.noEvents()
, the SDK now avoids generating any analytics event objects internally. Previously they were created and then discarded, causing unnecessary heap churn. - Network failures and server errors for streaming or polling requests were previously logged at
ERROR
level in most cases but sometimes atWARN
level. They are now all atWARN
level, but with a new behavior: if connection failures continue without a successful retry for a certain amount of time, the SDK will log a specialERROR
-level message to warn you that this is not just a brief outage. The amount of time is one minute by default, but can be changed with the newlogDataSourceOutageAsErrorAfter
option inLoggingConfigurationBuilder
. (#190) - Many internal methods have been rewritten to reduce the number of heap allocations in general.
- Evaluation of rules involving regex matches, date/time values, and semantic versions, has been speeded up by pre-parsing the values in the rules.
- Evaluation of rules involving an equality match to multiple values (such as "name is one of X, Y, Z") has been speeded up by converting the list of values to a
Set
. - The number of worker threads maintained by the SDK has been reduced so that most intermittent background tasks, such as listener notifications, event flush timers, and polling requests, are now dispatched on a single thread. The delivery of analytics events to LaunchDarkly still has its own thread pool because it is a heavier-weight task with greater need for concurrency.
- In polling mode, the poll requests previously ran on a dedicated worker thread that inherited its priority from the application thread that created the SDK. They are now on the SDK's main worker thread, which has
Thread.MIN_PRIORITY
by default (as all the other SDK threads already did) but the priority can be changed as described above. - When using a persistent data store such as Redis, if there is a database outage, the SDK will wait until the end of the outage and then restart the stream connection to ensure that it has the latest data. Previously, it would try to restart the connection immediately and continue restarting if the database was still not available, causing unnecessary overhead.
Fixed:
LDClient.version()
previously could not be used if the SDK classes were not packaged in their original jar. It now works correctly regardless of deployment details.
Removed:
- All types and methods that were deprecated as of Java SDK 4.13.0 have been removed. This includes many
LDConfig.Builder()
methods, which have been replaced by the modular configuration syntax that was already added in the 4.12.0 and 4.13.0 releases. See the migration guide for details on how to update your configuration code if you were using the older syntax. - The Redis integration is no longer built into the main SDK library. See: https://github.com/launchdarkly/java-server-sdk-redis
- The deprecated New Relic integration has been removed.
5.0.0-rc2
[5.0.0-rc2] - 2020-05-13
The primary purpose of this second beta release is to introduce the new DataSourceStatusProvider
API, which is the server-side equivalent to the "connection status" API that exists in LaunchDarkly's mobile SDKs. Other additions and changes since the previous beta release (5.0.0-rc1) are described below. See the 5.0.0-rc1 release notes for other changes since 4.13.0. Also, see the end of this release note for changes between 5.0.0-rc2 and the final 5.0.0.
Added:
LDClient.getDataSourceStatusProvider()
is a status monitoring mechanism similar togetDataStoreStatusProvider()
, but for the data source (streaming, polling, or file data). You can not only check the current connection status, but also choose to receive notifications when the status changes.LDConfig.Builder.logging()
is a new configuration category for options related to logging. Currently the only such option isescalateDataSourceOutageLoggingAfter
, which controls the new connection failure logging behavior described below.LDConfig.Builder.threadPriority()
allows you to set the priority for worker threads created by the SDK.
Changed:
- Network failures and server errors for streaming or polling requests were previously logged at
ERROR
level in most cases but sometimes atWARN
level. They are now all atWARN
level, but with a new behavior: if connection failures continue without a successful retry for a certain amount of time, the SDK will log a specialERROR
-level message to warn you that this is not just a brief outage. The amount of time is one minute by default, but can be changed with the newlogDataSourceOutageAsErrorAfter
option inLoggingConfigurationBuilder
. - The number of worker threads maintained by the SDK has been reduced so that most intermittent background tasks, such as listener notifications, event flush timers, and polling requests, are now dispatched on a single thread. The delivery of analytics events to LaunchDarkly still has its own thread pool because it is a heavier-weight task with greater need for concurrency.
- In polling mode, the poll requests previously ran on a dedicated worker thread that inherited its priority from the application thread that created the SDK. They are now on the SDK's main worker thread, which has
Thread.MIN_PRIORITY
by default (as all the other SDK threads already did) but the priority can be changed as described above. - Only relevant for implementing custom components: The
DataStore
andDataSource
interfaces, and their factories, have been changed to provide a more general mechanism for status reporting. This does not affect the part of a persistent data store implementation that is database-specific, so new beta releases of the Consul/DynamoDB/Redis libraries were not necessary.
Changes made after this beta release, in the final 5.0.0 release:
This section is an update in preparation for the full 5.0.0 release, for anyone who has beta-tested 5.0.0-rc2. The following things changed after 5.0.0-rc2:
- The flag listener methods were moved out of
LDClient
, into theFlagTracker
object that is available throughclient.getFlagTracker()
. DataSourceStatusProvider
now has awaitFor
method allowing the caller to block until the connection is established.LDClientInterface
has been moved into theinterfaces
subpackage.- The
initialized()
method inLDClient
andLDClientInterface
was renamed toisInitialized()
. LDClient.intVariation()
anddoubleVariation()
now returnint
anddouble
, not the nullableInteger
andDouble
.LDClient.version()
previously could not be used if the SDK classes were not packaged in their original jar. It now works correctly regardless of deployment details.- SLF4J logging now uses a simpler, more stable set of logger names instead of using the names of specific implementation classes that are subject to change. General messages are logged under
com.launchdarkly.sdk.server.LDClient
, while messages about specific areas of functionality are logged under that name plus.DataSource
(streaming, polling, file data, etc.),.DataStore
(database integrations),.Evaluation
(unexpected errors during flag evaluations), or.Events
(analytics event processing). - The
FileData
tool now supports reading flag data from a classpath resource as if it were a data file. SeeFileDataSourceBuilder.classpathResources()
. - Code coverage reports and JMH benchmarks are now generated in every build. Unit test coverage of the entire SDK codebase has been greatly improved.
4.14.0
[4.14.0] - 2020-05-13
Added:
EventSender
interface andEventsConfigurationBuilder.eventSender()
allow you to specify a custom implementation of how event data is sent. This is mainly to facilitate testing, but could also be used to store and forward event data.
Fixed:
- Changed the Javadoc comments for the
LDClient
constructors to provide a better explanation of the client's initialization behavior.
5.0.0-rc1
[5.0.0-rc1] - 2020-04-29
This beta release is being made available for testing and user feedback, due to the large number of changes from Java SDK 4.x. Features are still subject to change in the final 5.0.0 release. Until the final release, the beta source code will be on the 5.x branch. Javadocs can be found on javadoc.io.
This is a major rewrite that introduces a cleaner API design, adds new features, and makes the SDK code easier to maintain and extend. See the Java 4.x to 5.0 migration guide for an in-depth look at the changes in this version; the following is a summary.
Added:
- You can tell the SDK to notify you whenever a feature flag's configuration has changed in any way, using
FlagChangeListener
andLDClient.registerFlagChangeListener()
. - Or, you can tell the SDK to notify you only if the value of a flag for some particular
LDUser
has changed, usingFlagValueChangeListener
andComponents.flagValueMonitoringListener()
. - You can monitor the status of a persistent data store (for instance, to get caching statistics, or to be notified if the store's availability changes due to a database outage) with
LDClient.getDataStoreStatusProvider()
. - The
UserAttribute
class provides a less error-prone way to refer to user attribute names in configuration, and can also be used to get an arbitrary attribute from a user. - The
LDGson
andLDJackson
classes allow SDK classes like LDUser to be easily converted to or from JSON using the popular Gson and Jackson frameworks.
Changed:
- The minimum supported Java version is now 8.
- Package names have changed: the main SDK classes are now in
com.launchdarkly.sdk
andcom.launchdarkly.sdk.server
. - Many rarely-used classes and interfaces have been moved out of the main SDK package into
com.launchdarkly.sdk.server.integrations
andcom.launchdarkly.sdk.server.interfaces
. - The type
java.time.Duration
is now used for configuration properties that represent an amount of time, instead of using a number of milliseconds or seconds. - When using a persistent data store such as Redis, if there is a database outage, the SDK will wait until the end of the outage and then restart the stream connection to ensure that it has the latest data. Previously, it would try to restart the connection immediately and continue restarting if the database was still not available, causing unnecessary overhead.
EvaluationDetail.getVariationIndex()
now returnsint
instead ofInteger
.EvaluationReason
is now a single concrete class rather than an abstract base class.- The SDK no longer exposes a Gson dependency or any Gson types.
- Third-party libraries like Gson, Guava, and OkHttp that are used internally by the SDK have been updated to newer versions since Java 7 compatibility is no longer required.
- The component interfaces
FeatureStore
and UpdateProcessor have been renamed toDataStore
andDataSource
. The factory interfaces for these components now receive SDK configuration options in a different way that does not expose other components' configurations to each other. - The
PersistentDataStore
interface for creating your own database integrations has been simplified by moving all of the serialization and caching logic into the main SDK code.
Removed:
- All types and methods that were deprecated as of Java SDK 4.13.0 have been removed. This includes many
LDConfig.Builder()
methods, which have been replaced by the modular configuration syntax that was already added in the 4.12.0 and 4.13.0 releases. See the migration guide for details on how to update your configuration code if you were using the older syntax. - The Redis integration is no longer built into the main SDK library (see below).
- The deprecated New Relic integration has been removed.
If you want to test this release and you are using Consul, DynamoDB, or Redis as a persistent data store, you will also need to update to version 2.0.0-rc1 of the Consul integration, 3.0.0-rc1 of the DynamoDB integration, or 1.0.0-rc1 of the Redis integration (previously the Redis integration was built in; now it is a separate module).
4.13.0
[4.13.0] - 2020-04-21
Added:
- The new methods
Components.httpConfiguration()
andLDConfig.Builder.http()
, and the new classHttpConfigurationBuilder
, provide a subcomponent configuration model that groups together HTTP-related options such asconnectTimeoutMillis
andproxyHost
- similar to howComponents.streamingDataSource()
works for streaming-related options orComponents.sendEvents()
for event-related options. The individualLDConfig.Builder
methods for those options will still work, but are deprecated and will be removed in version 5.0. EvaluationReason
now has getter methods likegetRuleIndex()
that were previously only on specific reason subclasses. The subclasses will be removed in version 5.0.
Changed:
- In streaming mode, the SDK will now drop and restart the stream connection if either 1. it receives malformed data (indicating that some data may have been lost before reaching the application) or 2. you are using a database integration (a persistent feature store) and a database error happens while trying to store the received data. In both cases, the intention is to make sure updates from LaunchDarkly are not lost; restarting the connection causes LaunchDarkly to re-send the entire flag data set. This makes the Java SDK's behavior consistent with other LaunchDarkly server-side SDKs.
(Note that this means if there is a sustained database outage, you may see repeated reconnections as the SDK receives the data from LaunchDarkly again, tries to store it again, and gets another database error. Starting in version 5.0, there will be a more efficient mechanism in which the stream will only be restarted once the database becomes available again; that is not possible in this version because of limitations in the feature store interface.)
Fixed:
- Network errors during analytics event delivery could cause an unwanted large exception stacktrace to appear as part of the log message. This has been fixed to be consistent with the SDK's error handling in general: a brief message is logged at
ERROR
orWARN
level, and the stacktrace only appears if you have enabledDEBUG
level.
Deprecated:
LDConfig.Builder
methodsconnectTimeout
,connectTimeoutMillis
,proxyHost
,proxyPort
,proxyUsername
,proxyPassword
,sslSocketFactory
,wrapperName
, andwrapperVersion
. UseLDConfig.Builder.http()
andComponents.httpConfiguration()
instead.EvaluationReason
subclasses. Use the property getter methods onEvaluationReason
instead.- The built-in New Relic integration will be removed in the 5.0 release. Application code is not affected by this change since the integration was entirely reflection-based and was not exposed in the public API.