[SYNCOPE-1274] Add documentation for errors, X-Application-Error-Code, 
X-Application-Error-Info, X-Syncope-Null-Priority-Async


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/6498a0bf
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/6498a0bf
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/6498a0bf

Branch: refs/heads/master
Commit: 6498a0bf7186d4a5c68ae27131e74f743064f0b7
Parents: 36e5aa9
Author: Francesco Chicchiriccò <ilgro...@apache.org>
Authored: Mon Feb 19 10:52:39 2018 +0100
Committer: Francesco Chicchiriccò <ilgro...@apache.org>
Committed: Mon Feb 19 14:11:08 2018 +0100

----------------------------------------------------------------------
 .../rest/api/service/AccessTokenService.java    | 18 +++----
 .../rest/api/service/AnyObjectService.java      | 15 ++++++
 .../common/rest/api/service/AnyService.java     | 20 +++++++
 .../common/rest/api/service/GroupService.java   | 15 ++++++
 .../common/rest/api/service/RealmService.java   | 15 ++++++
 .../common/rest/api/service/UserService.java    | 20 +++++++
 .../core/rest/cxf/SyncopeOpenApiCustomizer.java | 57 +++++++++++++++-----
 7 files changed, 137 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/6498a0bf/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AccessTokenService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AccessTokenService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AccessTokenService.java
