summaryrefslogtreecommitdiffstats
path: root/docs/development/property-configuration.rst
diff options
context:
space:
mode:
authorLiam Fallon <liam.fallon@est.tech>2021-11-01 19:03:49 +0000
committerGerrit Code Review <gerrit@onap.org>2021-11-01 19:03:49 +0000
commit183c3ce689898af01ddc3f8d16cde818f4f838ca (patch)
tree9f5e6636a309ba95e32420749201adb1a590552b /docs/development/property-configuration.rst
parent407ef9b811fdbeba76ee53cf5cbc0ab9b9278ddf (diff)
parent7f8af467bb6653a109848594be8f909840f78092 (diff)
Merge "Evaluate property-configuration mechanisms" into istanbul
Diffstat (limited to 'docs/development/property-configuration.rst')
-rw-r--r--docs/development/property-configuration.rst220
1 files changed, 220 insertions, 0 deletions
diff --git a/docs/development/property-configuration.rst b/docs/development/property-configuration.rst
new file mode 100644
index 00000000..39691ade
--- /dev/null
+++ b/docs/development/property-configuration.rst
@@ -0,0 +1,220 @@
+.. 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();
+ }