blob: 39691ade3b7a8dfa85092c5410fde720f9b8b816 [file] [log] [blame]
.. This work is licensed under a
.. Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0
.. _property-configuration:
Property-configuration mechanisms
#################################
.. contents::
:depth: 3
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 ParameterHandler:
.. code-block:: java
public class PapParameterHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(PapParameterHandler.class);
private static final Coder CODER = new StandardCoder();
public PapParameterGroup getParameters(final PapCommandLineArguments arguments) throws PolicyPapException {
PapParameterGroup papParameterGroup = null;
try {
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);
}
if (papParameterGroup == null) {
final String errorMessage = "no parameters found in \"" + arguments.getConfigurationFilePath() + "\"";
LOGGER.error(errorMessage);
throw new PolicyPapException(errorMessage);
}
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:
.. code-block:: java
@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;
private List<@NotNull @Valid RestClientParameters> healthCheckRestClientParameters;
public PapParameterGroup(final String name) {
super(name);
}
}
The code shows below, is an example of Unit Test validation of the POJO PapParameterGroup:
.. code-block:: java
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.
.. code-block:: java
@Component
@RequiredArgsConstructor
public class Example {
private Environment env;
....
public void method(String pathPropertyName) {
.....
String path = env.getProperty(pathPropertyName);
.....
}
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.
.. code-block:: java
@Value("${security.enable-csrf:true}")
private boolean csrfEnabled = true;
The code below shows how to inject a value of a property into @Scheduled configuration.
.. code-block:: java
@Scheduled(
fixedRateString = "${runtime.participantParameters.heartBeatMs}",
initialDelayString = "${runtime.participantParameters.heartBeatMs}")
public void schedule() {
}
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**.
.. code-block:: java
@Validated
@Getter
@Setter
@ConfigurationProperties(prefix = "runtime")
public class ClRuntimeParameterGroup {
@Min(100)
private long heartBeatMs;
@Valid
@Positive
private long reportingTimeIntervalMs;
@Valid
@NotNull
private ParticipantUpdateParameters updateParameters;
@NotBlank
private String description;
}
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:
.. code-block:: java
@NotNull
@ParameterGroupConstraint
private TopicParameterGroup topicParameterGroup;
A bean configured with ConfigurationProperties, is automatically a Spring component and could be injected into other Spring components. The code below shown an example:
.. code-block:: java
@Component
@RequiredArgsConstructor
public class Example {
private ClRuntimeParameterGroup parameters;
....
public void method() {
.....
long heartBeatMs = parameters.getHeartBeatMs();
.....
}
The code shows below, is an example of Unit Test validation of the POJO ClRuntimeParameterGroup:
.. code-block:: java
private ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
@Test
void testParameters_NullTopicParameterGroup() {
final ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup();
parameters.setTopicParameterGroup(null);
assertThat(validatorFactory.getValidator().validate(parameters)).isNotEmpty();
}