Skip to content

Commit

Permalink
Merge pull request #119 from fauna/use-new-resp-types
Browse files Browse the repository at this point in the history
Use new response types
  • Loading branch information
findgriffin authored Aug 26, 2024
2 parents 4058392 + 1707ba4 commit 7b2ff87
Show file tree
Hide file tree
Showing 20 changed files with 248 additions and 293 deletions.
27 changes: 23 additions & 4 deletions src/main/java/com/fauna/exception/AbortException.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
package com.fauna.exception;

import com.fauna.codec.CodecProvider;
import com.fauna.codec.DefaultCodecProvider;
import com.fauna.codec.UTF8FaunaParser;
import com.fauna.response.QueryFailure;

import java.io.IOException;

public class AbortException extends ServiceException {

private Object abort = null;
private final CodecProvider provider = DefaultCodecProvider.SINGLETON;

public AbortException(QueryFailure response) {
super(response);
}

public Object getAbort() {
if (this.getResponse().getAbort().isPresent()) {
return this.getResponse().getAbort().get();
public Object getAbort() throws IOException {
return getAbort(Object.class);
}

@SuppressWarnings("unchecked")
public <T> T getAbort(Class<T> clazz) throws IOException {
if (abort != null) return (T) abort;

var abStr = this.getResponse().getAbortString();
if (abStr.isPresent()) {
var codec = provider.get(clazz);
var parser = new UTF8FaunaParser(abStr.get());
abort = codec.decode(parser);
return (T) abort;
} else {
throw new RuntimeException("Abort Exception missing abort data.");
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.fauna.response.ConstraintFailure;
import com.fauna.response.QueryFailure;

import java.util.List;

public class ConstraintFailureException extends ServiceException {
public ConstraintFailureException(QueryFailure failure) {
super(failure);
}

public ConstraintFailure[] getConstraintFailures() {
return this.getResponse().getConstraintFailures().orElseThrow();
public List<ConstraintFailure> getConstraintFailures() {
var cf = this.getResponse().getConstraintFailures();
return cf.orElseGet(List::of);
}

}
27 changes: 7 additions & 20 deletions src/main/java/com/fauna/exception/ErrorHandler.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.fauna.exception;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fauna.constants.ResponseFields;
import com.fauna.response.wire.QueryResponseWire;
import com.fauna.response.QueryFailure;
import com.fauna.response.QueryStats;

import java.io.IOException;

import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
import static java.net.HttpURLConnection.HTTP_CONFLICT;
Expand All @@ -31,8 +30,7 @@ public class ErrorHandler {
* Handles errors based on the HTTP status code and response body.
*
* @param statusCode The HTTP status code.
* @param body The decoded QueryFailure body.
* @param mapper Jackson ObjectMapper.
* @param response The decoded response.
* @throws AbortException
* @throws AuthenticationException
* @throws AuthorizationException
Expand All @@ -46,20 +44,9 @@ public class ErrorHandler {
* @throws ThrottlingException
*
*/
public static void handleErrorResponse(int statusCode, String body, ObjectMapper mapper) {
try {
JsonNode json = mapper.readTree(body);
JsonNode statsNode = json.get(ResponseFields.STATS_FIELD_NAME);
QueryStats stats = mapper.convertValue(statsNode, QueryStats.class);
if (stats != null) {
QueryFailure failure = new QueryFailure(statusCode, json, stats);
handleQueryFailure(statusCode, failure);
} else {
throw new ProtocolException(statusCode, body);
}
} catch (JsonProcessingException e) {
throw new ProtocolException(statusCode, body);
}
public static void handleErrorResponse(int statusCode, QueryResponseWire response, String body) throws IOException {
QueryFailure failure = new QueryFailure(statusCode, response);
handleQueryFailure(statusCode, failure);
throw new ProtocolException(statusCode, body);
}

Expand Down
25 changes: 7 additions & 18 deletions src/main/java/com/fauna/response/ConstraintFailure.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
package com.fauna.response;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;
import java.util.Optional;

public class ConstraintFailure {
private final String message;

private final String name;
private final Object[][] paths;

@JsonCreator
public ConstraintFailure(
@JsonProperty("message") String message,
@JsonProperty("name") String name,
@JsonProperty("paths") Object[][] paths) {
private final List<List<Object>> paths;

public ConstraintFailure(String message, String name, List<List<Object>> paths) {
this.message = message;
this.name = name;
this.paths = paths;
Expand All @@ -28,15 +24,8 @@ public Optional<String> getName() {
return Optional.ofNullable(this.name);
}

/**
* Each path returned by Fauna for a constraint failure is an array of strings and integers. But since Java
* doesn't really have a way to support union types, returning Object (the common parent of String and Integer)
* seems like the simplest solution.
*
* @return
*/
public Optional<Object[][]> getPaths() {
return Optional.ofNullable(this.paths);
public List<List<Object>> getPaths() {
return paths != null ? paths : List.of();
}

}
43 changes: 0 additions & 43 deletions src/main/java/com/fauna/response/ErrorInfo.java

This file was deleted.

75 changes: 40 additions & 35 deletions src/main/java/com/fauna/response/QueryFailure.java
Original file line number Diff line number Diff line change
@@ -1,55 +1,60 @@
package com.fauna.response;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fauna.constants.ResponseFields;

import com.fauna.codec.DefaultCodecProvider;
import com.fauna.codec.UTF8FaunaParser;
import com.fauna.response.wire.ConstraintFailureWire;
import com.fauna.response.wire.QueryResponseWire;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public final class QueryFailure extends QueryResponse {

private static ObjectMapper fallbackMapper = new ObjectMapper();
private int statusCode;
private final int statusCode;
private String errorCode = "";
private String message = "";
private ConstraintFailure[] constraintFailures;
private Object abort;

private String fullMessage = "";
private List<ConstraintFailure> constraintFailures;
private String abortString;

public static QueryFailure fallback() {
try {
return new QueryFailure(500, fallbackMapper.createObjectNode(), null);
} catch (JsonProcessingException exc) {
throw new RuntimeException(exc);
}
}
private final String fullMessage;

/**
* Initializes a new instance of the {@link QueryFailure} class, parsing the provided raw
* response text to extract error information.
* response to extract error information.
*
* @param statusCode The HTTP status code.
* @param json The JSON response body.
* @param response The parsed response.
*/
public QueryFailure(int statusCode, JsonNode json, QueryStats stats) throws JsonProcessingException {
super(json, stats);
this.statusCode = statusCode;

JsonNode elem;
public QueryFailure(int statusCode, QueryResponseWire response) throws IOException {
super(response);

if ((elem = json.get(ResponseFields.ERROR_FIELD_NAME)) != null) {
this.statusCode = statusCode;

ErrorInfo info = new ObjectMapper().treeToValue(elem, ErrorInfo.class);
errorCode = info.getCode() != null ? info.getCode() : "";
message = info.getMessage() != null ? info.getMessage() : "";
constraintFailures = info.getConstraintFailures();
abort = info.getAbort().isPresent() ? info.getAbort().get() : null;
var err = response.getError();
if (err != null) {
errorCode = err.getCode();
message = err.getMessage();

if (err.getConstraintFailures().isPresent()) {
var cf = new ArrayList<ConstraintFailure>();
var codec = DefaultCodecProvider.SINGLETON.get(Object.class);
for (ConstraintFailureWire cfw : err.getConstraintFailures().get()) {
var parser = new UTF8FaunaParser(cfw.getPaths());
var paths = codec.decode(parser);
cf.add(new ConstraintFailure(cfw.getMessage(), cfw.getName(), (List<List<Object>>) paths));
}
constraintFailures = cf;
}

if (err.getAbort().isPresent()) {
abortString = err.getAbort().get();
}
}

var maybeSummary = !this.getSummary().isEmpty() ? "\n---\n" + this.getSummary() : "";
var maybeSummary = this.getSummary() != null ? "\n---\n" + this.getSummary() : "";
fullMessage = String.format(
"%d (%s): %s%s",
this.getStatusCode(),
Expand All @@ -75,11 +80,11 @@ public String getFullMessage() {
return fullMessage;
}

public Optional<ConstraintFailure[]> getConstraintFailures() {
public Optional<List<ConstraintFailure>> getConstraintFailures() {
return Optional.ofNullable(constraintFailures);
}

public Optional<Object> getAbort() {
return Optional.ofNullable(this.abort);
public Optional<String> getAbortString() {
return Optional.ofNullable(this.abortString);
}
}
Loading

0 comments on commit 7b2ff87

Please sign in to comment.