Plugins Overview
Overview
Plugins are junctures in Socotra where system behavior can be customized with logic written in Java.
The following plugins are currently available:
Plugin Execution
Generally, plugins are executed on entities as they progress through their lifecycles, often as the result of user-initiated API requests. Consult the policy quotes guide for details on how new policies and subsequent post-issuance transactions are constructed and issued.
Assuming each plugin has been implemented, this nominal flow includes the following plugin execution order:
State |
Plugins |
---|---|
Draft |
n/a |
Validation |
Precommit, Validation |
Pricing |
Rating |
Underwriting |
Underwriting |
Accept |
n/a |
Issue |
n/a |
Plugin Configuration
Plugins are implemented as Java files included as part of the configuration. They can be added as either Global
plugins in the top-level /plugins/java
folder, or as Product
-specific plugins within a particular product’s folder <productName>/plugins/java
.
For each entity type defined in configuration and which should be subject to a plugin’s action, the plugin should implement an override method specific to the entity type. The method overrides the default no-op method implementation provided by the plugin interface.
Because the validation, pricing, and underwriting actions can occur for both quotes and policy transactions, distinct interfaces are defined for both quote and transaction requests.
When both Global
and Product
implementations of a particular interface coexist, the Product implementation takes precedence.
Examples:
Assuming Global-level plugins only
Configuration has a top-level
config.json
shown belowConfiguration has a top-level
plugins/java
folder containingValidationPluginImpl.java
Sample contents of the top-level config.json
file defining various entity types:
{
"accounts": {
"consumerAccount": {
"data": {"some data config"}
},
"commercialAccount": {
"data": {}
},
"products": {
"personalAuto": {
"eligibleAccountTypes": ["consumerAccount"]
"data": {}
}
"payments": {
"achPayment": {
"data": {}
}
}
"disbursements": {
"customerRefund": {
"data": {}
}
}
Sample contents of the ValidationPluginImpl.java
file:
package com.socotra.deployment.customer; // Must include
// Must implement ValidationPlugin, which defines interfaces and default method implementations for override
public class ValidationPluginImpl implements ValidationPlugin {
// Override method to implement validation of the ConsumerAccount type
@Override
public ValidationItem validate(ConsumerAccountRequest consumerAccountRequest) {
// Some validation logic
}
return ValidationItem.builder().build();
}
// Override method to implement validation of the CommercialAccount type
@Override
public ValidationItem validate(CommercialAccountRequest commercialAccountRequest) {
// Some validation logic
}
return ValidationItem.builder().build();
}
// Override method to implement validation of a QUOTE based on the PersonalAuto product
@Override
public ValidationItem validate(PersonalAutoQuoteRequest personalAutoQuoteRequest) {
// Some validation logic
}
return ValidationItem.builder().build();
}
// Override method to implement validation of a TRANSACTION based on the PersonalAuto product
@Override
public ValidationItem validate(PersonalAutoRequest personalAutoRequest) {
// Some validation logic
}
return ValidationItem.builder().build();
}
}
Refer to individual plugin pages for more specifics about their interface types.
Precommit and Validation
Validation is run on various key entities when in a draft state (and therefore still mutable). Its purpose is to verify that an entity conforms with the schema defined in its configuration, along with any custom business logic constraints the implementer chooses to impose. Unlike pricing and underwriting, which are actions exclusive to quotes and transactions, many other entities also require validation and so are subject to the validation plugin. Once successfully validated, entities are generally immutable.
The Precommit plugin affords the opportunity to manipulate the form of an entity immediately prior to validation. The precommit plugin is currently tethered to the validation plugin, executed in tandem: first precommit, followed by validation. Refer to their individual overviews for further details.
Data Fetcher
The Data Fetcher is a class available to plugins with a set of built-in methods that will return additional entity data, given a locator. Generally the return object is similar in structure to those returned from the API for that entity.
Usage example within a validation plugin:
package com.socotra.deployment.customer; // Must include
// Must implement ValidationPlugin
public class ValidationPluginImpl implements ValidationPlugin {
// Override method to implement validation of a QUOTE based on the PersonalAuto product
@Override
public ValidationItem validate(PersonalAutoQuoteRequest personalAutoQuoteRequest) {
// Fetching an account by its locator
var account = DataFetcherFactory.get().getAccount(personalAutoQuoteRequest.quote().accountLocator());
// Some validation logic
}
return ValidationItem.builder().build();
}
}
Method |
Parameters |
Response |
---|---|---|
getAccount() |
accountLocator |
|
getQuote() |
quoteLocator |
|
getQuoteUnderwritingFlags() |
quoteLocator |
|
getQuotePricing() |
quoteLocator |
|
getTransaction() |
transactionLocator |
|
getPolicy() |
policyLocator |
|
getSegments() |
transactionLocator |
|
getAuxData() |
locator, key |
|
getAuxDataKeys() |
locator, offset, count |
|
getTransactionPricing() |
transactionLocator |
|
getAffectedTransactions() |
transactionLocator |
|
getTerm() |
termLocator |
Resource Selector
The Resource Selector is a class available to plugins with a set of built-in methods for fetching table records or sensitive items like credentials from a Secret resource. Refer to the resources guide for more information on how resource versioning and effective dating are managed.
The Resource Selection service manages the identification of which particular resource instance the plugin should retrieve records from, and generally does not need to be accommodated by the plugin code.
Example:
makeSymbol |
modelSymbol |
modelYear |
typeFactor |
collFactor |
---|---|---|---|---|
key |
key |
key |
value |
value |
Toyota |
Camry |
2023 |
0.84221 |
0.86764 |
Ford |
Explorer |
2022 |
0.87839 |
0.91023 |
package com.socotra.deployment.customer;
import com.socotra.deployment.ResourceSelectorFactory;
public class RatingPluginImpl implements RatePlugin {
// Interface for rating quotes based on the personalAuto product
@Override
public RatingSet rate(PersonalAutoQuoteRequest personalAutoQuoteRequest) {
PersonalAutoQuote personalAutoQuote = personalAutoQuoteRequest.quote();
List<RatingItem> ratingItems = new ArrayList<>();
PersonalVehicle vehicle = personalAutoQuote.personalVehicle();
var vehicleClassFactor = ResourceSelectorFactory.getInstance()
.getSelector(personalAutoQuote)
.getTable(VehicleClassFactors.class)
.getRecord(VehicleClassFactors.makeKey(vehicle.data().makeSymbol(), vehicle.data().modelSymbol(), Integer.parseInt(vehicle.data().modelYear())));
BigDecimal vehicleTypeFactor = driverAgeFactor.get().typeFactor();
double rate = 0.003 * vehicleTypeFactor + 50;
ratingItems.add(RatingItem.builder()
.elementLocator(vehicle.bodilyInjuryCoverage().locator())
.chargeType(ChargeType.premium)
.rate(BigDecimal.valueOf(rate))
.build());
return RatingSet.builder().ok(true).ratingItems(ratingItems).build();
}
}
Note
For now, tables and Secrets are the only resource types used in plugins. That may change in future releases.
External API Calls
All plugins are capable to making secure API calls via the standard library’s HttpClient.
Sample code based on validation plugin below:
package com.socotra.deployment.customer;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ValidationPluginImpl implements ValidationPlugin {
@Override
public ValidationItem validate(PersonalAutoQuoteRequest personalAutoQuoteRequest) {
// Make the external call
try {
HttpRequest req = HttpRequest.newBuilder()
.uri(new URI("https://example.com/some-data")).GET().build();
HttpResponse<String> resp = HttpClient.newBuilder()
.build()
.send(req, HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
}
// Do some validation
return ValidationItem.builder().build();
}
}