---
title: SDK best practices
description: Your plugin can handle third-party dependencies in one of two ways:
component: pingfederate
version: 13.1
page_id: pingfederate:sdk_developers_guide:pf_sdk_best_practices
canonical_url: https://docs.pingidentity.com/pingfederate/13.1/sdk_developers_guide/pf_sdk_best_practices.html
llms_txt: https://docs.pingidentity.com/pingfederate/llms.txt
docs_for_agents: https://developer.pingidentity.com/build-with-ai/docs-for-agents.md
section_ids:
  dependency-management: Dependency management
  option-1-shade-the-dependency-into-your-jar: "Option 1: Shade the dependency into your jar"
  option-2-rely-on-the-server: "Option 2: rely on the server"
  when-to-use-each-method: When to use each method
  versioning-and-manifests: Versioning and manifests
  sdk-versioning-and-compatibility: SDK versioning and compatibility
---

# SDK best practices

## Dependency management

Your plugin can handle third-party dependencies in one of two ways:

### Option 1: Shade the dependency into your jar

If the server library might not stay stable, or if you need a specific library version to be isolated from other plugins' choices. use Maven's shade plugin to bundle it to your jar under a relocated packaged namespace. This ensures your plugin works identically across server versions, but at the cost of larger jars and more complex shade configuration.

The `notification-publisher` example demonstrates this patterns. It needs specific versions of Jackson, which it shades into the jar under `com.pingidentity.notification.publisher.shade.*`:

```xml
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.21.1</version>
    <scope>compile</scope>
</dependency>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.5.3</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <artifactSet>
                    <includes>
                        <include>com.fasterxml.jackson.core:jackson-databind</include>
                        <include>com.fasterxml.jackson.core:jackson-core</include>
                        <include>com.fasterxml.jackson.core:jackson-annotations</include>
                    </includes>
                </artifactSet>
                <relocations>
                    <relocation>
                        <pattern>com.fasterxml</pattern>
                        <shadedPattern>com.pingidentity.notification.publisher.shade.com.fasterxml</shadedPattern>
                    </relocation>
                </relocations>
            </configuration>
        </execution>
    </executions>
</plugin>
```

Refer to the `notification-publisher/pom.xml` for a complete example.

### Option 2: rely on the server

If PingFederate already includes the library you need, declare it using the `provided` scope rather than bundling it with your plugin. This reduces your jar size and avoids conflicts with other plugins. The catch is, if the server upgrades or removes that library in a future version, you'll need to test and potentially upgrade your plugin to prevent it from breaking.

```xml
<!-- Libraries PingFederate already ships; don't bundle them -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.18.0</version>
    <scope>provided</scope>
</dependency>
```

### When to use each method

* Use `provided` for small, stable libraries that the server is guaranteed to include, like `slf4j-api`, `commons-logging`, and `jakarta.servlet-api`.

* Shade dependencies that you own the version of, or that aren't bundled by PingFederate, or where version conflicts with other plugins are a risk.

* Never shade `pingfederate-sdk` itself. Always use `provided`.

## Versioning and manifests

Plugins can report their version to PingFederate at runtime using the jar manifest. To enable this, configure `maven-jar-plugin` to embed version information:

```xml
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.4.1</version>
    <configuration>
        <archive>
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
            </manifest>
        </archive>
    </configuration>
</plugin>
```

Then retrieve it in your plugin at runtime:

```java
public String getVersion() {
    return getClass().getPackage().getImplementationVersion();
}
```

This is a convention most plugins in the examples follow. It lets admins and logs verify which version of your plugin is deployed.

## SDK versioning and compatibility

The PingFederate SDK maintains backwards compatibility. If you build against version 13.0.0.4, your plugin will run on versions 13.1 or 13.2 without requiring a rebuild. The SDK doesn't remove or break existing interfaces.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | New releases can change which Java versions PingFederate is compiled with. When this happens, your plugin might need to be recompiled with the same or later version of the Java Development Kit (JDK) *(tooltip: \<div class="paragraph">&#xA;\<p>A development environment for building applications and components using Java.\</p>&#xA;\</div>)*. These changes are documented in [Installing Java](../installing_and_uninstalling_pingfederate/pf_install_java.html). |

* New features are added

  When new SDK interfaces and methods are introduced, they're marked with a `@Since` annotation in the Javadoc, indicating which SDK version introduced them.

* Features are deprecated

  When an interface or method is scheduled for removal, it's marked `@Deprecated` in the Javadoc with a note about what to use instead.

  Deprecated items remain available for several major versions, giving you time to migrate. The SDK won't break your plugin just because you're using a deprecated method. It will log warnings while compiling your plugin, but the plugin will continue to work. When you see these compile warnings, start planning to upgrade to the supported methods.

You can update your `pingfederate-sdk.version` confidently, and you can build plugins against newer SDK versions and deploy them to older servers, as long as you don't use methods newer than what the server includes.
