Skip to content

Commit

Permalink
secureCodeBox#121 Remove Checked Exception to Provide a Cleaner API
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Weltraumschaf committed Mar 5, 2024
1 parent 59bbda4 commit 492bdf9
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,8 +27,12 @@ protected Class<Endpoint> getModelClass() {
}

@Override
protected PaginatedResult<Endpoint> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<Endpoint> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,8 +27,12 @@ protected Class<Engagement> getModelClass() {
}

@Override
protected PaginatedResult<Engagement> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<Engagement> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
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;

import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;

Expand All @@ -30,12 +30,16 @@ protected Class<Finding> getModelClass() {
}

@Override
protected PaginatedResult<Finding> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<Finding> 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<Finding> getUnhandledFindingsForProduct(long productId, Finding.Severity minimumSeverity) throws URISyntaxException, JsonProcessingException {
public List<Finding> getUnhandledFindingsForProduct(long productId, Finding.Severity minimumSeverity) {
final Map<String, Object> queryParams = Map.of(
"test__engagement__product", Long.toString(productId),
"active", Boolean.toString(true));
Expand All @@ -46,7 +50,7 @@ public List<Finding> getUnhandledFindingsForProduct(long productId, Finding.Seve
.toList();
}

public List<Finding> getUnhandledFindingsForEngagement(long engagementId, Finding.Severity minimumSeverity) throws URISyntaxException, JsonProcessingException {
public List<Finding> getUnhandledFindingsForEngagement(long engagementId, Finding.Severity minimumSeverity) {
final Map<String, Object> queryParams = Map.of(
"test__engagement", Long.toString(engagementId),
"active", Boolean.toString(true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<T extends Model> {
private static final String API_PREFIX = "/api/v2/";
private static final long DEFECT_DOJO_OBJET_LIMIT = 100L;
Expand Down Expand Up @@ -88,7 +87,7 @@ private RestTemplate setupRestTemplate() {

protected abstract Class<T> getModelClass();

protected abstract PaginatedResult<T> deserializeList(String response) throws JsonProcessingException;
protected abstract PaginatedResult<T> deserializeList(String response);

public T get(long id) {
var restTemplate = this.getRestTemplate();
Expand All @@ -104,7 +103,7 @@ public T get(long id) {
return response.getBody();
}

protected PaginatedResult<T> internalSearch(Map<String, Object> queryParams, long limit, long offset) throws JsonProcessingException, URISyntaxException {
protected PaginatedResult<T> internalSearch(Map<String, Object> queryParams, long limit, long offset) {
var restTemplate = this.getRestTemplate();
HttpEntity<String> payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders());

Expand All @@ -118,11 +117,18 @@ protected PaginatedResult<T> internalSearch(Map<String, Object> 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<String> responseString = restTemplate.exchange(
uriBuilder.build(mutableQueryParams),
final ResponseEntity<String> responseString = restTemplate.exchange(
builder.build(mutableQueryParams),
HttpMethod.GET,
payload,
String.class
Expand All @@ -131,7 +137,7 @@ protected PaginatedResult<T> internalSearch(Map<String, Object> queryParams, lon
return deserializeList(responseString.getBody());
}

public List<T> search(Map<String, Object> queryParams) throws URISyntaxException, JsonProcessingException {
public List<T> search(Map<String, Object> queryParams) {
List<T> objects = new LinkedList<>();

boolean hasNext;
Expand All @@ -149,12 +155,12 @@ public List<T> search(Map<String, Object> queryParams) throws URISyntaxException
return objects;
}

public List<T> search() throws URISyntaxException, JsonProcessingException {
public List<T> search() {
return search(new LinkedHashMap<>());
}

@SuppressWarnings("unchecked")
public Optional<T> searchUnique(T searchObject) throws URISyntaxException, JsonProcessingException {
public Optional<T> searchUnique(T searchObject) {
Map<String, Object> queryParams = searchStringMapper.convertValue(searchObject, Map.class);

var objects = search(queryParams);
Expand All @@ -164,7 +170,7 @@ public Optional<T> searchUnique(T searchObject) throws URISyntaxException, JsonP
.findFirst();
}

public Optional<T> searchUnique(Map<String, Object> queryParams) throws URISyntaxException, JsonProcessingException {
public Optional<T> searchUnique(Map<String, Object> queryParams) {
var objects = search(queryParams);

return objects.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,8 +27,12 @@ protected Class<GroupMember> getModelClass() {
}

@Override
protected PaginatedResult<GroupMember> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<GroupMember> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,8 +27,12 @@ protected Class<Group> getModelClass() {
}

@Override
protected PaginatedResult<Group> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<Group> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,8 +27,12 @@ protected Class<ProductGroup> getModelClass() {
}

@Override
protected PaginatedResult<ProductGroup> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<ProductGroup> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -27,8 +28,12 @@ protected Class<Product> getModelClass() {
}

@Override
protected PaginatedResult<Product> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<Product> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -27,8 +28,12 @@ protected Class<ProductType> getModelClass() {
}

@Override
protected PaginatedResult<ProductType> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<ProductType> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,8 +27,12 @@ protected Class<Test> getModelClass() {
}

@Override
protected PaginatedResult<Test> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<Test> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,8 +27,12 @@ protected Class<TestType> getModelClass() {
}

@Override
protected PaginatedResult<TestType> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<TestType> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,8 +27,12 @@ protected Class<ToolConfig> getModelClass() {
}

@Override
protected PaginatedResult<ToolConfig> deserializeList(String response) throws JsonProcessingException {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
protected PaginatedResult<ToolConfig> deserializeList(String response) {
try {
return this.objectMapper.readValue(response, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new PersistenceException("Can't process JSON response!", e);
}
}
}
Loading

0 comments on commit 492bdf9

Please sign in to comment.