blob: 39691ade3b7a8dfa85092c5410fde720f9b8b816 [file] [log] [blame]
FrancescoFioraEstde777222021-10-21 09:32:08 +01001.. This work is licensed under a
2.. Creative Commons Attribution 4.0 International License.
3.. http://creativecommons.org/licenses/by/4.0
4
5.. _property-configuration:
6
7Property-configuration mechanisms
8#################################
9
10.. contents::
11 :depth: 3
12
13This article explains how to implement handling and validation of common parameter into the Policy Framework Components.
14
15Not Spring boot framework
16*************************
17The 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.
18
19The code below shown an example of ParameterHandler:
20
21.. code-block:: java
22
23 public class PapParameterHandler {
24
25 private static final Logger LOGGER = LoggerFactory.getLogger(PapParameterHandler.class);
26
27 private static final Coder CODER = new StandardCoder();
28
29 public PapParameterGroup getParameters(final PapCommandLineArguments arguments) throws PolicyPapException {
30 PapParameterGroup papParameterGroup = null;
31
32 try {
33 var file = new File(arguments.getFullConfigurationFilePath());
34 papParameterGroup = CODER.decode(file, PapParameterGroup.class);
35 } catch (final CoderException e) {
36 final String errorMessage = "error reading parameters from \"" + arguments.getConfigurationFilePath()
37 + "\"\n" + "(" + e.getClass().getSimpleName() + ")";
38 throw new PolicyPapException(errorMessage, e);
39 }
40
41 if (papParameterGroup == null) {
42 final String errorMessage = "no parameters found in \"" + arguments.getConfigurationFilePath() + "\"";
43 LOGGER.error(errorMessage);
44 throw new PolicyPapException(errorMessage);
45 }
46
47 final ValidationResult validationResult = papParameterGroup.validate();
48 if (!validationResult.isValid()) {
49 String returnMessage =
50 "validation error(s) on parameters from \"" + arguments.getConfigurationFilePath() + "\"\n";
51 returnMessage += validationResult.getResult();
52
53 LOGGER.error(returnMessage);
54 throw new PolicyPapException(returnMessage);
55 }
56
57 return papParameterGroup;
58 }
59 }
60
61
62The 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**.
63
64The code below shown an example of POJO:
65
66.. code-block:: java
67
68 @NotNull
69 @NotBlank
70 @Getter
71 public class PapParameterGroup extends ParameterGroupImpl {
72 @Valid
73 private RestServerParameters restServerParameters;
74 @Valid
75 private PdpParameters pdpParameters;
76 @Valid
77 private PolicyModelsProviderParameters databaseProviderParameters;
78 private boolean savePdpStatisticsInDb;
79 @Valid
80 private TopicParameterGroup topicParameterGroup;
81
82 private List<@NotNull @Valid RestClientParameters> healthCheckRestClientParameters;
83
84 public PapParameterGroup(final String name) {
85 super(name);
86 }
87 }
88
89
90The code shows below, is an example of Unit Test validation of the POJO PapParameterGroup:
91
92.. code-block:: java
93
94 private static final Coder coder = new StandardCoder();
95
96 @Test
97 void testPapParameterGroup_NullName() throws Exception {
98 String json = commonTestData.getPapParameterGroupAsString(1).replace("\"PapGroup\"", "null");
99 final PapParameterGroup papParameters = coder.decode(json, PapParameterGroup.class);
100 final ValidationResult validationResult = papParameters.validate();
101 assertFalse(validationResult.isValid());
102 assertEquals(null, papParameters.getName());
103 assertThat(validationResult.getResult()).contains("is null");
104 }
105
106
107Using Spring boot framework
108***************************
109Spring loads automatically the property file and put it available under the **org.springframework.core.env.Environment** Spring component.
110
111Environment
112+++++++++++
113A component can use Environment component directly.
114
115Environment 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.
116
117.. code-block:: java
118
119 @Component
120 @RequiredArgsConstructor
121 public class Example {
122
123 private Environment env;
124 ....
125
126 public void method(String pathPropertyName) {
127 .....
128 String path = env.getProperty(pathPropertyName);
129 .....
130 }
131
132Annotation-based Spring configuration
133+++++++++++++++++++++++++++++++++++++
134All annotation-based Spring configurations support the Spring Expression Language (SpEL), a powerful expression language that supports querying and manipulating an object graph at runtime.
135A documentation about SpEL could be found here: https://docs.spring.io/spring-framework/docs/3.0.x/reference/expressions.html.
136
137A 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.
138
139.. code-block:: java
140
141 @Value("${security.enable-csrf:true}")
142 private boolean csrfEnabled = true;
143
144
145The code below shows how to inject a value of a property into @Scheduled configuration.
146
147.. code-block:: java
148
149 @Scheduled(
150 fixedRateString = "${runtime.participantParameters.heartBeatMs}",
151 initialDelayString = "${runtime.participantParameters.heartBeatMs}")
152 public void schedule() {
153 }
154
155ConfigurationProperties
156+++++++++++++++++++++++
157@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**.
158
159.. code-block:: java
160
161 @Validated
162 @Getter
163 @Setter
164 @ConfigurationProperties(prefix = "runtime")
165 public class ClRuntimeParameterGroup {
166 @Min(100)
167 private long heartBeatMs;
168
169 @Valid
170 @Positive
171 private long reportingTimeIntervalMs;
172
173 @Valid
174 @NotNull
175 private ParticipantUpdateParameters updateParameters;
176
177 @NotBlank
178 private String description;
179 }
180
181In 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.
182
183The code below shown how to add TopicParameterGroup parameter into ClRuntimeParameterGroup:
184
185.. code-block:: java
186
187 @NotNull
188 @ParameterGroupConstraint
189 private TopicParameterGroup topicParameterGroup;
190
191
192A bean configured with ConfigurationProperties, is automatically a Spring component and could be injected into other Spring components. The code below shown an example:
193
194.. code-block:: java
195
196 @Component
197 @RequiredArgsConstructor
198 public class Example {
199
200 private ClRuntimeParameterGroup parameters;
201 ....
202
203 public void method() {
204 .....
205 long heartBeatMs = parameters.getHeartBeatMs();
206 .....
207 }
208
209The code shows below, is an example of Unit Test validation of the POJO ClRuntimeParameterGroup:
210
211.. code-block:: java
212
213 private ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
214
215 @Test
216 void testParameters_NullTopicParameterGroup() {
217 final ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup();
218 parameters.setTopicParameterGroup(null);
219 assertThat(validatorFactory.getValidator().validate(parameters)).isNotEmpty();
220 }