From 612c43517adedd53466d919fa3c9088b23ef4c7c Mon Sep 17 00:00:00 2001 From: FrancescoFioraEst Date: Tue, 3 Aug 2021 16:54:30 +0100 Subject: Handle Exceptions in Rest Control Loop Runtime POLICY-3462: Handle Exceptions in Rest Control Loop Runtime Change-Id: I586f6f6d85f9253cb2a29c70df38c49ca26c5852 Signed-off-by: FrancescoFioraEst --- .../commissioning/CommissioningProvider.java | 120 +++++++------ .../runtime/main/rest/CommissioningController.java | 197 +++++++-------------- .../runtime/main/rest/InstantiationController.java | 137 +++++--------- .../main/rest/MonitoringQueryController.java | 87 +++------ .../main/web/GlobalControllerExceptionHandler.java | 73 ++++++++ 5 files changed, 270 insertions(+), 344 deletions(-) create mode 100644 runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/GlobalControllerExceptionHandler.java (limited to 'runtime-controlloop/src') 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 getInitialNodeTypesMap( - Map fullNodeTypes, boolean common) { + private Map getInitialNodeTypesMap(Map fullNodeTypes, + boolean common) { var tempNodeTypesMap = new HashMap(); @@ -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 findCommonOrInstancePropsInNodeTypes( - ToscaNodeType nodeType, boolean common) { + private Map findCommonOrInstancePropsInNodeTypes(ToscaNodeType nodeType, boolean common) { var tempCommonPropertyMap = new HashMap(); var tempInstancePropertyMap = new HashMap(); @@ -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 getFinalNodeTypesMap( - Map initialNodeTypes, - Map filteredNodeTypes) { + private Map getFinalNodeTypesMap(Map initialNodeTypes, + Map 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( - 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 getCommonOrInstancePropertiesFromNodeTypes( - boolean common, String name, String version) - throws PfModelException { + private Map 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 getDerivedCommonOrInstanceNodeTemplates( - Map initialNodeTemplates, - Map nodeTypeProps) { + Map initialNodeTemplates, Map nodeTypeProps) { var finalNodeTemplatesMap = new HashMap(); @@ -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 getNodeTemplatesWithCommonOrInstanceProperties( - boolean common, String name, String version) throws PfModelException { + public Map 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 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> 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 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 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> 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> 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 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 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 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 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 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 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 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 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 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 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,21 +47,12 @@ 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. * @@ -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 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 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 handleBadRequest(PfModelException ex) { + var resp = new SimpleResponse(); + resp.setErrorDetails(ex.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(ex.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + +} -- cgit 1.2.3-korg