index b9756b0..81728f1 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AccessTokenService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AccessTokenService.java
@@ -55,15 +55,15 @@ public interface AccessTokenService extends JAXRSService {
      */
     @Operation(security = {
         @SecurityRequirement(name = "BasicAuthentication") })
-    @ApiResponses(
-            @ApiResponse(responseCode = "204",
-                    description = "JWT successfully generated", headers = {
-                @Header(name = RESTHeaders.TOKEN, schema =
-                        @Schema(type = "string"),
-                        description = "Generated JWT")
-                , @Header(name = RESTHeaders.TOKEN_EXPIRE, schema =
-                        @Schema(type = "string"),
-                        description = "Expiration of the generated JWT") }))
+    @ApiResponses({
+        @ApiResponse(responseCode = "204",
+                description = "JWT successfully generated", headers = {
+                    @Header(name = RESTHeaders.TOKEN, schema =
+                            @Schema(type = "string"), description = "Generated 
JWT")
+                    , @Header(name = RESTHeaders.TOKEN_EXPIRE, schema =
+                            @Schema(type = "string"), description = 
"Expiration of the generated JWT") })
+        , @ApiResponse(responseCode = "401", description = "Invalid username 
or password")
+    })
     @POST
     @Path("login")
     @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })

http://git-wip-us.apache.org/repos/asf/syncope/blob/6498a0bf/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyObjectService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyObjectService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyObjectService.java
index 005cb67..d08bd67 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyObjectService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyObjectService.java
@@ -80,6 +80,11 @@ public interface AnyObjectService extends 
AnyService<AnyObjectTO> {
             description = "Allows client to specify a preference for the 
result to be returned from the server",
             allowEmptyValue = true, schema =
             @Schema(defaultValue = "return-content", allowableValues = { 
"return-content", "return-no-content" }))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses(
             @ApiResponse(responseCode = "201",
                     description =
@@ -118,6 +123,11 @@ public interface AnyObjectService extends 
AnyService<AnyObjectTO> {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Any object successfully updated enriched with 
propagation status information, as Entity",
@@ -154,6 +164,11 @@ public interface AnyObjectService extends 
AnyService<AnyObjectTO> {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Any object successfully updated enriched with 
propagation status information, as Entity",

http://git-wip-us.apache.org/repos/asf/syncope/blob/6498a0bf/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyService.java
index 768b3e6..b526d36 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyService.java
@@ -156,6 +156,11 @@ public interface AnyService<TO extends AnyTO> extends 
JAXRSService {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "User, Group or Any Object successfully deleted 
enriched with propagation status "
@@ -191,6 +196,11 @@ public interface AnyService<TO extends AnyTO> extends 
JAXRSService {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Bulk action result", content =
@@ -226,6 +236,11 @@ public interface AnyService<TO extends AnyTO> extends 
JAXRSService {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Bulk action result", content =
@@ -256,6 +271,11 @@ public interface AnyService<TO extends AnyTO> extends 
JAXRSService {
             description = "Allows client to specify a preference for the 
result to be returned from the server",
             allowEmptyValue = true, schema =
             @Schema(defaultValue = "return-content", allowableValues = { 
"return-content", "return-no-content" }))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Bulk action result", content =

http://git-wip-us.apache.org/repos/asf/syncope/blob/6498a0bf/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
index e4eaafa..39f37ad 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
@@ -85,6 +85,11 @@ public interface GroupService extends AnyService<GroupTO> {
             description = "Allows client to specify a preference for the 
result to be returned from the server",
             allowEmptyValue = true, schema =
             @Schema(defaultValue = "return-content", allowableValues = { 
"return-content", "return-no-content" }))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses(
             @ApiResponse(responseCode = "201",
                     description = "Group successfully created enriched with 
propagation status information, as Entity,"
@@ -122,6 +127,11 @@ public interface GroupService extends AnyService<GroupTO> {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Group successfully updated enriched with 
propagation status information, as Entity",
@@ -158,6 +168,11 @@ public interface GroupService extends AnyService<GroupTO> {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Group successfully updated enriched with 
propagation status information, as Entity",

http://git-wip-us.apache.org/repos/asf/syncope/blob/6498a0bf/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RealmService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RealmService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RealmService.java
index 517aa20..a9e8ff3 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RealmService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RealmService.java
@@ -87,6 +87,11 @@ public interface RealmService extends JAXRSService {
             description = "Allows client to specify a preference for the 
result to be returned from the server",
             allowEmptyValue = true, schema =
             @Schema(defaultValue = "return-content", allowableValues = { 
"return-content", "return-no-content" }))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses(
             @ApiResponse(responseCode = "201",
                     description = "Realm successfully created enriched with 
propagation status information, as Entity,"
@@ -120,6 +125,11 @@ public interface RealmService extends JAXRSService {
             description = "Allows client to specify a preference for the 
result to be returned from the server",
             allowEmptyValue = true, schema =
             @Schema(defaultValue = "return-content", allowableValues = { 
"return-content", "return-no-content" }))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Realm successfully updated enriched with 
propagation status information, as Entity",
@@ -148,6 +158,11 @@ public interface RealmService extends JAXRSService {
             description = "Allows client to specify a preference for the 
result to be returned from the server",
             allowEmptyValue = true, schema =
             @Schema(defaultValue = "return-content", allowableValues = { 
"return-content", "return-no-content" }))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "Realm successfully deleted enriched with 
propagation status information, as Entity",

http://git-wip-us.apache.org/repos/asf/syncope/blob/6498a0bf/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
index 6f36494..7c4e33a 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
@@ -84,6 +84,11 @@ public interface UserService extends AnyService<UserTO> {
             description = "Allows client to specify a preference for the 
result to be returned from the server",
             allowEmptyValue = true, schema =
             @Schema(defaultValue = "return-content", allowableValues = { 
"return-content", "return-no-content" }))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses(
             @ApiResponse(responseCode = "201",
                     description = "User successfully created enriched with 
propagation status information, as Entity,"
@@ -123,6 +128,11 @@ public interface UserService extends AnyService<UserTO> {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "User successfully updated enriched with 
propagation status information, as Entity",
@@ -160,6 +170,11 @@ public interface UserService extends AnyService<UserTO> {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "User successfully updated enriched with 
propagation status information, as Entity",
@@ -198,6 +213,11 @@ public interface UserService extends AnyService<UserTO> {
             + "an error is reported and the requested operation is not 
performed.",
             allowEmptyValue = true, schema =
             @Schema(type = "string"))
+    @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
+            description = "If 'true', instructs the propagation process not to 
wait for completion when communicating"
+            + " with External Resources with no priority set",
+            allowEmptyValue = true, schema =
+            @Schema(type = "boolean", defaultValue = "false"))
     @ApiResponses({
         @ApiResponse(responseCode = "200",
                 description = "User successfully updated enriched with 
propagation status information, as Entity",

http://git-wip-us.apache.org/repos/asf/syncope/blob/6498a0bf/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeOpenApiCustomizer.java
----------------------------------------------------------------------
diff --git 
a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeOpenApiCustomizer.java
 
b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeOpenApiCustomizer.java
index 80a6f61..788c12f 100644
--- 
a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeOpenApiCustomizer.java
+++ 
b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/SyncopeOpenApiCustomizer.java
@@ -18,14 +18,23 @@
  */
 package org.apache.syncope.core.rest.cxf;
 
+import io.swagger.v3.oas.integration.api.OpenAPIConfiguration;
+import io.swagger.v3.oas.models.headers.Header;
+import io.swagger.v3.oas.models.media.Content;
+import io.swagger.v3.oas.models.media.MediaType;
 import io.swagger.v3.oas.models.media.Schema;
 import io.swagger.v3.oas.models.parameters.HeaderParameter;
 import io.swagger.v3.oas.models.parameters.Parameter;
+import io.swagger.v3.oas.models.responses.ApiResponse;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import org.apache.cxf.jaxrs.openapi.OpenApiCustomizer;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.ErrorTO;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.core.persistence.api.DomainsHolder;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
@@ -44,6 +53,31 @@ public class SyncopeOpenApiCustomizer extends 
OpenApiCustomizer {
     }
 
     @Override
+    public OpenAPIConfiguration customize(final OpenAPIConfiguration 
configuration) {
+        Map<String, Header> headers = new LinkedHashMap<>();
+        headers.put(
+                RESTHeaders.ERROR_CODE,
+                new Header().schema(new 
Schema<>().type("string")).description("Error code"));
+        headers.put(
+                RESTHeaders.ERROR_INFO,
+                new Header().schema(new 
Schema<>().type("string")).description("Error message"));
+
+        Content content = new Content();
+        content.addMediaType(
+                javax.ws.rs.core.MediaType.APPLICATION_JSON, new 
MediaType().schema(new Schema<ErrorTO>()));
+        content.addMediaType(
+                javax.ws.rs.core.MediaType.APPLICATION_XML, new 
MediaType().schema(new Schema<ErrorTO>()));
+
+        configuration.getOpenAPI().getComponents().addResponses("400", new 
ApiResponse().
+                description("An error occurred; HTTP status code can vary 
depending on the actual error: "
+                        + "400, 403, 404, 409, 412").
+                headers(headers).
+                content(content));
+
+        return super.customize(configuration);
+    }
+
+    @Override
     protected void addParameters(final List<Parameter> parameters) {
         if (domains == null) {
             domains = new ArrayList<>(
@@ -51,26 +85,21 @@ public class SyncopeOpenApiCustomizer extends 
OpenApiCustomizer {
                             
getBean(DomainsHolder.class).getDomains().keySet());
         }
 
-        boolean domainHeaderParameterFound = false;
-        for (int i = 0; i < parameters.size(); i++) {
-            if (parameters.get(i) instanceof HeaderParameter
-                    && RESTHeaders.DOMAIN.equals(parameters.get(i).getName())) 
{
-
-                domainHeaderParameterFound = true;
-            }
-        }
-        if (!domainHeaderParameterFound) {
-            HeaderParameter domainHeaderParameter = new HeaderParameter();
-            domainHeaderParameter.setName(RESTHeaders.DOMAIN);
-            domainHeaderParameter.setRequired(true);
+        Optional<Parameter> domainHeaderParameter = 
parameters.stream().filter(parameter
+                -> parameter instanceof HeaderParameter && 
RESTHeaders.DOMAIN.equals(parameter.getName())).
+                findFirst();
+        if (!domainHeaderParameter.isPresent()) {
+            HeaderParameter parameter = new HeaderParameter();
+            parameter.setName(RESTHeaders.DOMAIN);
+            parameter.setRequired(true);
 
             Schema<String> schema = new Schema<>();
             schema.setType("string");
             schema.setEnum(domains);
             schema.setDefault(SyncopeConstants.MASTER_DOMAIN);
-            domainHeaderParameter.setSchema(schema);
+            parameter.setSchema(schema);
 
-            parameters.add(domainHeaderParameter);
+            parameters.add(parameter);
         }
     }
 }

Reply via email to