Evaluate property-configuration mechanisms
This article explains how to implement handling and validation of common parameter into the Policy Framework Components.
Not Spring boot framework
The application should have a ParameterHandler class to support the map values from Json to a POJO, so it should be load the file, convert it performing all type conversion.
The code below shown an example of that class:
public class PapParameterHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(PapParameterHandler.class);
private static final Coder CODER = new StandardCoder();
/**
* Read the parameters from the parameter file.
*
* @param arguments the arguments passed to policy pap
* @return the parameters read from the configuration file
* @throws PolicyPapException on parameter exceptions
*/
public PapParameterGroup getParameters(final PapCommandLineArguments arguments) throws PolicyPapException {
PapParameterGroup papParameterGroup = null;
// Read the parameters
try {
// Read the parameters from JSON
var file = new File(arguments.getFullConfigurationFilePath());
papParameterGroup = CODER.decode(file, PapParameterGroup.class);
} catch (final CoderException e) {
final String errorMessage = "error reading parameters from \"" + arguments.getConfigurationFilePath()
+ "\"\n" + "(" + e.getClass().getSimpleName() + ")";
throw new PolicyPapException(errorMessage, e);
}
// The JSON processing returns null if there is an empty file
if (papParameterGroup == null) {
final String errorMessage = "no parameters found in \"" + arguments.getConfigurationFilePath() + "\"";
LOGGER.error(errorMessage);
throw new PolicyPapException(errorMessage);
}
// validate the parameters
final ValidationResult validationResult = papParameterGroup.validate();
if (!validationResult.isValid()) {
String returnMessage =
"validation error(s) on parameters from \"" + arguments.getConfigurationFilePath() + "\"\n";
returnMessage += validationResult.getResult();
LOGGER.error(returnMessage);
throw new PolicyPapException(returnMessage);
}
return papParameterGroup;
}
}
The POJO have to implement org.onap.policy.common.parameters.ParameterGroup interface or eventually extend org.onap.policy.common.parameters.ParameterGroupImpl. The last one already implements validate() method that performs error checking using validation org.onap.policy.common.parameters.annotations.
The code below shown an example of POJO:
@NotNull
@NotBlank
@Getter
public class PapParameterGroup extends ParameterGroupImpl {
@Valid
private RestServerParameters restServerParameters;
@Valid
private PdpParameters pdpParameters;
@Valid
private PolicyModelsProviderParameters databaseProviderParameters;
private boolean savePdpStatisticsInDb;
@Valid
private TopicParameterGroup topicParameterGroup;
// API, Distribution Health Check REST client parameters.
private List<@NotNull @Valid RestClientParameters> healthCheckRestClientParameters;
/**
* Create the pap parameter group.
*
* @param name the parameter group name
*/
public PapParameterGroup(final String name) {
super(name);
}
}
The code shows below, is an example of Unit Test validation of the POJO PapParameterGroup:
private static final Coder coder = new StandardCoder();
@Test
void testPapParameterGroup_NullName() throws Exception {
String json = commonTestData.getPapParameterGroupAsString(1).replace("\"PapGroup\"", "null");
final PapParameterGroup papParameters = coder.decode(json, PapParameterGroup.class);
final ValidationResult validationResult = papParameters.validate();
assertFalse(validationResult.isValid());
assertEquals(null, papParameters.getName());
assertThat(validationResult.getResult()).contains("is null");
}
Using Spring boot framework
Spring loads automatically the property file and put it available under the org.springframework.core.env.Environment Spring component.
Environment
A component can use Environment component directly.
Environment component is not a good approach because there is not type conversion and error checking, but it could be useful when the name of the property you need to access changes dynamically.
Annotation-based Spring configuration
All annotation-based Spring configurations support the Spring Expression Language (SpEL), a powerful expression language that supports querying and manipulating an object graph at runtime.
A documentation about SpEL could be found here: https://docs.spring.io/spring-framework/docs/3.0.x/reference/expressions.html.
A component can use org.springframework.beans.factory.annotation.Value, which reads from properties, performs a type conversion and injects the value into the filed. There is not error checking, but it can assign default value if the property is not defined.
The code below shows how to inject a value of a property into @Scheduled configuration.
ConfigurationProperties
@ConfigurationProperties can be used to map values from .properties( .yml also supported) to a POJO. It performs all type conversion and error checking using validation javax.validation.constraints
In a scenario that we need to include into a POJO shown before, a class that implement ParameterGroup interface, we need to add the org.onap.policy.common.parameters.validation.ParameterGroupConstraint annotation. That annotation is configured to use ParameterGroupValidator that handles the conversion of a org.onap.policy.common.parameters.BeanValidationResult to a Spring validation.
The code below shown how to add TopicParameterGroup parameter into ClRuntimeParameterGroup:
A bean configured with ConfigurationProperties, is automatically a Spring component and could be injected into other Spring components. The code below shown an example:
The code shows below, is an example of Unit Test validation of the POJO ClRuntimeParameterGroup: