summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancescoFioraEst <francesco.fiora@est.tech>2021-08-03 16:54:30 +0100
committerFrancesco Fiora <francesco.fiora@est.tech>2021-08-05 12:26:45 +0000
commit612c43517adedd53466d919fa3c9088b23ef4c7c (patch)
tree5f22a2262b8902c846755090eeae1b6cbdf56d5a
parent055fa4ad38a11bb5890b6e0ea280e9b96a1b2a39 (diff)
Handle Exceptions in Rest Control Loop Runtime
POLICY-3462: Handle Exceptions in Rest Control Loop Runtime Change-Id: I586f6f6d85f9253cb2a29c70df38c49ca26c5852 Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java120
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java197
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java137
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java87
-rw-r--r--runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/GlobalControllerExceptionHandler.java73
5 files changed, 270 insertions, 344 deletions
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java
index 891d42072..e676cbe0e 100644
--- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java
@@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import javax.ws.rs.core.Response.Status;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
@@ -60,6 +61,7 @@ public class CommissioningProvider {
private final PolicyModelsProvider modelsProvider;
private final ControlLoopProvider clProvider;
+ private final ObjectMapper mapper = new ObjectMapper();
private static final Object lockit = new Object();
@@ -72,6 +74,7 @@ public class CommissioningProvider {
public CommissioningProvider(PolicyModelsProvider modelsProvider, ControlLoopProvider clProvider) {
this.modelsProvider = modelsProvider;
this.clProvider = clProvider;
+ mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
}
/**
@@ -189,8 +192,8 @@ public class CommissioningProvider {
* @return node types map that only has common properties
* @throws PfModelException on errors getting node type with common properties
*/
- private Map<String, ToscaNodeType> getInitialNodeTypesMap(
- Map<String, ToscaNodeType> fullNodeTypes, boolean common) {
+ private Map<String, ToscaNodeType> getInitialNodeTypesMap(Map<String, ToscaNodeType> fullNodeTypes,
+ boolean common) {
var tempNodeTypesMap = new HashMap<String, ToscaNodeType>();
@@ -198,8 +201,7 @@ public class CommissioningProvider {
var tempToscaNodeType = new ToscaNodeType();
tempToscaNodeType.setName(key);
- var resultantPropertyMap = findCommonOrInstancePropsInNodeTypes(
- nodeType, common);
+ var resultantPropertyMap = findCommonOrInstancePropsInNodeTypes(nodeType, common);
if (!resultantPropertyMap.isEmpty()) {
tempToscaNodeType.setProperties(resultantPropertyMap);
@@ -209,8 +211,7 @@ public class CommissioningProvider {
return tempNodeTypesMap;
}
- private Map<String, ToscaProperty> findCommonOrInstancePropsInNodeTypes(
- ToscaNodeType nodeType, boolean common) {
+ private Map<String, ToscaProperty> findCommonOrInstancePropsInNodeTypes(ToscaNodeType nodeType, boolean common) {
var tempCommonPropertyMap = new HashMap<String, ToscaProperty>();
var tempInstancePropertyMap = new HashMap<String, ToscaProperty>();
@@ -246,9 +247,8 @@ public class CommissioningProvider {
* @return all node types that have common properties including their children
* @throws PfModelException on errors getting node type with common properties
*/
- private Map<String, ToscaNodeType> getFinalNodeTypesMap(
- Map<String, ToscaNodeType> initialNodeTypes,
- Map<String, ToscaNodeType> filteredNodeTypes) {
+ private Map<String, ToscaNodeType> getFinalNodeTypesMap(Map<String, ToscaNodeType> initialNodeTypes,
+ Map<String, ToscaNodeType> filteredNodeTypes) {
for (var i = 0; i < initialNodeTypes.size(); i++) {
initialNodeTypes.forEach((key, nodeType) -> {
var tempToscaNodeType = new ToscaNodeType();
@@ -258,7 +258,7 @@ public class CommissioningProvider {
tempToscaNodeType.setName(key);
var finalProps = new HashMap<String, ToscaProperty>(
- filteredNodeTypes.get(nodeType.getDerivedFrom()).getProperties());
+ filteredNodeTypes.get(nodeType.getDerivedFrom()).getProperties());
tempToscaNodeType.setProperties(finalProps);
} else {
@@ -280,16 +280,15 @@ public class CommissioningProvider {
* @return the node types with common or instance properties
* @throws PfModelException on errors getting node type properties
*/
- private Map<String, ToscaNodeType> getCommonOrInstancePropertiesFromNodeTypes(
- boolean common, String name, String version)
- throws PfModelException {
+ private Map<String, ToscaNodeType> getCommonOrInstancePropertiesFromNodeTypes(boolean common, String name,
+ String version) throws PfModelException {
var serviceTemplates = new ToscaServiceTemplates();
serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version));
var tempNodeTypesMap =
- this.getInitialNodeTypesMap(serviceTemplates.getServiceTemplates().get(0).getNodeTypes(), common);
+ this.getInitialNodeTypesMap(serviceTemplates.getServiceTemplates().get(0).getNodeTypes(), common);
- return this.getFinalNodeTypesMap(
- serviceTemplates.getServiceTemplates().get(0).getNodeTypes(), tempNodeTypesMap);
+ return this.getFinalNodeTypesMap(serviceTemplates.getServiceTemplates().get(0).getNodeTypes(),
+ tempNodeTypesMap);
}
@@ -302,8 +301,7 @@ public class CommissioningProvider {
* @throws PfModelException on errors getting map of node templates with common or instance properties added
*/
private Map<String, ToscaNodeTemplate> getDerivedCommonOrInstanceNodeTemplates(
- Map<String, ToscaNodeTemplate> initialNodeTemplates,
- Map<String, ToscaNodeType> nodeTypeProps) {
+ Map<String, ToscaNodeTemplate> initialNodeTemplates, Map<String, ToscaNodeType> nodeTypeProps) {
var finalNodeTemplatesMap = new HashMap<String, ToscaNodeTemplate>();
@@ -332,18 +330,17 @@ public class CommissioningProvider {
* @return the nodes templates with common or instance properties
* @throws PfModelException on errors getting common or instance properties from node_templates
*/
- public Map<String, ToscaNodeTemplate> getNodeTemplatesWithCommonOrInstanceProperties(
- boolean common, String name, String version) throws PfModelException {
+ public Map<String, ToscaNodeTemplate> getNodeTemplatesWithCommonOrInstanceProperties(boolean common, String name,
+ String version) throws PfModelException {
- var commonOrInstanceNodeTypeProps =
- this.getCommonOrInstancePropertiesFromNodeTypes(common, name, version);
+ var commonOrInstanceNodeTypeProps = this.getCommonOrInstancePropertiesFromNodeTypes(common, name, version);
var serviceTemplates = new ToscaServiceTemplates();
serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version));
return this.getDerivedCommonOrInstanceNodeTemplates(
- serviceTemplates.getServiceTemplates().get(0).getToscaTopologyTemplate().getNodeTemplates(),
- commonOrInstanceNodeTypeProps);
+ serviceTemplates.getServiceTemplates().get(0).getToscaTopologyTemplate().getNodeTemplates(),
+ commonOrInstanceNodeTypeProps);
}
/**
@@ -368,7 +365,7 @@ public class CommissioningProvider {
* @return the tosca service template
* @throws PfModelException on errors getting tosca service template
*/
- public Map<String, Object> getToscaServiceTemplateReduced(String name, String version) throws PfModelException {
+ public String getToscaServiceTemplateReduced(String name, String version) throws PfModelException {
var serviceTemplates = new ToscaServiceTemplates();
serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version));
@@ -381,7 +378,12 @@ public class CommissioningProvider {
template.put("node_types", fullTemplate.getNodeTypes());
template.put("topology_template", fullTemplate.getToscaTopologyTemplate());
- return template;
+ try {
+ return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(template);
+
+ } catch (JsonProcessingException e) {
+ throw new PfModelException(Status.BAD_REQUEST, "Converion to Json Schema failed", e);
+ }
}
/**
@@ -390,41 +392,43 @@ public class CommissioningProvider {
* @param section section of the tosca service template to get schema for
* @return the specified tosca service template or section Json Schema
* @throws PfModelException on errors with retrieving the classes
- * @throws JsonProcessingException on errors generating the schema
*/
- public String getToscaServiceTemplateSchema(String section) throws PfModelException, JsonProcessingException {
- var mapper = new ObjectMapper();
- mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
+ public String getToscaServiceTemplateSchema(String section) throws PfModelException {
var visitor = new SchemaFactoryWrapper();
- switch (section) {
- case "data_types":
- mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaDataType.class), visitor);
- break;
- case "capability_types":
- mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaCapabilityType.class), visitor);
- break;
- case "node_types":
- mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeType.class), visitor);
- break;
- case "relationship_types":
- mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaRelationshipType.class), visitor);
- break;
- case "policy_types":
- mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaPolicyType.class), visitor);
- break;
- case "topology_template":
- mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaTopologyTemplate.class), visitor);
- break;
- case "node_templates":
- mapper.acceptJsonFormatVisitor(mapper.getTypeFactory()
- .constructCollectionType(List.class, ToscaNodeTemplate.class), visitor);
- break;
- default:
- mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaServiceTemplate.class), visitor);
- }
+ try {
+ switch (section) {
+ case "data_types":
+ mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaDataType.class), visitor);
+ break;
+ case "capability_types":
+ mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaCapabilityType.class), visitor);
+ break;
+ case "node_types":
+ mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeType.class), visitor);
+ break;
+ case "relationship_types":
+ mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaRelationshipType.class), visitor);
+ break;
+ case "policy_types":
+ mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaPolicyType.class), visitor);
+ break;
+ case "topology_template":
+ mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaTopologyTemplate.class), visitor);
+ break;
+ case "node_templates":
+ mapper.acceptJsonFormatVisitor(
+ mapper.getTypeFactory().constructCollectionType(List.class, ToscaNodeTemplate.class),
+ visitor);
+ break;
+ default:
+ mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaServiceTemplate.class), visitor);
+ }
- var jsonSchema = visitor.finalSchema();
- return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema);
+ var jsonSchema = visitor.finalSchema();
+ return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema);
+ } catch (JsonProcessingException e) {
+ throw new PfModelException(Status.BAD_REQUEST, "Converion to Json Schema failed", e);
+ }
}
}
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java
index 8fe3c0c88..ec7f14d8b 100644
--- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java
@@ -20,9 +20,6 @@
package org.onap.policy.clamp.controlloop.runtime.main.rest;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
@@ -32,18 +29,16 @@ import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.ResponseHeader;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import javax.ws.rs.core.Response.Status;
+import lombok.RequiredArgsConstructor;
import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse;
import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController;
import org.onap.policy.models.base.PfModelException;
-import org.onap.policy.models.base.PfModelRuntimeException;
import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -58,29 +53,20 @@ import org.springframework.web.bind.annotation.RestController;
* Class to provide REST end points for creating, deleting, querying commissioned control loops.
*/
@RestController
+@RequiredArgsConstructor
public class CommissioningController extends AbstractRestController {
- private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class);
-
private static final String TAGS = "Clamp Control Loop Commissioning API";
private final CommissioningProvider provider;
/**
- * Create Commissioning Controller.
- *
- * @param provider the CommissioningProvider
- */
- public CommissioningController(CommissioningProvider provider) {
- this.provider = provider;
- }
-
- /**
* Creates a control loop definition.
*
* @param requestId request ID used in ONAP logging
* @param body the body of control loop following TOSCA definition
* @return a response
+ * @throws PfModelException on errors creating a control loop definition
*/
// @formatter:off
@PostMapping(value = "/commission",
@@ -133,17 +119,10 @@ public class CommissioningController extends AbstractRestController {
@RequestHeader(
name = REQUEST_ID_NAME,
required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ToscaServiceTemplate body) {
- try {
- return ResponseEntity.ok().body(provider.createControlLoopDefinitions(body));
-
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("Commissioning of the control loops failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
- }
+ @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ToscaServiceTemplate body)
+ throws PfModelException {
+ return ResponseEntity.ok().body(provider.createControlLoopDefinitions(body));
}
/**
@@ -153,6 +132,7 @@ public class CommissioningController extends AbstractRestController {
* @param name the name of the control loop definition to delete
* @param version the version of the control loop definition to delete
* @return a response
+ * @throws PfModelException on errors deleting a control loop definition
*/
// @formatter:off
@DeleteMapping(value = "/commission",
@@ -206,18 +186,10 @@ public class CommissioningController extends AbstractRestController {
value = "name") String name,
@ApiParam(
value = "Control Loop definition version",
- required = true) @RequestParam("version") String version) {
-
- try {
- return ResponseEntity.ok().body(provider.deleteControlLoopDefinition(name, version));
-
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("Decommisssioning of control loop failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
- }
+ required = true) @RequestParam("version") String version)
+ throws PfModelException {
+ return ResponseEntity.ok().body(provider.deleteControlLoopDefinition(name, version));
}
/**
@@ -227,6 +199,7 @@ public class CommissioningController extends AbstractRestController {
* @param name the name of the control loop definition to get, null for all definitions
* @param version the version of the control loop definition to get, null for all definitions
* @return the control loop definitions
+ * @throws PfModelException on errors getting details of all or specific control loop definitions
*/
// @formatter:off
@GetMapping(value = "/commission",
@@ -266,7 +239,7 @@ public class CommissioningController extends AbstractRestController {
}
)
// @formatter:on
- public ResponseEntity<?> query(
+ public ResponseEntity<List<ToscaNodeTemplate>> query(
@RequestHeader(
name = REQUEST_ID_NAME,
required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
@@ -275,18 +248,10 @@ public class CommissioningController extends AbstractRestController {
required = false) String name,
@ApiParam(value = "Control Loop definition version", required = false) @RequestParam(
value = "version",
- required = false) String version) {
-
- try {
- return ResponseEntity.ok().body(provider.getControlLoopDefinitions(name, version));
-
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("Get of control loop definitions failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
- }
+ required = false) String version)
+ throws PfModelException {
+ return ResponseEntity.ok().body(provider.getControlLoopDefinitions(name, version));
}
/**
@@ -296,6 +261,7 @@ public class CommissioningController extends AbstractRestController {
* @param name the name of the tosca service template to retrieve
* @param version the version of the tosca service template to get
* @return the specified tosca service template
+ * @throws PfModelException on errors getting the Tosca Service Template
*/
// @formatter:off
@GetMapping(value = "/commission/toscaservicetemplate",
@@ -335,36 +301,19 @@ public class CommissioningController extends AbstractRestController {
}
)
// @formatter:on
- public ResponseEntity<?> queryToscaServiceTemplate(
+ public ResponseEntity<String> queryToscaServiceTemplate(
@RequestHeader(
name = REQUEST_ID_NAME,
required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
@ApiParam(value = "Tosca service template name", required = false) @RequestParam(
value = "name",
required = false) String name,
- @ApiParam(value = "Tosca service template version", required = true) @RequestParam(
+ @ApiParam(value = "Tosca service template version", required = false) @RequestParam(
value = "version",
- required = false) String version) {
-
- try {
- var mapper = new ObjectMapper();
- mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
- var response = mapper.writerWithDefaultPrettyPrinter()
- .writeValueAsString(provider.getToscaServiceTemplateReduced(name, version));
+ required = false) String version)
+ throws PfModelException {
- return ResponseEntity.ok().body(response);
-
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("Get of tosca service template failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
- } catch (JsonProcessingException e) {
- LOGGER.warn("Get of tosca service template failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getMessage());
- return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp);
- }
+ return ResponseEntity.ok().body(provider.getToscaServiceTemplateReduced(name, version));
}
/**
@@ -373,6 +322,7 @@ public class CommissioningController extends AbstractRestController {
* @param requestId request ID used in ONAP logging
* @param section section of the tosca service template to get schema for
* @return the specified tosca service template or section Json Schema
+ * @throws PfModelException on errros getting the Json Schema for the specified Tosca Service Template
*/
// @formatter:off
@GetMapping(value = "/commission/toscaServiceTemplateSchema",
@@ -412,27 +362,17 @@ public class CommissioningController extends AbstractRestController {
}
)
// @formatter:on
- public ResponseEntity<?> queryToscaServiceTemplateJsonSchema(
- @RequestHeader(
- name = REQUEST_ID_NAME,
- required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "Section of Template schema is desired for", required = false) @RequestParam(
- value = "section",
- required = false, defaultValue = "all") String section) {
- try {
- return ResponseEntity.ok().body(provider.getToscaServiceTemplateSchema(section));
+ public ResponseEntity<String> queryToscaServiceTemplateJsonSchema(
+ @RequestHeader(
+ name = REQUEST_ID_NAME,
+ required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Section of Template schema is desired for", required = false) @RequestParam(
+ value = "section",
+ required = false,
+ defaultValue = "all") String section)
+ throws PfModelException {
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("Get of tosca service template json schema failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
- } catch (JsonProcessingException e) {
- LOGGER.warn("Get of tosca service template json schema failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getMessage());
- return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp);
- }
+ return ResponseEntity.ok().body(provider.getToscaServiceTemplateSchema(section));
}
/**
@@ -443,6 +383,7 @@ public class CommissioningController extends AbstractRestController {
* @param name the name of the tosca service template to retrieve
* @param version the version of the tosca service template to get
* @return the specified tosca service template or section Json Schema
+ * @throws PfModelException on errors getting the Common or Instance Properties
*/
// @formatter:off
@GetMapping(value = "/commission/getCommonOrInstanceProperties",
@@ -482,30 +423,23 @@ public class CommissioningController extends AbstractRestController {
}
)
// @formatter:on
- public ResponseEntity<?> queryToscaServiceCommonOrInstanceProperties(
- @RequestHeader(
- name = REQUEST_ID_NAME,
- required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "Flag, true for common properties, false for instance", required = false) @RequestParam(
- value = "common",
- defaultValue = "false",
- required = false) boolean common,
- @ApiParam(value = "Tosca service template name", required = false) @RequestParam(
- value = "name",
- required = false) String name,
- @ApiParam(value = "Tosca service template version", required = true) @RequestParam(
- value = "version",
- required = false) String version) {
- try {
- return ResponseEntity.ok().body(provider.getNodeTemplatesWithCommonOrInstanceProperties(
- common, name, version));
+ public ResponseEntity<Map<String, ToscaNodeTemplate>> queryToscaServiceCommonOrInstanceProperties(
+ @RequestHeader(
+ name = REQUEST_ID_NAME,
+ required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Flag, true for common properties, false for instance", required = false) @RequestParam(
+ value = "common",
+ defaultValue = "false",
+ required = false) boolean common,
+ @ApiParam(value = "Tosca service template name", required = false) @RequestParam(
+ value = "name",
+ required = false) String name,
+ @ApiParam(value = "Tosca service template version", required = false) @RequestParam(
+ value = "version",
+ required = false) String version)
+ throws PfModelException {
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("Get of common or instance properties failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
- }
+ return ResponseEntity.ok().body(provider.getNodeTemplatesWithCommonOrInstanceProperties(common, name, version));
}
/**
@@ -515,6 +449,7 @@ public class CommissioningController extends AbstractRestController {
* @param name the name of the control loop definition to get
* @param version the version of the control loop definition to get
* @return the control loop element definitions
+ * @throws PfModelException on errors getting the elements of a specific control loop
*/
// @formatter:off
@GetMapping(value = "/commission/elements",
@@ -554,35 +489,25 @@ public class CommissioningController extends AbstractRestController {
}
)
// @formatter:on
- public ResponseEntity<?> queryElements(
+ public ResponseEntity<List<ToscaNodeTemplate>> queryElements(
@RequestHeader(
name = REQUEST_ID_NAME,
required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
@ApiParam(value = "Control Loop definition name", required = false) @RequestParam(
value = "name",
required = false) String name,
- @ApiParam(value = "Control Loop definition version", required = true) @RequestParam(
+ @ApiParam(value = "Control Loop definition version", required = false) @RequestParam(
value = "version",
- required = false) String version) {
-
- try {
- List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
- // Prevent ambiguous queries with multiple returns
- if (nodeTemplate.size() > 1) {
- var resp = new CommissioningResponse();
- resp.setErrorDetails("Multiple ControlLoops are not supported");
- return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(resp);
- }
-
- List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
- return ResponseEntity.ok().body(response);
+ required = false) String version)
+ throws PfModelException {
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("Get of control loop element definitions failed", e);
- var resp = new CommissioningResponse();
- resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
+ List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
+ // Prevent ambiguous queries with multiple returns
+ if (nodeTemplate.size() > 1) {
+ throw new PfModelException(Status.NOT_ACCEPTABLE, "Multiple ControlLoops are not supported");
}
+ List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
+ return ResponseEntity.ok().body(response);
}
}
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java
index 5a320e8dc..29919f528 100644
--- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java
@@ -29,6 +29,7 @@ import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.ResponseHeader;
import java.util.UUID;
+import lombok.RequiredArgsConstructor;
import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops;
import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand;
@@ -36,10 +37,6 @@ import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.Inst
import org.onap.policy.clamp.controlloop.runtime.instantiation.ControlLoopInstantiationProvider;
import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController;
import org.onap.policy.models.base.PfModelException;
-import org.onap.policy.models.base.PfModelRuntimeException;
-import org.onap.policy.models.errors.concepts.ErrorResponseInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
@@ -55,30 +52,21 @@ import org.springframework.web.bind.annotation.RestController;
* Class to provide REST end points for creating, deleting, query and commanding a control loop definition.
*/
@RestController
+@RequiredArgsConstructor
public class InstantiationController extends AbstractRestController {
- private static final Logger LOGGER = LoggerFactory.getLogger(InstantiationController.class);
-
private static final String TAGS = "Clamp Control Loop Instantiation API";
// The CL provider for instantiation requests
private final ControlLoopInstantiationProvider provider;
/**
- * Create Instantiation Controller.
- *
- * @param provider the ControlLoopInstantiationProvider
- */
- public InstantiationController(ControlLoopInstantiationProvider provider) {
- this.provider = provider;
- }
-
- /**
* Creates a control loop.
*
* @param requestId request ID used in ONAP logging
* @param controlLoops the control loops
* @return a response
+ * @throws PfModelException on errors creating a control loop
*/
// @formatter:off
@PostMapping(value = "/instantiation",
@@ -128,18 +116,13 @@ public class InstantiationController extends AbstractRestController {
)
// @formatter:on
public ResponseEntity<InstantiationResponse> create(
- @RequestHeader(name = REQUEST_ID_NAME, required = false)
- @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "Entity Body of Control Loop", required = true)
- @RequestBody ControlLoops controlLoops) {
-
- try {
- return ResponseEntity.ok().body(provider.createControlLoops(controlLoops));
+ @RequestHeader(
+ name = REQUEST_ID_NAME,
+ required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ControlLoops controlLoops)
+ throws PfModelException {
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("creation of control loop failed", e);
- return createInstantiationErrorResponse(e);
- }
+ return ResponseEntity.ok().body(provider.createControlLoops(controlLoops));
}
/**
@@ -149,6 +132,7 @@ public class InstantiationController extends AbstractRestController {
* @param name the name of the control loop to get, null for all control loops
* @param version the version of the control loop to get, null for all control loops
* @return the control loops
+ * @throws PfModelException on errors getting commissioning of control loop
*/
// @formatter:off
@GetMapping(value = "/instantiation",
@@ -187,22 +171,19 @@ public class InstantiationController extends AbstractRestController {
}
)
// @formatter:on
- public ResponseEntity<?> query(
- @RequestHeader(name = REQUEST_ID_NAME, required = false)
- @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "Control Loop definition name", required = false)
- @RequestParam(value = "name", required = false) String name,
- @ApiParam(value = "Control Loop definition version", required = false)
- @RequestParam(value = "version", required = false) String version) {
-
- try {
- return ResponseEntity.ok().body(provider.getControlLoops(name, version));
-
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("commisssioning of control loop failed", e);
- return createInstantiationErrorResponse(e);
- }
+ public ResponseEntity<ControlLoops> query(
+ @RequestHeader(
+ name = REQUEST_ID_NAME,
+ required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Control Loop definition name", required = false) @RequestParam(
+ value = "name",
+ required = false) String name,
+ @ApiParam(value = "Control Loop definition version", required = false) @RequestParam(
+ value = "version",
+ required = false) String version)
+ throws PfModelException {
+ return ResponseEntity.ok().body(provider.getControlLoops(name, version));
}
/**
@@ -211,6 +192,7 @@ public class InstantiationController extends AbstractRestController {
* @param requestId request ID used in ONAP logging
* @param controlLoops the control loops
* @return a response
+ * @throws PfModelException on errors updating of control loops
*/
// @formatter:off
@PutMapping(value = "/instantiation",
@@ -260,18 +242,13 @@ public class InstantiationController extends AbstractRestController {
)
// @formatter:on
public ResponseEntity<InstantiationResponse> update(
- @RequestHeader(name = REQUEST_ID_NAME, required = false)
- @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "Entity Body of Control Loop", required = true)
- @RequestBody ControlLoops controlLoops) {
-
- try {
- return ResponseEntity.ok().body(provider.updateControlLoops(controlLoops));
+ @RequestHeader(
+ name = REQUEST_ID_NAME,
+ required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ControlLoops controlLoops)
+ throws PfModelException {
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("update of control loops failed", e);
- return createInstantiationErrorResponse(e);
- }
+ return ResponseEntity.ok().body(provider.updateControlLoops(controlLoops));
}
/**
@@ -281,6 +258,7 @@ public class InstantiationController extends AbstractRestController {
* @param name the name of the control loop to delete
* @param version the version of the control loop to delete
* @return a response
+ * @throws PfModelException on errors deleting of control loop
*/
// @formatter:off
@DeleteMapping(value = "/instantiation",
@@ -328,20 +306,16 @@ public class InstantiationController extends AbstractRestController {
// @formatter:on
public ResponseEntity<InstantiationResponse> delete(
- @RequestHeader(name = REQUEST_ID_NAME, required = false)
- @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "Control Loop definition name", required = true)
- @RequestParam("name") String name,
- @ApiParam(value = "Control Loop definition version")
- @RequestParam(value = "version", required = false) String version) {
-
- try {
- return ResponseEntity.ok().body(provider.deleteControlLoop(name, version));
+ @RequestHeader(
+ name = REQUEST_ID_NAME,
+ required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Control Loop definition name", required = true) @RequestParam("name") String name,
+ @ApiParam(value = "Control Loop definition version") @RequestParam(
+ value = "version",
+ required = false) String version)
+ throws PfModelException {
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("delete of control loop failed", e);
- return createInstantiationErrorResponse(e);
- }
+ return ResponseEntity.ok().body(provider.deleteControlLoop(name, version));
}
/**
@@ -350,6 +324,8 @@ public class InstantiationController extends AbstractRestController {
* @param requestId request ID used in ONAP logging
* @param command the command to issue to control loops
* @return the control loop definitions
+ * @throws PfModelException on errors issuing a command
+ * @throws ControlLoopException on errors issuing a command
*/
// @formatter:off
@PutMapping(value = "/instantiation/command",
@@ -390,29 +366,14 @@ public class InstantiationController extends AbstractRestController {
)
// @formatter:on
public ResponseEntity<InstantiationResponse> issueControlLoopCommand(
- @RequestHeader(name = REQUEST_ID_NAME, required = false)
- @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
- @ApiParam(value = "Entity Body of control loop command", required = true)
- @RequestBody InstantiationCommand command) {
-
- try {
- return ResponseEntity.accepted().body(provider.issueControlLoopCommand(command));
-
- } catch (PfModelRuntimeException | PfModelException | ControlLoopException e) {
- LOGGER.warn("creation of control loop failed", e);
- return createInstantiationErrorResponse(e);
- }
- }
+ @RequestHeader(
+ name = REQUEST_ID_NAME,
+ required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(
+ value = "Entity Body of control loop command",
+ required = true) @RequestBody InstantiationCommand command)
+ throws ControlLoopException, PfModelException {
- /**
- * create a Instantiation Response from an exception.
- *
- * @param e the error
- * @return the Instantiation Response
- */
- private ResponseEntity<InstantiationResponse> createInstantiationErrorResponse(ErrorResponseInfo e) {
- var resp = new InstantiationResponse();
- resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
+ return ResponseEntity.accepted().body(provider.issueControlLoopCommand(command));
}
}
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java
index 7ac95003e..c4ce5bb05 100644
--- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java
@@ -30,14 +30,12 @@ import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.ResponseHeader;
import java.time.Instant;
import java.util.UUID;
+import lombok.RequiredArgsConstructor;
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList;
import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatisticsList;
import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController;
import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider;
import org.onap.policy.models.base.PfModelException;
-import org.onap.policy.models.base.PfModelRuntimeException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
@@ -49,22 +47,13 @@ import org.springframework.web.bind.annotation.RestController;
* This class handles REST endpoints for CL Statistics monitoring.
*/
@RestController
+@RequiredArgsConstructor
public class MonitoringQueryController extends AbstractRestController {
- private static final Logger LOGGER = LoggerFactory.getLogger(MonitoringQueryController.class);
private static final String TAGS = "Clamp Control Loop Monitoring API";
private final MonitoringProvider provider;
/**
- * Create Monitoring Controller.
- *
- * @param provider the MonitoringProvider
- */
- public MonitoringQueryController(MonitoringProvider provider) {
- this.provider = provider;
- }
-
- /**
* Queries details of control loop participants statistics.
*
* @param requestId request ID used in ONAP logging
@@ -133,24 +122,17 @@ public class MonitoringQueryController extends AbstractRestController {
value = "endTime",
required = false) final String endTime) {
- try {
- Instant startTimestamp = null;
- Instant endTimestamp = null;
+ Instant startTimestamp = null;
+ Instant endTimestamp = null;
- if (startTime != null) {
- startTimestamp = Instant.parse(startTime);
- }
- if (endTime != null) {
- endTimestamp = Instant.parse(endTime);
- }
- return ResponseEntity.ok().body(provider.fetchFilteredParticipantStatistics(name, version, recordCount,
- startTimestamp, endTimestamp));
-
- } catch (PfModelRuntimeException e) {
- LOGGER.warn("Monitoring of participants statistics failed", e);
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build();
+ if (startTime != null) {
+ startTimestamp = Instant.parse(startTime);
}
-
+ if (endTime != null) {
+ endTimestamp = Instant.parse(endTime);
+ }
+ return ResponseEntity.ok().body(
+ provider.fetchFilteredParticipantStatistics(name, version, recordCount, startTimestamp, endTimestamp));
}
/**
@@ -208,14 +190,7 @@ public class MonitoringQueryController extends AbstractRestController {
value = "version",
required = false) final String version) {
- try {
- return ResponseEntity.ok().body(provider.fetchParticipantStatsPerControlLoop(name, version));
-
- } catch (PfModelRuntimeException e) {
- LOGGER.warn("Monitoring of Cl participant statistics failed", e);
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build();
- }
-
+ return ResponseEntity.ok().body(provider.fetchParticipantStatsPerControlLoop(name, version));
}
/**
@@ -273,14 +248,7 @@ public class MonitoringQueryController extends AbstractRestController {
value = "version",
required = false) final String version) {
- try {
- return ResponseEntity.ok().body(provider.fetchClElementStatsPerControlLoop(name, version));
-
- } catch (PfModelRuntimeException e) {
- LOGGER.warn("Monitoring of Cl Element statistics failed", e);
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build();
- }
-
+ return ResponseEntity.ok().body(provider.fetchClElementStatsPerControlLoop(name, version));
}
/**
@@ -294,6 +262,7 @@ public class MonitoringQueryController extends AbstractRestController {
* @param startTime the time from which to get statistics
* @param endTime the time to which to get statistics
* @return the control loop element statistics
+ * @throws PfModelException on errors getting details of all control loop element statistics per control loop
*/
// @formatter:off
@GetMapping(value = "/monitoring/clelement",
@@ -353,26 +322,20 @@ public class MonitoringQueryController extends AbstractRestController {
required = false) final String startTime,
@ApiParam(value = "end time", required = false) @RequestParam(
value = "endTime",
- required = false) final String endTime) {
-
- try {
- Instant startTimestamp = null;
- Instant endTimestamp = null;
+ required = false) final String endTime)
+ throws PfModelException {
- if (startTime != null) {
- startTimestamp = Instant.parse(startTime);
- }
- if (endTime != null) {
- endTimestamp = Instant.parse(endTime);
- }
- return ResponseEntity.ok().body(provider.fetchFilteredClElementStatistics(name, version, id, startTimestamp,
- endTimestamp, recordCount));
+ Instant startTimestamp = null;
+ Instant endTimestamp = null;
- } catch (PfModelRuntimeException | PfModelException e) {
- LOGGER.warn("Monitoring of Cl Element statistics failed", e);
- return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build();
+ if (startTime != null) {
+ startTimestamp = Instant.parse(startTime);
}
-
+ if (endTime != null) {
+ endTimestamp = Instant.parse(endTime);
+ }
+ return ResponseEntity.ok().body(provider.fetchFilteredClElementStatistics(name, version, id, startTimestamp,
+ endTimestamp, recordCount));
}
}
diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/GlobalControllerExceptionHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/GlobalControllerExceptionHandler.java
new file mode 100644
index 000000000..d093c677f
--- /dev/null
+++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/GlobalControllerExceptionHandler.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.main.web;
+
+import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException;
+import org.onap.policy.clamp.controlloop.models.messages.rest.SimpleResponse;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+public class GlobalControllerExceptionHandler {
+
+ /**
+ * Handle ControlLoopException.
+ *
+ * @param ex ControlLoopException
+ * @return ResponseEntity
+ */
+ @ExceptionHandler(ControlLoopException.class)
+ public ResponseEntity<SimpleResponse> handleBadRequest(ControlLoopException ex) {
+ var resp = new SimpleResponse();
+ resp.setErrorDetails(ex.getErrorResponse().getErrorMessage());
+ return ResponseEntity.status(ex.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
+ }
+
+ /**
+ * Handle PfModelRuntimeException.
+ *
+ * @param ex PfModelRuntimeException
+ * @return ResponseEntity
+ */
+ @ExceptionHandler(PfModelRuntimeException.class)
+ public ResponseEntity<SimpleResponse> handleBadRequest(PfModelRuntimeException ex) {
+ var resp = new SimpleResponse();
+ resp.setErrorDetails(ex.getErrorResponse().getErrorMessage());
+ return ResponseEntity.status(ex.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
+ }
+
+ /**
+ * Handle PfModelException.
+ *
+ * @param ex PfModelException
+ * @return ResponseEntity
+ */
+ @ExceptionHandler(PfModelException.class)
+ public ResponseEntity<SimpleResponse> handleBadRequest(PfModelException ex) {
+ var resp = new SimpleResponse();
+ resp.setErrorDetails(ex.getErrorResponse().getErrorMessage());
+ return ResponseEntity.status(ex.getErrorResponse().getResponseCode().getStatusCode()).body(resp);
+ }
+
+}