From 75adc7453c947fbc05b796d00c3b8473d9c45ecd Mon Sep 17 00:00:00 2001 From: Kc Date: Mon, 24 Sep 2018 23:36:57 +0200 Subject: [PATCH 1/2] Better help messages FIXED: save ApiClient.translator CHANGED: ApiClient now respects more resource annotations for building help messages (success and error responses) CHANGED: Added more detailed annotations to BlocksResource --- src/api/ApiClient.java | 78 ++++++++++++++++++++++++++++++------ src/api/ApiErrorFactory.java | 20 +++++++-- src/api/BlocksResource.java | 41 ++++++++++++------- 3 files changed, 109 insertions(+), 30 deletions(-) diff --git a/src/api/ApiClient.java b/src/api/ApiClient.java index 49d9cd8a..d43a63f2 100644 --- a/src/api/ApiClient.java +++ b/src/api/ApiClient.java @@ -3,6 +3,8 @@ package api; import globalization.Translator; import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.ArrayList; @@ -30,16 +32,20 @@ import settings.Settings; public class ApiClient { - private class HelpString { + private class HelpInfo { public final Pattern pattern; public final String fullPath; public final String description; + public final List success; + public final List errors; - public HelpString(Pattern pattern, String fullPath, String description) { + public HelpInfo(Pattern pattern, String fullPath, String description, List success, List errors) { this.pattern = pattern; this.fullPath = fullPath; this.description = description; + this.success = success; + this.errors = errors; } } @@ -55,11 +61,12 @@ public class ApiClient { ApiService apiService; private Translator translator; - List helpStrings; + List helpInfos; public ApiClient(ApiService apiService, Translator translator) { this.apiService = apiService; - this.helpStrings = getHelpStrings(apiService.getResources()); + this.translator = translator; + this.helpInfos = getHelpInfos(apiService.getResources()); } //XXX: replace singleton pattern by dependency injection? @@ -73,9 +80,11 @@ public class ApiClient { return instance; } - private List getHelpStrings(Iterable> resources) { - List result = new ArrayList<>(); + private List getHelpInfos(Iterable> resources) { + List result = new ArrayList<>(); + // TODO: need some way to realize translation from resource annotations + // scan each resource class for (Class resource : resources) { if (OpenApiResource.class.isAssignableFrom(resource)) { @@ -96,6 +105,38 @@ public class ApiClient { } String description = operationAnnotation.description(); + + // extract responses + ArrayList success = new ArrayList(); + ArrayList errors = new ArrayList(); + for(ApiResponse response : operationAnnotation.responses()) { + String responseDescription = response.description(); + if(StringUtils.isBlank(responseDescription)) + continue; // ignore responses without description + + try { + // try to identify response type by status code + int responseCode = Integer.parseInt(response.responseCode()); + if(responseCode >= 400) { + errors.add(responseDescription); + } else { + success.add(responseDescription); + } + } catch (NumberFormatException e) { + // try to identify response type by content + if(response.content().length > 0) { + Content content = response.content()[0]; + Class implementation = content.schema().implementation(); + if(implementation != null && ApiErrorMessage.class.isAssignableFrom(implementation)) { + errors.add(responseDescription); + } else { + success.add(responseDescription); + } + } else { + success.add(responseDescription); + } + } + } Path methodPath = method.getDeclaredAnnotation(Path.class); String methodPathString = (methodPath != null) ? methodPath.value() : ""; @@ -110,9 +151,10 @@ public class ApiClient { HttpMethod httpMethod = annotation.annotationType().getDeclaredAnnotation(HttpMethod.class); String httpMethodString = httpMethod.value(); - String fullPath = httpMethodString + " " + resourcePathString + methodPathString; + String fullPath = httpMethodString + " " + resourcePathString + methodPathString; + Pattern pattern = Pattern.compile("^ *(" + httpMethodString + " *)?" + getHelpPatternForPath(resourcePathString + methodPathString)); - result.add(new HelpString(pattern, fullPath, description)); + result.add(new HelpInfo(pattern, fullPath, description, success, errors)); } } } @@ -151,7 +193,7 @@ public class ApiClient { StringBuilder result = new StringBuilder(); boolean showAll = command.trim().equalsIgnoreCase("all"); - for (HelpString helpString : helpStrings) { + for (HelpInfo helpString : helpInfos) { if (showAll || helpString.pattern.matcher(command).matches()) { appendHelp(result, helpString); } @@ -194,8 +236,20 @@ public class ApiClient { return result.toString(); } - private void appendHelp(StringBuilder builder, HelpString helpString) { - builder.append(helpString.fullPath + "\n"); - builder.append(helpString.description + "\n"); + private void appendHelp(StringBuilder builder, HelpInfo help) { + builder.append(help.fullPath + "\n"); + builder.append(" " + help.description + "\n"); + if(help.success != null && help.success.size() > 0) { + builder.append(" On success returns:\n"); + for(String content : help.success) { + builder.append(" " + content + "\n"); + } + } + if(help.errors != null && help.errors.size() > 0) { + builder.append(" On failure returns:\n"); + for(String content : help.errors) { + builder.append(" " + content + "\n"); + } + } } } diff --git a/src/api/ApiErrorFactory.java b/src/api/ApiErrorFactory.java index ad7c7f7e..784a3476 100644 --- a/src/api/ApiErrorFactory.java +++ b/src/api/ApiErrorFactory.java @@ -150,14 +150,27 @@ public class ApiErrorFactory { String templateKey = String.format("%s: ApiError.%s message", ApiErrorFactory.class.getSimpleName(), errorCode.name()); return new ErrorMessageEntry(templateKey, defaultTemplate, templateValues); } + + public String getErrorMessage(Locale locale, ApiError error) { + ErrorMessageEntry errorMessage = this.errorMessages.get(error); + String message = this.translator.translate(locale, errorMessage.templateKey, errorMessage.defaultTemplate, errorMessage.templateValues); + return message; + } public ApiException createError(ApiError error) { return createError(error, null); } + public ApiException createError(Locale locale, ApiError error) { + return createError(locale, error, null); + } + public ApiException createError(ApiError error, Throwable throwable) { - Locale locale = Locale.ENGLISH; // XXX: should this be in local language? - + Locale locale = Locale.ENGLISH; // default locale + return createError(locale, error, throwable); + } + + public ApiException createError(Locale locale, ApiError error, Throwable throwable) { // TODO: handle AT errors // old AT error handling // JSONObject jsonObject = new JSONObject(); @@ -173,9 +186,8 @@ public class ApiErrorFactory { // // // return new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).entity(jsonObject.toJSONString()).build()); - ErrorMessageEntry errorMessage = this.errorMessages.get(error); - String message = this.translator.translate(locale, errorMessage.templateKey, errorMessage.defaultTemplate, errorMessage.templateValues); + String message = getErrorMessage(locale, error); return new ApiException(error.getStatus(), error.getCode(), message, throwable); } } diff --git a/src/api/BlocksResource.java b/src/api/BlocksResource.java index ae79734d..e4f7f09b 100644 --- a/src/api/BlocksResource.java +++ b/src/api/BlocksResource.java @@ -40,11 +40,12 @@ public class BlocksResource { responses = { @ApiResponse( description = "The blocks" - //content = @Content(schema = @Schema(implementation = ???)) + //content = @Content(schema = @Schema(implementation = ???)) ), @ApiResponse( responseCode = "422", - description = "Wallet does not exist" + description = "Error: 201 - Wallet does not exist", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ) } ) @@ -65,15 +66,18 @@ public class BlocksResource { ), @ApiResponse( responseCode = "400", - description = "Invalid address" + description = "102 - Invalid address", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ), @ApiResponse( responseCode = "422", - description = "Wallet does not exist" + description = "201 - Wallet does not exist", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ), @ApiResponse( responseCode = "422", - description = "Address does not exist in wallet" + description = "202 - Address does not exist in wallet", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ) } ) @@ -94,11 +98,13 @@ public class BlocksResource { ), @ApiResponse( responseCode = "400", - description = "Invalid signature" + description = "101 - Invalid signature", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ), @ApiResponse( responseCode = "422", - description = "Block does not exist" + description = "301 - Block does not exist", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ) } ) @@ -153,11 +159,13 @@ public class BlocksResource { ), @ApiResponse( responseCode = "400", - description = "Invalid signature" + description = "101 - Invalid signature", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ), @ApiResponse( responseCode = "422", - description = "Block does not exist" + description = "301 - Block does not exist", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ) } ) @@ -195,11 +203,13 @@ public class BlocksResource { ), @ApiResponse( responseCode = "400", - description = "Invalid signature" + description = "101 - Invalid signature", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ), @ApiResponse( responseCode = "422", - description = "Block does not exist" + description = "301 - Block does not exist", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ) } ) @@ -275,11 +285,13 @@ public class BlocksResource { ), @ApiResponse( responseCode = "400", - description = "Invalid signature" + description = "101 - Invalid signature", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ), @ApiResponse( responseCode = "422", - description = "Block does not exist" + description = "301 - Block does not exist", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ) } ) @@ -300,7 +312,8 @@ public class BlocksResource { ), @ApiResponse( responseCode = "422", - description = "Block does not exist" + description = "301 - Block does not exist", + content = @Content(schema = @Schema(implementation = ApiErrorMessage.class)) ) } ) From 1b58bc82e94eb6415e31641e18fa05916bfde7a0 Mon Sep 17 00:00:00 2001 From: Kc Date: Sat, 29 Sep 2018 12:23:49 +0200 Subject: [PATCH 2/2] CHANGED: moved hsqldb-r5836.jar to local maven repository to fix build --- .classpath | 1 - lib/org/hsqldb/hsqldb/maven-metadata.xml | 12 ++++++++++++ lib/org/hsqldb/hsqldb/maven-metadata.xml.md5 | 1 + lib/org/hsqldb/hsqldb/maven-metadata.xml.sha1 | 1 + lib/{ => org/hsqldb/hsqldb/r5836}/hsqldb-r5836.jar | Bin lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.md5 | 1 + lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.sha1 | 1 + lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom | 8 ++++++++ lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.md5 | 1 + lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.sha1 | 1 + pom.xml | 9 +++++++-- 11 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 lib/org/hsqldb/hsqldb/maven-metadata.xml create mode 100644 lib/org/hsqldb/hsqldb/maven-metadata.xml.md5 create mode 100644 lib/org/hsqldb/hsqldb/maven-metadata.xml.sha1 rename lib/{ => org/hsqldb/hsqldb/r5836}/hsqldb-r5836.jar (100%) create mode 100644 lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.md5 create mode 100644 lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.sha1 create mode 100644 lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom create mode 100644 lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.md5 create mode 100644 lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.sha1 diff --git a/.classpath b/.classpath index dc543d95..77e8068a 100644 --- a/.classpath +++ b/.classpath @@ -17,6 +17,5 @@ - diff --git a/lib/org/hsqldb/hsqldb/maven-metadata.xml b/lib/org/hsqldb/hsqldb/maven-metadata.xml new file mode 100644 index 00000000..c2b0ba09 --- /dev/null +++ b/lib/org/hsqldb/hsqldb/maven-metadata.xml @@ -0,0 +1,12 @@ + + + org.hsqldb + hsqldb + + r5836 + + r5836 + + 20180929092113 + + diff --git a/lib/org/hsqldb/hsqldb/maven-metadata.xml.md5 b/lib/org/hsqldb/hsqldb/maven-metadata.xml.md5 new file mode 100644 index 00000000..e54c38b1 --- /dev/null +++ b/lib/org/hsqldb/hsqldb/maven-metadata.xml.md5 @@ -0,0 +1 @@ +1d7f55d30c3542b76ef961749da3c40f \ No newline at end of file diff --git a/lib/org/hsqldb/hsqldb/maven-metadata.xml.sha1 b/lib/org/hsqldb/hsqldb/maven-metadata.xml.sha1 new file mode 100644 index 00000000..41a9f454 --- /dev/null +++ b/lib/org/hsqldb/hsqldb/maven-metadata.xml.sha1 @@ -0,0 +1 @@ +8bb6a2ace951f1805b9baac61bca3a548e4299cc \ No newline at end of file diff --git a/lib/hsqldb-r5836.jar b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar similarity index 100% rename from lib/hsqldb-r5836.jar rename to lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar diff --git a/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.md5 b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.md5 new file mode 100644 index 00000000..127cbd95 --- /dev/null +++ b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.md5 @@ -0,0 +1 @@ +7d59b5596e655b2e4fd78796e7a3896b \ No newline at end of file diff --git a/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.sha1 b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.sha1 new file mode 100644 index 00000000..73d9c685 --- /dev/null +++ b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.jar.sha1 @@ -0,0 +1 @@ +a7d55ed9afd753fd9c620796f7d88f67a554711c \ No newline at end of file diff --git a/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom new file mode 100644 index 00000000..ec5069a1 --- /dev/null +++ b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom @@ -0,0 +1,8 @@ + + + 4.0.0 + org.hsqldb + hsqldb + r5836 + diff --git a/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.md5 b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.md5 new file mode 100644 index 00000000..74e8c4f7 --- /dev/null +++ b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.md5 @@ -0,0 +1 @@ +4d667eead4590a45fd75787cd6125701 \ No newline at end of file diff --git a/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.sha1 b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.sha1 new file mode 100644 index 00000000..12b17562 --- /dev/null +++ b/lib/org/hsqldb/hsqldb/r5836/hsqldb-r5836.pom.sha1 @@ -0,0 +1 @@ +f77180541070ce99899dc281b1c4469a6b9656f0 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 08a54ee9..dfd08a3d 100644 --- a/pom.xml +++ b/pom.xml @@ -17,13 +17,18 @@ + + + project.local + project + file:${project.basedir}/lib + + org.hsqldb hsqldb r5836 - system - ${project.basedir}/lib/hsqldb-r5836.jar com.googlecode.json-simple