# Floating Features

Similar to [**Floating Licenses**](https://docs.licensespring.com/license-entitlements/floating-licenses), LicenseSpring supports [**Floating Features**](https://docs.licensespring.com/license-entitlements/floating-features).

In this guide you can find an overview of the floating features functionality: registering and releasing floating features and setting up the Floating Features Watchdog.

#### Check if a feature is floating

As with floating licenses, you can check if a feature is floating using properties for cloud, as well as offline floating features. To start, use the following code to check if a license feature is floating:

{% tabs %}
{% tab title="C#" %}

```csharp
foreach (ILicenseFeature licenseFeature in license.Features())
{
  if(licenseFeature.IsFloating || licenseFeature.IsOfflineFloating)
  {
    // DO SOMETHING WITH A FLOATING FEATURE
  }
}
```

{% endtab %}

{% tab title="C++" %}

```cpp
for( const auto& feature : license->features() )
{
    if( feature.isFloating() || feature.isOfflineFloating() )
    {
        // DO SOMETHING WITH A FLOATING FEATURE
    }
}
```

{% endtab %}

{% tab title="Python" %}

```python
## add getters
for feature in license.features():
    feature_data = get_feature_data(feature)
    if feature_data["is_floating"] or feature_data["is_floating_cloud"]
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseData data = license.getData();
List<LicenseFeature> features = data.getProductFeatures();

for (LicenseFeature feature : features) {
  if (feature.isFloating() || feature.isFloatingCloud()) {
    // Do something with a floating feature...
  }
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
for feature in license.features {
    if feature.isFloating || feature.isOfflineFloating {
        // DO SOMETHING WITH A FLOATING FEATURE
    }
}
```

{% endtab %}
{% endtabs %}

#### Floating slots

Developers will want to know the maximum number of users that can simultaneously use a floating feature and the current number of users using the feature. That can be done with:

{% tabs %}
{% tab title="C#" %}

```csharp
uint maxUsers = licenseFeature.FloatingSlotsCount;
uint currentUsers = licenseFeature.FloatingSlotsInUse;
```

{% endtab %}

{% tab title="C++" %}

```cpp
int32_t maxUsers = feature.floatingUsers()
int32_t currentUsers = feature.floatingInUseCount();
```

{% endtab %}

{% tab title="Python" %}

```python
feature_lkprod1f1fc1 = license.get_feature_data("lkprod1f1fc1")

feature_lkprod1f1fc1["floating_timeout"] # if feature is floating type
feature_lkprod1f1fc1["floating_users"] # if feature is floating type
```

{% endtab %}

{% tab title="Java" %}

```java
Long floatingTimeout = feature.getFloatingTimeout();
Long floatingUsers = feature.getFloatingUsers();
```

{% endtab %}

{% tab title="Swift" %}

```swift
let floatingTimeout = feature.floatingTimeout
let floatingUsers = feature.floatingInUseCount
```

{% endtab %}
{% endtabs %}

#### Floating timeout

You can get information on the floating feature timeout (in minutes) and the point in time until which a registered feature is valid (time of registration + floating feature timeout). After that time, LicenseSpring server will automatically release the feature - if it's not registered again.

{% tabs %}
{% tab title="C#" %}

```csharp
uint floatingTimeout = license.FloatingTimeout;
DateTime floatingEndDateTime = license.FloatingEndDateTime;
DateTime floatingEndDateTimeUtc = license.FloatingEndDateTimeUtc;
```

{% endtab %}

{% tab title="C++" %}

```cpp
int32_t floatingTimeout = feature.floatingTimeout();
tm floatingEndDateTime = feature.floatingEndDateTime();
tm floatingEndDateTimeUtc = feature.floatingEndDateTimeUtc();
```

{% endtab %}

{% tab title="Python" %}

```python
feature_lkprod1f1fc1 = license.get_feature_data("lkprod1f1fc1")

feature_lkprod1f1fc1["floating_timeout"]
feature_lkprod1f1fc1["floating_end_date"]
feature_lkprod1f1fc1["floating_start_date"]
```

{% endtab %}

{% tab title="Java" %}

```java
Long floatingTimeout = feature.getFloatingTimeout();
```

{% endtab %}

{% tab title="Swift" %}

```swift
let floatingTimeout = license.floatingTimeout
let floatingEndDate = license.floatingEndDate
```

{% endtab %}
{% endtabs %}

#### Registering and releasing floating features

Similar to floating licenses, floating features have to be periodically registered on the server for them to take up a floating slot.

{% tabs %}
{% tab title="C#" %}

```csharp
ILicenseManager licenseManager = LicenseManager.GetInstance();
ILicense license = licenseManager.CurrentLicense();
ILicenseFeature feature = license.Features().First(e => e.IsFloating);
license.RegisterFloatingFeature(feature);
// You can find a similar sample in the console sample app 
// that is a part of the SDK.
```

{% endtab %}

{% tab title="C++" %}

```cpp
auto licenseManager = LicenseManager::create( pConfiguration );
auto license = licenseManager->getCurrentLicense();
auto feature = license->features().front();
license->registerFloatingFeature( feature.code() );

// You can find a similar sample in CppSample 
// if you wish not to add the feature to the watchdog, License::registerFloatingFeature has an optional `addToWatchdog` bool parameter.
```

{% endtab %}

{% tab title="Python" %}

```python
license.check_feature("feature_code")
```

{% endtab %}

{% tab title="Go" %}

```go
// Go SDK v2
ld, err = lh.CheckLicenseFeature(ctx, featureCode)
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseIdentity identity = LicenseIdentity.fromKey("<LICENSE-KEY>");
String featureCode = "<FEATURE-CODE>";
service.checkLicenseFeature(identity, featureCode)
```

{% endtab %}

{% tab title="Swift" %}

```swift
let floatingFeature = license.features.filter { $0.isFloating || $0.isOfflineFloating }.first!
try license.registerFloatingFeature(floatingFeature)
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Note that in the C++ SDK you need to pass the feature code instead of the feature object to `License::registerFloatingFeature`
{% endhint %}

Likewise, if you wish to release a feature before its timeout, you can do it like so:

{% tabs %}
{% tab title="C#" %}

```csharp
ILicenseManager licenseManager = LicenseManager.GetInstance();
ILicense license = licenseManager.CurrentLicense();
ILicenseFeature feature = license
                           .Features()
                           .First(e => e.FloatingEndDateTime > DateTime.Now);
license.ReleaseFloatingFeature(feature);
// You can find a similar sample in the console sample app 
// that is a part of the SDK.
```

{% endtab %}

{% tab title="C++" %}

```cpp
auto licenseManager = LicenseManager::create(pConfiguration);
auto license = licenseManager->getCurrentLicense();
auto feature = license->features().front();
license->releaseFloatingFeature(feature.code());
```

{% endtab %}

{% tab title="Python" %}

```python
license.release_feature("lkprod1f1fc1")
```

{% endtab %}

{% tab title="Go" %}

```go
ld, err = lh.ReleaseFloatingLicenseFeature(ctx, featureCode)
```

{% endtab %}

{% tab title="Java" %}

```java
LicenseIdentity identity = LicenseIdentity.fromKey("<LICENSE-KEY>");
String featureCode = "<FEATURE-CODE>";
service.releaseFloatingFeature(identity, featureCode);
```

{% endtab %}

{% tab title="Swift" %}

```swift
let floatingFeature = license.features.filter { $0.isFloating || $0.isOfflineFloating }.first!
license.ReleaseFloatingFeature(feature)
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
In .NET SDK, ILicenseFeature data is not refreshed after registering and releasing the feature. In order to get updated values like FloatingSlotsInUse and FloatingEndDateTime you have to call ILicense.Features() method again.

The same applies to the C++ SDK. You have to call license->features() again to get updated feature values.
{% endhint %}

#### Floating feature borrowing

If the license user is planning to be offline for a longer period of time, they can borrow a floating feature instead. Borrowing a feature removes it from the feature watchdog.

For user-based licenses, the application must collect the user's password or initiate an SSO login via their Identity Provider:

{% tabs %}
{% tab title="C++" %}

```cpp
std::string featureCode = "floatingfeature";
license->borrowFloatingFeature(featureCode);

std::string accountCode;
bool useAuthCode = true;
auto url = manager->getSSOUrl(accountCode, useAuthCode);

std::string authCode; // extracted from the redirect URI
std::string borrowEndDateTime; // empty timestamp indicates maximum allowed borrow length
std::string redirectUri; // set when using alternative redirect URI
license->borrowFloatingFeature(featureCode, borrowEndDateTime, accountCode, useAuthCode, redirectUri);
```

{% endtab %}
{% endtabs %}

#### Watchdog setup

Similar to a **floating license watchdog**, floating features have to initialize the watchdog in order to use its functionalities. See: [Floating Licensing](https://docs.licensespring.com/sdks/tutorials/licensing-scenarios/floating-licensing).

Once configured, floating features only need to be registered once. The watchdog ensures they remain active until they are manually released. Be sure to release them when the application shuts down to free up the slots.

You initialize the watchdog like so:

{% tabs %}
{% tab title="C#" %}

```csharp
void WatchdogCallbackMethod(LicenseSpringException e)
{
  // DO SOMETHING
}

license.SetupFloatingFeatureWatchdog(WatchdogCallbackMethod);

// Callback method will be invoked only if an exception in a watchdog thread
// is raised. If you want to invoke the callback on every feature
// registration you can pass an optional parameter to the method:
license.SetupFloatingFeatureWatchdog(WatchdogCallbackMethod, true);
```

{% endtab %}

{% tab title="C++" %}

```cpp
void watchdogCallback( const LicenseSpringException& ex )
{
  // DO SOMETHING
}

license->setupFeatureWatchdog( watchdogCallback );
```

{% endtab %}

{% tab title="Python" %}

```python
license.setup_feature_watch_dog(callback,timeout)
```

{% endtab %}

{% tab title="Java" %}

```java
FloatingConfiguration config = FloatingConfiguration.builder()
  .enableFloatingFeaturePeriodicCheck(true)
  .build();
```

{% endtab %}

{% tab title="Swift" %}

```swift
typealias LicenseWatchdogCallback = (LSError?) -> Void

license.setupFloatingFeatureWatchdog(callback: { error in
    //do something
}, runCallbackOnEveryCheck: true)
```

{% endtab %}
{% endtabs %}

Setting up the watchdog will also start the thread. If you wish to stop automatically extending your floating features, you can stop the watchdog:

{% tabs %}
{% tab title="C#" %}

```csharp
license.StopFloatingFeatureWatchdog();
```

{% endtab %}

{% tab title="C++" %}

```cpp
license->stopFeatureWatchdog();
```

{% endtab %}

{% tab title="Python" %}

```python
license.stop_feature_watch_dog()
```

{% endtab %}

{% tab title="Swift" %}

```swift
license.stopFloatingFeatureWatchdog()
```

{% endtab %}
{% endtabs %}

And once stopped, it can be restarted again:

{% tabs %}
{% tab title="C#" %}

```csharp
license.StartFloatingFeatureWatchdog();
```

{% endtab %}

{% tab title="C++" %}

```cpp
license->resumeFeatureWatchdog();
```

{% endtab %}

{% tab title="Swift" %}

```swift
license.startFloatingFeatureWatchdog();
```

{% endtab %}
{% endtabs %}
