-
Notifications
You must be signed in to change notification settings - Fork 76
Common Problems and FAQ
This page contains a "Frequently Asked Questions" section that may be referenced for common issues when working with the UnboundID SCIM2 SDK.
Short Summary
When Java objects are converted to strings, they can be serialized incorrectly if a misconfigured object mapper is used. To solve this, ensure that your application is using an object mapper acquired from the SCIM SDK with:
final ObjectMapper OBJECT_MAPPER = JsonUtils.createObjectMapper();
If your application is a Spring application, it is strongly encouraged to obtain this object mapper and register it as a Spring Bean.
The UnboundID SCIM2 SDK leverages the Jackson library for converting between raw JSON strings and Plain Old Java Objects (POJOs) that can be leveraged in application code.
Jackson allows Java (and Java-based) code to have a high level of customizability for an application's JSON parsing, but some of its default settings are not optimal for the SCIM SDK's needs. For example, the SCIM SDK sets values to null
to signify that they are not being used. When printing a SCIM resource, these null values should not be included, since they have no data. However, the default ObjectMapper configuration in Jackson will explicitly print null values. A code example is provided below:
GroupResource group = new GroupResource().setDisplayName("kendrick");
String stringValue = new ObjectMapper().valueToTree(group).toPrettyString();
System.out.println(stringValue);
In the code snippet above, a new object mapper (with the default configuration) is being used to convert the object into a string. Because of this, the JSON that is printed will show all values, even they are null:
{
"schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:Group" ],
"id" : null,
"externalId" : null,
"meta" : null,
"displayName" : "kendrick",
"members" : null
}
This is undesirable for SCIM resources. If a resource (such as a group or user) does not have a value for a field, then it should simply not be printed when displaying the SCIM data. Compare this with the output of new GroupResource().toString()
, which uses the SCIM SDK's object mapper:
{
"schemas" : [ "urn:ietf:params:scim:schemas:core:2.0:Group" ],
"displayName" : "kendrick"
}
Null values are just one example. There are many other behaviors that should be changed for SCIM applications, which can be hard to track and discover. For this reason, the SCIM SDK provides a pre-configured ObjectMapper that you should use for any serialization/deserialization of SCIM resources, as we have already found a reliable configuration for you. As shown above, this SCIM object mapper can be obtained from the SCIM SDK with:
final ObjectMapper OBJECT_MAPPER = JsonUtils.createObjectMapper();
If you are creating a SCIM application in the Spring framework, then you should register the SCIM SDK's object mapper as a Spring Bean. This way, the Controller will leverage the correct configuration when accepting client requests and returning client responses:
public static final ObjectMapper SCIM_SDK_OBJECT_MAPPER = JsonUtils.createObjectMapper();
@Bean
@Primary
public ObjectMapper getSCIMObjectMapper()
{
return SCIM_SDK_OBJECT_MAPPER;
}
Note that the object mapper is created as a member variable to ensure that it is only created once. Creating new instances of object mappers is considered expensive and should be done sparingly when possible.
Null values are printed by Jackson's default settings for object mappers. Ensure you are using the SCIM SDK's object mapper. See SCIM resources are converted into invalid JSON for more information.
It is common for SCIM service providers to have restrictions on the format of a user. For example, in the PingOne SCIM API, users may only have a single email address, though it will still be returned as an array. Other SCIM service providers, such as Amazon Web Services, contain similar constraints.
When working with a particular service provider, these constraints can be hard to track. For example, consider an AWS SCIM user that does not support the use of the photos
attribute. The best way to enforce this is to create a new AWS user class that extends the default SCIM UserResource
:
public class AWSUser extends UserResource
{
}
To ensure that an AWS user will never be able to set a value for photos, override the setPhotos()
methods:
public class AWSUser extends UserResource
{
@Override
public UserResource setPhotos(final List<Photo> photos)
{
// Throw an exception or ignore the request.
return this;
}
@Override
public UserResource setPhotos(final Photo... photos)
{
// Throw an exception or ignore the request.
return this;
}
@Override
public List<Photos> getPhotos()
{
return null;
}
}
It would also be a good idea to explicitly set this value to null
in the constructor:
public class AWSUser extends UserResource
{
public AWSUser()
{
super();
// AWS does not support the 'photos' attribute.
super.setPhotos(null);
}
...
}
Now, the AWSUser
can be used by the application, and you don't have to worry about the photos
attribute ever containing a value. It's worth noting that this example is only for one attribute. When there are multiple attributes that have special considerations, it is best to enforce this logic in the dedicated user model (e.g., AWSUser
) to prevent mistakes that would violate the SCIM service provider's user constraints.
There are several common Java libraries that support parsing JSON objects. One such library is Jackson, and another is JSON-B. The UnboundID SCIM2 SDK leverages the Jackson library for serialization and deserialization between JSON strings and Java objects. If you are receiving JSON-B exceptions, it could indicate that:
- Your project is not configured to use Jackson
- There is a transitive dependency that is using JSON-B and should be removed
If you are using Spring, ensure your project is using Jackson. The Spring documentation has a guide on this.
To analyze the dependencies, you can use mvn dependency:analyze
for Maven-based projects. In
particular, this issue is known to affect the org.glassfish.jersey.security:oauth2-client
library.
If you are using this dependency, be sure to exclude the jersey-media-json-binding
library:
<dependency>
<groupId>org.glassfish.jersey.security</groupId>
<artifactId>oauth2-client</artifactId>
<version>${jersey.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
</exclusion>
</exclusions>
</dependency>
See https://github.com/pingidentity/scim2/issues/222 for more information.
The SCIM SDK's JsonUtils class can be used to manually serialize/deserialize between a POJO (Plain
Old Java Object) and a Jackson JsonNode
. To convert an object from a JsonNode into a desired object:
UserResource user = JsonUtils.nodeToValue(objectNode, UserResource.class);
To convert an object into a Jackson JsonNode (or subtype of JsonNode, such as ObjectNode):
ObjectNode node = JsonUtils.valueToNode(object);
Note that most SCIM SDK objects can easily be converted to a String by calling the toString()
method.