.. 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();
   }
