From a61cc1320020b05568d4e47a1a776b8c796ae48f Mon Sep 17 00:00:00 2001 From: Sven Strittmatter Date: Fri, 16 Feb 2024 16:14:08 +0100 Subject: [PATCH] #121 Remove Checked Exception to Provide a Cleaner API Checked exceptions in a public used API is quite cumbersome. Alo checked exceptions should onlybe used forerrors you can deal with in the source code. Since the errors in this case origin from outside, it is better to use runtime exceptions. This does not clutter the API clients. Signed-off-by: Sven Strittmatter --- .../defectdojo/service/EndpointService.java | 11 +++++-- .../defectdojo/service/EngagementService.java | 11 +++++-- .../defectdojo/service/FindingService.java | 11 +++++-- .../service/GenericDefectDojoService.java | 30 +++++++++++-------- .../service/GroupMemberService.java | 11 +++++-- .../defectdojo/service/GroupService.java | 11 +++++-- .../service/ProductGroupService.java | 11 +++++-- .../defectdojo/service/ProductService.java | 11 +++++-- .../service/ProductTypeService.java | 11 +++++-- .../defectdojo/service/TestService.java | 11 +++++-- .../defectdojo/service/TestTypeService.java | 11 +++++-- .../defectdojo/service/ToolConfigService.java | 11 +++++-- .../defectdojo/service/ToolTypeService.java | 11 +++++-- .../service/UserProfileService.java | 12 ++++++-- .../defectdojo/service/UserService.java | 11 +++++-- 15 files changed, 131 insertions(+), 54 deletions(-) diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/EndpointService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/EndpointService.java index eef68497..cfbe5e3f 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/EndpointService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/EndpointService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.Endpoint; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/EngagementService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/EngagementService.java index 07976423..b5926926 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/EngagementService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/EngagementService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.Engagement; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java index 7a339a4f..2e5ef21c 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.Finding; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; @@ -30,9 +31,13 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } public List getUnhandledFindingsForProduct(long productId, Finding.Severity minimumSeverity) throws URISyntaxException, JsonProcessingException { diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java index 23a71956..14a12f3e 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java @@ -5,12 +5,12 @@ package io.securecodebox.persistence.defectdojo.service; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.cfg.CoercionAction; import com.fasterxml.jackson.databind.cfg.CoercionInputShape; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.exception.TooManyResponsesException; import io.securecodebox.persistence.defectdojo.http.Foo; import io.securecodebox.persistence.defectdojo.http.ProxyConfigFactory; @@ -35,7 +35,6 @@ import java.util.*; // FIXME: Should be package private bc implementation detail. -// TODO: Remove JsonProcessingException, URISyntaxException from public API and use a own runtime exception type bc these checked exceptions clutter the client coe. public abstract class GenericDefectDojoService { private static final String API_PREFIX = "/api/v2/"; private static final long DEFECT_DOJO_OBJET_LIMIT = 100L; @@ -88,7 +87,7 @@ private RestTemplate setupRestTemplate() { protected abstract Class getModelClass(); - protected abstract PaginatedResult deserializeList(String response) throws JsonProcessingException; + protected abstract PaginatedResult deserializeList(String response); public T get(long id) { var restTemplate = this.getRestTemplate(); @@ -104,7 +103,7 @@ public T get(long id) { return response.getBody(); } - protected PaginatedResult internalSearch(Map queryParams, long limit, long offset) throws JsonProcessingException, URISyntaxException { + protected PaginatedResult internalSearch(Map queryParams, long limit, long offset) { var restTemplate = this.getRestTemplate(); HttpEntity payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders()); @@ -118,11 +117,18 @@ protected PaginatedResult internalSearch(Map queryParams, lon multiValueMap.set(entry.getKey(), String.valueOf(entry.getValue())); } - var url = new URI(this.config.getUrl() + API_PREFIX + this.getUrlPath() + "/"); - var uriBuilder = UriComponentsBuilder.fromUri(url).queryParams(multiValueMap); + final var url = this.config.getUrl() + API_PREFIX + this.getUrlPath() + "/"; + final UriComponentsBuilder builder; + try { + builder = UriComponentsBuilder + .fromUri(new URI(url)) + .queryParams(multiValueMap); + } catch (URISyntaxException e) { + throw new PersistenceException("Bad URL given: " + url, e); + } - ResponseEntity responseString = restTemplate.exchange( - uriBuilder.build(mutableQueryParams), + final ResponseEntity responseString = restTemplate.exchange( + builder.build(mutableQueryParams), HttpMethod.GET, payload, String.class @@ -131,7 +137,7 @@ protected PaginatedResult internalSearch(Map queryParams, lon return deserializeList(responseString.getBody()); } - public List search(Map queryParams) throws URISyntaxException, JsonProcessingException { + public List search(Map queryParams) { List objects = new LinkedList<>(); boolean hasNext; @@ -149,12 +155,12 @@ public List search(Map queryParams) throws URISyntaxException return objects; } - public List search() throws URISyntaxException, JsonProcessingException { + public List search() { return search(new LinkedHashMap<>()); } @SuppressWarnings("unchecked") - public Optional searchUnique(T searchObject) throws URISyntaxException, JsonProcessingException { + public Optional searchUnique(T searchObject) { Map queryParams = searchStringMapper.convertValue(searchObject, Map.class); var objects = search(queryParams); @@ -164,7 +170,7 @@ public Optional searchUnique(T searchObject) throws URISyntaxException, JsonP .findFirst(); } - public Optional searchUnique(Map queryParams) throws URISyntaxException, JsonProcessingException { + public Optional searchUnique(Map queryParams) { var objects = search(queryParams); return objects.stream() diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupMemberService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupMemberService.java index 10ba6495..77b2f7b1 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupMemberService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupMemberService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.GroupMember; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupService.java index ca5fa92e..629aeace 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.Group; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductGroupService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductGroupService.java index 4b57db78..ff6a9fe8 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductGroupService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductGroupService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.ProductGroup; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductService.java index 0aae2f2b..6d159b94 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.Product; @@ -27,8 +28,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductTypeService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductTypeService.java index 0039a92a..530eb134 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductTypeService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductTypeService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.ProductType; @@ -27,8 +28,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/TestService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/TestService.java index d2ca576d..4c0af509 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/TestService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/TestService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.Test; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/TestTypeService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/TestTypeService.java index ec2b1c4a..42349f22 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/TestTypeService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/TestTypeService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.TestType; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolConfigService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolConfigService.java index 27894660..450f06b3 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolConfigService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolConfigService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.ToolConfig; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolTypeService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolTypeService.java index 24ff54a2..03f71b95 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolTypeService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolTypeService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.ToolType; @@ -31,8 +32,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/UserProfileService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/UserProfileService.java index 0083dd55..b5b0608a 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/UserProfileService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/UserProfileService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.UserProfile; @@ -29,13 +30,18 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) { /* GenericDefectDojoService expects that the response from the defectdojo api is a list. * This endpoint returns a single object though, to not break the code this response * gets converted to a defectdojo response. */ - final var userProfile = this.objectMapper.readValue(response, new TypeReference() { - }); + final UserProfile userProfile; + try { + userProfile = this.objectMapper.readValue(response, new TypeReference() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } final var result = new PaginatedResult(); result.setResults(List.of(userProfile)); result.setCount(1); diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/UserService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/UserService.java index d9c619e7..62dc4f43 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/UserService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/UserService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; +import io.securecodebox.persistence.defectdojo.exception.PersistenceException; import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.User; @@ -26,8 +27,12 @@ protected Class getModelClass() { } @Override - protected PaginatedResult deserializeList(String response) throws JsonProcessingException { - return this.objectMapper.readValue(response, new TypeReference<>() { - }); + protected PaginatedResult deserializeList(String response) { + try { + return this.objectMapper.readValue(response, new TypeReference<>() { + }); + } catch (JsonProcessingException e) { + throw new PersistenceException("Can't process JSON response!", e); + } } }