Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This article explains how to implement handling and validation of common parameter into the Policy Framework Components using .

Table of Contents

Not Spring boot framework

...

Environment

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:

Code Block
languagejava
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:

Code Block
languagejava
@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:

Code Block
languagejava
    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

A component can use 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.

...

The code below shows how to inject a value of a property into @Schedule @Scheduled configuration.

Code Block
languagejava
    @Scheduled(
            fixedRateString = "${runtime.participantParameters.heartBeatMs}",
            initialDelayString = "${runtime.participantParameters.heartBeatMs}")
    public void schedule() { 
}

...

Code Block
languagejava
@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; 
}


Convert 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.BeanValidationResult to Spring validator using 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.ParameterGroupConstraint

The code below shown how to add TopicParameterGroup parameter into ClRuntimeParameterGroup:

Code Block
languagejava
    @NotNull
    @ParameterGroupConstraint
    private TopicParameterGroup topicParameterGroup;


ClRuntimeParameterGroup defined before 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
languagejava
@Component
@RequiredArgsConstructor
public class Example {
 
private ClRuntimeParameterGroup parameters;
....
 
public void method() {
    ..... 
    long heartBeatMs = parameters.getHeartBeatMs();
    .....
}


The below code shows below, is an example of Unit Test validation of the POJO ClRuntimeParameterGroup which contains the values mapped from properties file.:

Code Block
languagejava
    private ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

    @Test
    void testParameters_NullTopicParameterGroup() {
        final ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup();
        parameters.setTopicParameterGroup(null);
        assertThat(validatorFactory.getValidator().validate(parameters)).isNotEmpty();
    }

Note
This page is Work in Progress