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 referenceUser
instances would be in thegw.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 method declaration must return
- 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.
- The method declaration's input parameter must be set to
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:
- Implement a concrete subclass of
AbstractKeyableBeanJsonValueResolver
. - Add the following to your updater declaration:
typename
set to your value resolver.resolvedValueToAncestorPath
set to the path from the foreign key entity to the common ancestorrootToAncestor
set to the path from the root entity to the common ancestor