Skip to content

Bulk Get (Custom Feature) (@since 1.15.0)

Pascal Knüppel edited this page Oct 28, 2022 · 6 revisions

This feature must be explicitly activated within the SCIM-SDK server

serviceProvider.getBulkConfig().setSupportBulkGet(true);

The SCIM SDK server supports a new custom feature that is usable by the SCIM-SDK-Client implementation. This feature will allow to retrieve a parent resource with its children to a specified depth level. Imagine the following dependency chain:

{
  "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:Group" ],
  "id" : "1",
  "displayName" : "group1"
}

{
  "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:Group" ],
  "id" : "2",
  "displayName" : "group2",
  "members" : [ {
    "value" : "1",
    "$ref" : "http://localhost:58887/scim/v2/Groups/1"
  } ]
}

{
  "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:Group" ],
  "id" : "3",
  "displayName" : "group3",
  "members" : [ {
    "value" : "2",
    "$ref" : "http://localhost:58887/scim/v2/Groups/2"
  } ]
}

{
  "schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:Group" ],
  "id" : "4",
  "displayName" : "group4",
  "members" : [ {
    "value" : "3",
    "$ref" : "http://localhost:58887/scim/v2/Groups/3"
  } ]
}

SCIM is actually pretty unflexible when it comes to getting this complete dependency chain together. You would need to send four requests to get'em all. The Bulk-Get feature allows you to get all of these resources in a single request or at least a part of it based on the depth level you specify.

A Bulk request to utilize this would look like this:

{
  "schemas" : [ "urn:ietf:params:scim:api:messages:2.0:BulkRequest" ],
  "failOnErrors" : 0,
  "Operations" : [ {
    "method" : "GET",          // GET is normally not supported at the bulk-endpoint
    "bulkId" : "bulk-get-op",  // still an optional value
    "path" : "/Groups/4",      // the resource to retrieve with its children
    "maxResourceLevel" : 2     // the specified depth level (parent [level: 0], parent.children [level: 1], parent.children.children [level: 2])
  } ]
}

and can be utilized with the SCIM-SDK Client like this:

    final String bulkId = "bulk-get-op";
    ServerResponse<BulkResponse> response = scimRequestBuilder.bulk()
                                                              .bulkRequestOperation("/Groups/4")
                                                              .method(HttpMethod.GET)
                                                              .bulkId(bulkId)
                                                              .maxResourceLevel(2)
                                                              .sendRequest();
    BulkResponse bulkResponse = response.getResource();
    BulkResponseOperation responseOperation = bulkResponse.getByBulkId(bulkId).get();
    BulkResponseGetOperation getResponseOperation = responseOperation.getResponse(BulkResponseGetOperation.class).get();

The response will contain the resources from group4 -> group3 -> group2 and group1 will be left out since the maxResourceLevel was limited to 2. If the maxResourceLevel is set to 3 the resource group1 would also be returned. The JSON response of such a bulk-request will look like this:

{
    "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:BulkResponse"
    ],
    "Operations": [
        {
            "method": "GET",
            "bulkId": "bulk-get-op",
            "id": "4",
            "location": "http://localhost:59592/scim/v2/Groups/4",
            "status": 200,
            "response": {
                "resourceId": "4",
                "status": 200,
                "resourceType": "Group",
                "resource": {
                    "schemas": [
                        "urn:ietf:params:scim:schemas:core:2.0:Group"
                    ],
                    "id": "4",
                    "displayName": "group4",
                    "members": [
                        {
                            "value": "3",
                            "$ref": "http://localhost:59592/scim/v2/Groups/3"
                        }
                    ]
                },
                "children": [
                    {
                        "nodePath": "members",
                        "resourceId": "3",
                        "status": 200,
                        "resourceType": "Group",
                        "resource": {
                            "schemas": [
                                "urn:ietf:params:scim:schemas:core:2.0:Group"
                            ],
                            "id": "3",
                            "displayName": "group3",
                            "members": [
                                {
                                    "value": "2",
                                    "$ref": "http://localhost:59592/scim/v2/Groups/2"
                                }
                            ]
                        },
                        "children": [
                            {
                                "nodePath": "members",
                                "resourceId": "2",
                                "status": 200,
                                "resourceType": "Group",
                                "resource": {
                                    "schemas": [
                                        "urn:ietf:params:scim:schemas:core:2.0:Group"
                                    ],
                                    "id": "2",
                                    "displayName": "group2",
                                    "members": [
                                        {
                                            "value": "1",
                                            "$ref": "http://localhost:59592/scim/v2/Groups/1"
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                ]
            }
        }
    ]
}

The response is built like this: You have a completely normal BulkResponse with several BulkResponseOperations based on the BulkRequestOperations you sent. In the example above exactly one BulkResponseOperation. The BulkResponseOperation does now contain a custom resource that is not defined by SCIM under the keyword response.

The first resource under the response-property is assumed to be resourceLevel=0 and it consists of the properties:

"resourceId": "4",
"status": 200,
"resourceType": "Group",
"resource": {...}
"children": [{...}, {...}, ...]

The status indicates if it was successful to retrieve the resource. It might happen that the client accessing the resource is not authorized to access some of the sub-resources and in this case such a resource would have a status of 403 (unauthorized). The resourceType maps to the name of the Group resource-type. So if you would access the /ResourceTypes endpoint, it would be the name-property of the resource-type.

The resource-property contains the resource that was retrieved that might contain referenced resources. In the example above the group4 references the group3-resource.

The children-property contains all retrieved child-resources. In case of a Group all retrievable members from the parent group.

The first resources within the first children-property is assumed to be resourceLevel=1 and it contains one additional property in comparison to resourceLevel=0

"nodePath": "members",           // the additional property is present from resourceLevel=1 and onwards
"resourceId": "3",
"status": 200,
"resourceType": "Group",
"resource": {...}
"children": [{...}, {...}, ...]

The nodePath property will give you the location of the parent-resource to where the resource belongs. In this case it will tell you that the contained resource is a members-element of the parent-group.

This feature is also usable with simple resource-reference-fields that are also a custom feature of this API. See: https://github.com/Captain-P-Goldfish/SCIM-SDK/wiki/Simple-Resource-References-(Custom-Feature)-(@since-1.15.0)