Update case 3: Accessibility of resolved value is conditional

Making access to a resolved object conditional

In some cases, a foreign key field can reference a given object only if the object meets certain criteria. For example, suppose that the Activity entity has an ApprovalManager_Ext field. This field identifies the manager of the activity, who is responsible for addressing the situation when an activity is still open past its due date. The ApprovalManager_Ext field is set to a User, but it can only be set to a User who has the "Manager" role.

When you configure a foreign key in Cloud API, you can specify this type of conditional foreign key logic. This is done in a layer of logic known as "isEntityViewable logic". This optional logic specifies that you can set a foreign key property to an object only if the object meets certain conditions.

The KeyableBeanJsonValueResolver does not have any isEntityViewable logic. If you want to implement isEntityViewable logic for a custom foreign key, you must use the AbstractKeyableBeanJsonValueResolver.

The AbstractKeyableBeanJsonValueResolver

The AbstractKeyableBeanJsonValueResolver is abstract and therefore is never used directly. If you want to specify isEntityViewable logic, you must implement a concrete subclass of this resolver. The subclass has an isEntityViewable method where you can specify your logic. You then reference this subclass in the appropriate updater file.

Extending the AbstractKeyableBeanJsonValueResolver

When you extend the AbstractKeyableBeanJsonValueResolver, do the following.

  • Guidewire recommends putting the class in the gw.rest.ext.pc.<api>.v1 package. Guidewire also recommends putting the class in a sub-package named after the resolved value. For example, a resolver used for foreign keys that reference User instances would be in the gw.rest.ext.pc.common.v1.users package.
  • Guidewire recommends you name the class <ResolvedEntity>ExtJsonValueResolver.
  • The class must extend AbstractKeyableBeanJsonValueResolver<V>, where "V" is the entity type of the resolved value. (For example, AbstractKeyableBeanJsonValueResolver<User>.)
  • The class must include the @NotNull annotation.
  • The class must override the ResolvedValueType method.
    • The method declaration must return Class<V>, where "V" is the entity type of the resolved value. (For example, Class<User>.)
    • The method must return V. (For example, return User)
  • The class must override the isEntityViewable method.
    • The method declaration's input parameter must be set to keyableBean: V, where "V" is the entity type of the resolved value. (For example, keyableBean : User.)
    • The method must return a Boolean value.
      • Returning true indicates the resolved value is accessible, and the corresponding foreign key property can be set to it.
      • Returning false indicates the resolved value is not accessible, and the corresponding foreign key property cannot be set to it.

For example, suppose that the Activity entity has an ApprovalManager_Ext field. This field identifies the manager of the activity, who is responsible for addressing the situation when an activity is still open past its due date. The ApprovalManager_Ext field is set to a User, but it can only be set to a user who has the "Manager" role. The value resolver for this business requirement would be as follows.

package gw.rest.ext.xc.common.v1.users

uses gw.rest.core.pl.framework.v1.refs.AbstractKeyableBeanJsonValueResolver
uses org.jetbrains.annotations.NotNull

class UserExtJsonValueResolver extends AbstractKeyableBeanJsonValueResolver<User> {

  @NotNull
  protected override property get ResolvedValueType() : Class<User> {
    return User
  }

  protected override function isEntityViewable(keyableBean : User) : boolean {
    return keyableBean.Roles.hasMatch(\role -> role.Role.Name == "Manager")
  }
}

Extending the updater

The mapper must have a valueResolver property whose typeName is set to the concrete subclass of AbstractKeyableBeanJsonValueResolver. For example, the updater from the previous example would be as follows:

"updaters": {
  "Activity": {
    "properties": {
      ...
      "activityManager_Ext": {
        "path": "Activity.ActivityManager_Ext",
        "valueResolver": {
          "typeName": "gw.rest.ext.cc.common.v1.users.UserExtJsonValueResolver"
        }
      }

Validation when the foreign key resource is not accessible

If you try to set a foreign key property to a resource, and the value resolver's isEntityViewable method returns false, an error similar to the following is returned:

data.attributes.activityManager_Ext.id - The id 'demo_sample:2' is not a valid 'User'",

Using isEntityViewable logic with common ancestors

You can create a foreign key field that makes use of isEntityViewable logic and that requires the foreign key entity to share a common ancestor. To do this:

  1. Implement a concrete subclass of AbstractKeyableBeanJsonValueResolver.
  2. Add the following to your updater declaration:
    1. typename set to your value resolver.
    2. resolvedValueToAncestorPath set to the path from the foreign key entity to the common ancestor
    3. rootToAncestor set to the path from the root entity to the common ancestor