| Interface | Description |
|---|---|
| ConfigurablePlugin<T extends PluginConfiguration> |
Interface to allow plugins to receive configuration information from the UI/Administrative API.
|
| DescribesUIConfigurable |
An interface for describing the expected schema for a plugin's configuration, for use by the Administrative API
and UI.
|
| EntityScopedHandlerPlugin<H,C extends PluginConfiguration> |
A
ConfigurablePlugin that provides methods to create a runtime handler scoped to a specific configuration
entity such as a Site. |
ConfigurablePlugin and
DescribesUIConfigurable interfaces.provider-configuration file,
placed in the META-INF/services resource directory. The file name must be the fully
qualified class name of the plugin SPI. For example, the provider-configuration file for the
RuleInterceptor SPI would be named com.pingidentity.pa.sdk.policy.RuleInterceptor. The file
contains a list of fully qualified class names corresponding to implementations of the SPI, one per
line.lib/ directory of PingAccess.GET request to the descriptor endpoint for the corresponding SPI, such as
/rules/descriptors for RuleInterceptors. That endpoint is
populated by interrogating the installed plugins and calling their
DescribesUIConfigurable.getConfigurationFields() methods,
defined by DescribesUIConfigurable.
PingAccess expects that the ConfigurationFields provided by the plugin describe
the form of configuration data that can be mapped to a PluginConfiguration
instance.
PingAccess maps the plugin's JSON configuration, defined via the Administrative API, to a
PluginConfiguration instance. The concrete type of the
PluginConfiguration used by the plugin is
defined by the plugin annotation's expectedConfiguration field. The base class,
SimplePluginConfiguration, is provided to aid implementing the
PluginConfiguration interface.
PingAccess uses Jackson for JSON serialization and deserialization. A plugin can use Jackson custom serializers and deserializers to perform custom JSON mapping to fields in its configuration class. If a plugin requires custom JSON mapping, it must provide both a deserializer and serializer to allow PingAccess to store and transfer the configuration as JSON.
The ConfigurablePlugin interface expects implementations of
ConfigurablePlugin.getConfiguration() to return the
PluginConfiguration passed via the
ConfigurablePlugin.configure(com.pingidentity.pa.sdk.policy.PluginConfiguration)
method.
Once the JSON configuration is mapped into a PluginConfiguration, PingAccess
validates the configuration in two ordered steps:
Validator. Any
ConstraintViolations found will be returned to the administrator via the API.Validator returns no validation errors, the configuration instance
is passed to the
ConfigurablePlugin.configure(com.pingidentity.pa.sdk.policy.PluginConfiguration)
method.
Using javax.validation constraints is the preferred method for validating a
PluginConfiguration instance.
The field represented by a ConstraintViolation should reflect the name of the
corresponding field in the JSON configuration. This allows the API to correlate validation messages with their
corresponding field in the JSON configuration. An easy way to accomplish this is to apply a
Constraint to a field. That field's name should match the name of the
ConfigurationField used to describe the field in the configuration.
See this tutorial for an example of using
javax.validation constraints
Alternatively, plugins can throw a ConstraintViolationException from the
ConfigurablePlugin.configure(com.pingidentity.pa.sdk.policy.PluginConfiguration)
method. This is not preferred, but if the validation must be performed programmatically, the
ConstraintViolations defined within that exception will be used
by the API to correlate validation messages to their corresponding field in the JSON configuration. Since this
is not the preferred approach, plugins that take this route must provide their own implementation of
the ConstraintViolation class.
An example of the preferred validation approach:
public class ValidationExample implements ConfigurablePlugin<ValidationExample.Configuration>
{
private Configuration configuration;
@Override
public void configure(Configuration configuration) throws ValidationException
{
this.configuration = configuration;
// These assertions are guaranteed by the framework to always be true
assert(configuration.getAttributeName() != null);
assert(configuration.getAttributeName().length() > 0);
assert(configuration.getAttributeName().length() <= 16);
assert(configuration.getAttributeValue() != null);
}
@Override
public Configuration getConfiguration()
{
return configuration;
}
static class Configuration extends SimplePluginConfiguration
{
@NotNull
@Size(min = 1, max = 16, message = "Attribute name length must be between 1 and 16 characters")
private String attributeName;
@NotNull
private String attributeValue;
public String getAttributeName()
{
return attributeName;
}
public void setAttributeName(String attributeName)
{
this.attributeName = attributeName;
}
public String getAttributeValue()
{
return attributeValue;
}
public void setAttributeValue(String attributeValue)
{
this.attributeValue = attributeValue;
}
}
}
PluginConfiguration can be instantiated for many reasons and at many
times. The following describes the lifecycle actions that occur before the configurable plugin is considered
ready for use:
PostConstruct. The ordering of these operations is unspecified.PluginConfiguration will be instantiated.
PluginConfiguration is instantiated.PostConstruct. The ordering of these operations is unspecified.PluginConfiguration.setName(String) is calledPluginConfiguration instance.PluginConfiguration instance is passed to
a Validator.ConfigurablePlugin.configure(com.pingidentity.pa.sdk.policy.PluginConfiguration)
is called with the validated PluginConfiguration instance.HttpClient. These interfaces should only be implemented if the
implementation requires use of a HttpClient.
AsyncRuleInterceptorAsyncSiteAuthenticatorInterceptorAsyncIdentityMappingPluginAsyncLoadBalancingPluginHttpClient. They are not intended to be used for scheduling
asynchronous tasks. As a result, implementations should avoid using the following methods in
CompletableFuture:
CompletableFuture.runAsync(java.lang.Runnable)CompletableFuture.runAsync(java.lang.Runnable, java.util.concurrent.Executor)CompletableFuture.supplyAsync(java.util.function.Supplier)CompletableFuture.supplyAsync(java.util.function.Supplier, java.util.concurrent.Executor)provider-configuration file,
placed in META-INF/services resource directory. The file name must be the fully
qualified class name of the plugin SPI. For example, the provider-configuration file for the
LocaleOverrideService SPI would be named com.pingidentity.pa.sdk.localization.LocaleOverrideService.
The file contains a list of fully qualified class names corresponding to implementations of the SPI,
one per line.lib/ directory of PingAccess.Copyright 2023 Ping Identity Corp. All rights reserved.