This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new 8c190d643f [SYNCOPE-1944] Fixing derived attribute management for 
memberships
8c190d643f is described below

commit 8c190d643f8ba66f203203f72163fa0046831611
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Thu Jan 15 16:38:38 2026 +0100

    [SYNCOPE-1944] Fixing derived attribute management for memberships
---
 .../core/provisioning/api/DerAttrHandler.java      |  60 +++++-----
 .../provisioning/api/jexl/JexlContextBuilder.java  |   5 +-
 .../core/provisioning/api/jexl/JexlUtilsTest.java  |  10 +-
 .../provisioning/java/DefaultDerAttrHandler.java   | 124 ++++++++++++---------
 .../provisioning/java/DefaultMappingManager.java   |  10 +-
 .../core/provisioning/java/data/AnyDataBinder.java |  13 +--
 .../java/data/RealmDataBinderImpl.java             |   2 +-
 .../notification/DefaultNotificationManager.java   |   6 +-
 .../java/DefaultMappingManagerTest.java            |   9 +-
 .../apache/syncope/fit/core/MembershipITCase.java  |  27 +++++
 10 files changed, 159 insertions(+), 107 deletions(-)

diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java
index 395e2c82d4..b910c86954 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java
@@ -30,30 +30,21 @@ import 
org.apache.syncope.core.persistence.api.entity.Relationship;
 public interface DerAttrHandler {
 
     /**
-     * Calculates derived attribute value associated to the given realm, for 
the given derived schema.
+     * Calculates derived attributes values associated to the given realm.
      *
      * @param realm realm
-     * @param schema derived schema
-     * @return derived attribute value
+     * @return derived attribute values
      */
-    String getValue(Realm realm, DerSchema schema);
+    Map<String, String> getValues(Realm realm);
 
     /**
-     * Calculates derived attribute value associated to the given any, for the 
given derived schema.
+     * Calculates derived attribute value associated to the given realm, for 
the given derived schema.
      *
-     * @param any any object
+     * @param realm realm
      * @param schema derived schema
      * @return derived attribute value
      */
-    String getValue(Any any, DerSchema schema);
-
-    /**
-     * Calculates derived attributes values associated to the given realm.
-     *
-     * @param realm realm
-     * @return derived attribute values
-     */
-    Map<DerSchema, String> getValues(Realm realm);
+    String getValue(Realm realm, DerSchema schema);
 
     /**
      * Calculates derived attributes values associated to the given any.
@@ -61,45 +52,54 @@ public interface DerAttrHandler {
      * @param any any object
      * @return derived attribute values
      */
-    Map<DerSchema, String> getValues(Any any);
+    Map<String, String> getValues(Any any);
 
     /**
-     * Calculates derived attribute value associated to the given any, for the 
given membership and
-     * derived schema.
+     * Calculates derived attribute value associated to the given any, for the 
given derived schema.
      *
      * @param any any object
-     * @param membership membership
      * @param schema derived schema
      * @return derived attribute value
      */
-    String getValue(Any any, Membership<?> membership, DerSchema schema);
+    String getValue(Any any, DerSchema schema);
 
     /**
-     * Calculates derived attributes values associated to the given any, for 
the given membership.
+     * Calculates derived attributes values associated to the given groupable, 
for the given membership.
      *
-     * @param any any object
+     * @param groupable user or any object
      * @param membership membership
      * @return derived attribute values
      */
-    Map<DerSchema, String> getValues(Groupable<?, ?, ?> any, Membership<?> 
membership);
+    Map<String, String> getValues(Groupable<?, ?, ?> groupable, Membership<?> 
membership);
 
     /**
-     * Calculates derived attribute value associated to the given any, for the 
given relationship and
+     * Calculates derived attribute value associated to the given groupable, 
for the given membership and
      * derived schema.
      *
-     * @param any any object
-     * @param relationship relationship
+     * @param groupable user or any object
+     * @param membership membership
      * @param schema derived schema
      * @return derived attribute value
      */
-    String getValue(Any any, Relationship<?, ?> relationship, DerSchema 
schema);
+    String getValue(Groupable<?, ?, ?> groupable, Membership<?> membership, 
DerSchema schema);
 
     /**
-     * Calculates derived attributes values associated to the given any, for 
the given relationship.
+     * Calculates derived attributes values associated to the given relatable, 
for the given relationship.
      *
-     * @param any any object
+     * @param relatable user, group or any object
      * @param relationship relationship
      * @return derived attribute values
      */
-    Map<DerSchema, String> getValues(Relatable<?, ?> any, Relationship<?, ?> 
relationship);
+    Map<String, String> getValues(Relatable<?, ?> relatable, Relationship<?, 
?> relationship);
+
+    /**
+     * Calculates derived attribute value associated to the given relatable, 
for the given relationship and
+     * derived schema.
+     *
+     * @param relatable user, group or any object
+     * @param relationship relationship
+     * @param schema derived schema
+     * @return derived attribute value
+     */
+    String getValue(Relatable<?, ?> relatable, Relationship<?, ?> 
relationship, DerSchema schema);
 }
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlContextBuilder.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlContextBuilder.java
index 269ec784e8..bed2130497 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlContextBuilder.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/jexl/JexlContextBuilder.java
@@ -41,7 +41,6 @@ import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.Attributable;
-import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.utils.FormatUtils;
@@ -187,13 +186,13 @@ public class JexlContextBuilder {
     }
 
     public JexlContextBuilder derAttrs(final Attributable attributable, final 
DerAttrHandler derAttrHandler) {
-        Map<DerSchema, String> derAttrs = attributable instanceof Realm realm
+        Map<String, String> derAttrs = attributable instanceof Realm realm
                 ? derAttrHandler.getValues(realm)
                 : attributable instanceof Any any
                         ? derAttrHandler.getValues(any)
                         : Map.of();
 
-        derAttrs.forEach((schema, value) -> jexlContext.set(schema.getKey(), 
value));
+        derAttrs.forEach((schema, value) -> jexlContext.set(schema, value));
 
         return this;
     }
diff --git 
a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtilsTest.java
 
b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtilsTest.java
index 5ccaad0c27..39cae5985f 100644
--- 
a/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtilsTest.java
+++ 
b/core/provisioning-api/src/test/java/org/apache/syncope/core/provisioning/api/jexl/JexlUtilsTest.java
@@ -147,8 +147,8 @@ public class JexlUtilsTest extends AbstractTest {
 
         String expression = null;
 
-        Map<DerSchema, String> derAttrs = new HashMap<>();
-        derAttrs.put(derSchema, expression);
+        Map<String, String> derAttrs = new HashMap<>();
+        derAttrs.put("derSchema", expression);
 
         when(derAttrHandler.getValues(any(Any.class))).thenReturn(derAttrs);
 
@@ -156,7 +156,7 @@ public class JexlUtilsTest extends AbstractTest {
         ReflectionTestUtils.setField(builder, "jexlContext", context);
 
         builder.derAttrs(any, derAttrHandler);
-        verify(context).set(derAttrs.get(derSchema), expression);
+        verify(context).set("derSchema", expression);
     }
 
     @Test
@@ -168,8 +168,8 @@ public class JexlUtilsTest extends AbstractTest {
 
         String expression = null;
 
-        Map<DerSchema, String> derAttrs = new HashMap<>();
-        derAttrs.put(derSchema, expression);
+        Map<String, String> derAttrs = new HashMap<>();
+        derAttrs.put("derSchema", expression);
 
         when(any.getPlainAttrs()).thenReturn(new ArrayList<>());
         when(derAttrHandler.getValues(any(Any.class))).thenReturn(derAttrs);
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultDerAttrHandler.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultDerAttrHandler.java
index 8d56f41db6..015c365781 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultDerAttrHandler.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultDerAttrHandler.java
@@ -54,11 +54,11 @@ public class DefaultDerAttrHandler implements 
DerAttrHandler {
         this.jexlTools = jexlTools;
     }
 
-    protected Map<DerSchema, String> getValues(
+    protected Map<String, String> getValues(
             final Attributable attributable,
             final Collection<? extends DerSchema> schemas) {
 
-        Map<DerSchema, String> result = new HashMap<>(schemas.size());
+        Map<String, String> result = new HashMap<>(schemas.size());
 
         schemas.forEach(schema -> {
             JexlContext jexlContext = new JexlContextBuilder().
@@ -66,12 +66,20 @@ public class DefaultDerAttrHandler implements 
DerAttrHandler {
                     fields(attributable).
                     build();
 
-            result.put(schema, 
jexlTools.evaluateExpression(schema.getExpression(), jexlContext).toString());
+            result.put(schema.getKey(), 
jexlTools.evaluateExpression(schema.getExpression(), jexlContext).toString());
         });
 
         return result;
     }
 
+    @Override
+    public Map<String, String> getValues(final Realm realm) {
+        return getValues(
+                realm,
+                realm.getAnyTypeClasses().stream().
+                        flatMap(atc -> 
atc.getDerSchemas().stream()).collect(Collectors.toSet()));
+    }
+
     @Override
     public String getValue(final Realm realm, final DerSchema schema) {
         if (realm.getAnyTypeClasses().stream().flatMap(atc -> 
atc.getDerSchemas().stream()).anyMatch(schema::equals)) {
@@ -79,91 +87,105 @@ public class DefaultDerAttrHandler implements 
DerAttrHandler {
             return null;
         }
 
-        return getValues(realm, Set.of(schema)).get(schema);
+        return getValues(realm, Set.of(schema)).get(schema.getKey());
     }
 
     @Override
-    public String getValue(final Any any, final DerSchema schema) {
-        if (!anyUtilsFactory.getInstance(any).dao().findAllowedSchemas(any, 
DerSchema.class).selfContains(schema)) {
-            LOG.debug("{} not allowed for {}", schema, any);
-            return null;
-        }
-
-        return getValues(any, Set.of(schema)).get(schema);
+    public Map<String, String> getValues(final Any any) {
+        return getValues(
+                any,
+                anyUtilsFactory.getInstance(any).dao().findAllowedSchemas(any, 
DerSchema.class).self());
     }
 
     @Override
-    public String getValue(final Any any, final Membership<?> membership, 
final DerSchema schema) {
-        if (!anyUtilsFactory.getInstance(any).dao().
-                findAllowedSchemas(any, 
DerSchema.class).membershipsContains(membership.getRightEnd(), schema)) {
-
+    public String getValue(final Any any, final DerSchema schema) {
+        if (!anyUtilsFactory.getInstance(any).dao().findAllowedSchemas(any, 
DerSchema.class).selfContains(schema)) {
             LOG.debug("{} not allowed for {}", schema, any);
             return null;
         }
 
-        return getValues(any, Set.of(schema)).get(schema);
+        return getValues(any, Set.of(schema)).get(schema.getKey());
     }
 
-    @Override
-    public Map<DerSchema, String> getValues(final Realm realm) {
-        return getValues(
-                realm,
-                realm.getAnyTypeClasses().stream().
-                        flatMap(atc -> 
atc.getDerSchemas().stream()).collect(Collectors.toSet()));
-    }
+    protected Map<String, String> getValues(
+            final Groupable<?, ?, ?> groupable,
+            final Membership<?> membership,
+            final Set<DerSchema> schemas) {
 
-    @Override
-    public Map<DerSchema, String> getValues(final Any any) {
-        return getValues(
-                any,
-                anyUtilsFactory.getInstance(any).dao().findAllowedSchemas(any, 
DerSchema.class).self());
-    }
-
-    @Override
-    public Map<DerSchema, String> getValues(final Groupable<?, ?, ?> any, 
final Membership<?> membership) {
-        Set<DerSchema> schemas = anyUtilsFactory.getInstance(any).dao().
-                findAllowedSchemas(any, 
DerSchema.class).membership(membership.getRightEnd());
-        Map<DerSchema, String> result = new HashMap<>(schemas.size());
+        Map<String, String> result = new HashMap<>(schemas.size());
 
         schemas.forEach(schema -> {
             JexlContext jexlContext = new JexlContextBuilder().
-                    plainAttrs(any.getPlainAttrs(membership)).
-                    fields(any).
+                    plainAttrs(groupable.getPlainAttrs(membership)).
+                    fields(groupable).
                     build();
 
-            result.put(schema, 
jexlTools.evaluateExpression(schema.getExpression(), jexlContext).toString());
+            result.put(schema.getKey(), 
jexlTools.evaluateExpression(schema.getExpression(), jexlContext).toString());
         });
 
         return result;
     }
 
     @Override
-    public String getValue(final Any any, final Relationship<?, ?> 
relationship, final DerSchema schema) {
-        if (!anyUtilsFactory.getInstance(any).dao().
-                findAllowedSchemas(any, 
DerSchema.class).relationshipTypesContains(relationship.getType(), schema)) {
+    public Map<String, String> getValues(final Groupable<?, ?, ?> groupable, 
final Membership<?> membership) {
+        Set<DerSchema> schemas = anyUtilsFactory.getInstance(groupable).dao().
+                findAllowedSchemas(groupable, 
DerSchema.class).membership(membership.getRightEnd());
+        return getValues(groupable, membership, schemas);
+    }
 
-            LOG.debug("{} not allowed for {}", schema, any);
+    @Override
+    public String getValue(final Groupable<?, ?, ?> groupable, final 
Membership<?> membership, final DerSchema schema) {
+        if (!anyUtilsFactory.getInstance(groupable).dao().
+                findAllowedSchemas(groupable, DerSchema.class).
+                membership(membership.getRightEnd()).contains(schema)) {
+
+            LOG.debug("{} not allowed for {}", schema, groupable);
             return null;
         }
 
-        return getValues(any, Set.of(schema)).get(schema);
+        return getValues(groupable, membership, 
Set.of(schema)).get(schema.getKey());
     }
 
-    @Override
-    public Map<DerSchema, String> getValues(final Relatable<?, ?> any, final 
Relationship<?, ?> relationship) {
-        Set<DerSchema> schemas = anyUtilsFactory.getInstance(any).dao().
-                findAllowedSchemas(any, 
DerSchema.class).relationshipType(relationship.getType());
-        Map<DerSchema, String> result = new HashMap<>(schemas.size());
+    protected Map<String, String> getValues(
+            final Relatable<?, ?> relatable,
+            final Relationship<?, ?> relationship,
+            final Set<DerSchema> schemas) {
+
+        Map<String, String> result = new HashMap<>(schemas.size());
 
         schemas.forEach(schema -> {
             JexlContext jexlContext = new JexlContextBuilder().
-                    plainAttrs(any.getPlainAttrs(relationship)).
-                    fields(any).
+                    plainAttrs(relatable.getPlainAttrs(relationship)).
+                    fields(relatable).
                     build();
 
-            result.put(schema, 
jexlTools.evaluateExpression(schema.getExpression(), jexlContext).toString());
+            result.put(schema.getKey(), 
jexlTools.evaluateExpression(schema.getExpression(), jexlContext).toString());
         });
 
         return result;
     }
+
+    @Override
+    public Map<String, String> getValues(final Relatable<?, ?> relatable, 
final Relationship<?, ?> relationship) {
+        Set<DerSchema> schemas = anyUtilsFactory.getInstance(relatable).dao().
+                findAllowedSchemas(relatable, 
DerSchema.class).relationshipType(relationship.getType());
+        return getValues(relatable, relationship, schemas);
+    }
+
+    @Override
+    public String getValue(
+            final Relatable<?, ?> relatable,
+            final Relationship<?, ?> relationship,
+            final DerSchema schema) {
+
+        if (!anyUtilsFactory.getInstance(relatable).dao().
+                findAllowedSchemas(relatable, DerSchema.class).
+                relationshipTypesContains(relationship.getType(), schema)) {
+
+            LOG.debug("{} not allowed for {}", schema, relatable);
+            return null;
+        }
+
+        return getValues(relatable, relationship, 
Set.of(schema)).get(schema.getKey());
+    }
 }
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultMappingManager.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultMappingManager.java
index d447634095..c303c634b6 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultMappingManager.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultMappingManager.java
@@ -271,7 +271,11 @@ public class DefaultMappingManager implements 
MappingManager {
         String connObjectLink = orgUnit.getConnObjectLink();
         String evalConnObjectLink = null;
         if (StringUtils.isNotBlank(connObjectLink)) {
-            JexlContext jexlContext = new 
JexlContextBuilder().fields(realm).build();
+            JexlContext jexlContext = new JexlContextBuilder().
+                    fields(realm).
+                    plainAttrs(realm.getPlainAttrs()).
+                    derAttrs(realm, derAttrHandler).
+                    build();
 
             evalConnObjectLink = jexlTools.evaluateExpression(connObjectLink, 
jexlContext).toString();
         }
@@ -830,8 +834,8 @@ public class DefaultMappingManager implements 
MappingManager {
                         String derValue = membership == null && relationship 
== null
                                 ? derAttrHandler.getValue(ref, derSchema)
                                 : membership == null
-                                        ? derAttrHandler.getValue(ref, 
relationship, derSchema)
-                                        : derAttrHandler.getValue(ref, 
membership, derSchema);
+                                        ? 
derAttrHandler.getValue((Relatable<?, ?>) ref, relationship, derSchema)
+                                        : 
derAttrHandler.getValue((Groupable<?, ?, ?>) ref, membership, derSchema);
                         if (derValue != null) {
                             PlainAttrValue attrValue = new PlainAttrValue();
                             attrValue.setStringValue(derValue);
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
index 1563e9cba1..c26a1b8b65 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
@@ -64,7 +64,6 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.Groupable;
@@ -100,7 +99,7 @@ abstract class AnyDataBinder extends AttributableDataBinder {
             final String realmFullPath,
             final Collection<? extends AnyTypeClass> auxClasses,
             final Collection<PlainAttr> plainAttrs,
-            final Map<DerSchema, String> derAttrs,
+            final Map<String, String> derAttrs,
             final Collection<? extends ExternalResource> resources) {
 
         anyTO.setRealm(realmFullPath);
@@ -111,14 +110,14 @@ abstract class AnyDataBinder extends 
AttributableDataBinder {
                 add(new 
Attr.Builder(plainAttr.getSchema()).values(plainAttr.getValuesAsStrings()).build()));
 
         derAttrs.forEach((schema, value) -> anyTO.getDerAttrs().
-                add(new Attr.Builder(schema.getKey()).value(value).build()));
+                add(new Attr.Builder(schema).value(value).build()));
 
         
anyTO.getResources().addAll(resources.stream().map(ExternalResource::getKey).collect(Collectors.toSet()));
     }
 
     protected static RelationshipTO getRelationshipTO(
             final Collection<PlainAttr> plainAttrs,
-            final Map<DerSchema, String> derAttrs,
+            final Map<String, String> derAttrs,
             final String relationshipType,
             final RelationshipTO.End end,
             final Any otherEnd) {
@@ -137,14 +136,14 @@ abstract class AnyDataBinder extends 
AttributableDataBinder {
                 add(new 
Attr.Builder(plainAttr.getSchema()).values(plainAttr.getValuesAsStrings()).build()));
 
         derAttrs.forEach((schema, value) -> relationshipTO.getDerAttrs().
-                add(new Attr.Builder(schema.getKey()).value(value).build()));
+                add(new Attr.Builder(schema).value(value).build()));
 
         return relationshipTO;
     }
 
     protected static MembershipTO getMembershipTO(
             final Collection<PlainAttr> plainAttrs,
-            final Map<DerSchema, String> derAttrs,
+            final Map<String, String> derAttrs,
             final Membership<? extends Any> membership) {
 
         MembershipTO membershipTO = new 
MembershipTO.Builder(membership.getRightEnd().getKey()).
@@ -154,7 +153,7 @@ abstract class AnyDataBinder extends AttributableDataBinder 
{
                 add(new 
Attr.Builder(plainAttr.getSchema()).values(plainAttr.getValuesAsStrings()).build()));
 
         derAttrs.forEach((schema, value) -> membershipTO.getDerAttrs().
-                add(new Attr.Builder(schema.getKey()).value(value).build()));
+                add(new Attr.Builder(schema).value(value).build()));
 
         return membershipTO;
     }
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
index 248d2a18e1..893411d0ad 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
@@ -359,7 +359,7 @@ public class RealmDataBinderImpl extends 
AttributableDataBinder implements Realm
                 add(new 
Attr.Builder(plainAttr.getSchema()).values(plainAttr.getValuesAsStrings()).build()));
 
         derAttrHandler.getValues(realm).forEach((schema, value) -> 
realmTO.getDerAttrs().
-                add(new Attr.Builder(schema.getKey()).value(value).build()));
+                add(new Attr.Builder(schema).value(value).build()));
 
         if (admin) {
             
Optional.ofNullable(realm.getAccountPolicy()).map(AccountPolicy::getKey).
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/DefaultNotificationManager.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/DefaultNotificationManager.java
index 8553f3b01d..951006a4b1 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/DefaultNotificationManager.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/DefaultNotificationManager.java
@@ -54,8 +54,10 @@ import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.Groupable;
 import org.apache.syncope.core.persistence.api.entity.Notification;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.Relatable;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
@@ -414,8 +416,8 @@ public class DefaultNotificationManager implements 
NotificationManager {
                             map(derSchema -> membership == null && 
relationship.get() == null
                             ? derAttrHandler.getValue(user, derSchema)
                             : relationship.get() == null
-                            ? derAttrHandler.getValue(user, membership, 
derSchema)
-                            : derAttrHandler.getValue(user, 
relationship.get(), derSchema)).
+                            ? derAttrHandler.getValue((Groupable<?, ?, ?>) 
user, membership, derSchema)
+                            : derAttrHandler.getValue((Relatable<?, ?>) user, 
relationship.get(), derSchema)).
                             orElse(null);
                 }
 
diff --git 
a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/DefaultMappingManagerTest.java
 
b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/DefaultMappingManagerTest.java
index 57d692715d..95561f9e71 100644
--- 
a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/DefaultMappingManagerTest.java
+++ 
b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/DefaultMappingManagerTest.java
@@ -83,7 +83,7 @@ public class DefaultMappingManagerTest extends AbstractTest {
     public void prepareAttrsForUser() {
         User bellini = userDAO.findByUsername("bellini").orElseThrow();
         ExternalResource ldap = 
resourceDAO.findById("resource-ldap").orElseThrow();
-        Provision provision = 
ldap.getProvisionByAnyType(AnyTypeKind.USER.name()).get();
+        Provision provision = 
ldap.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow();
 
         assertNotEquals(CipherAlgorithm.AES, bellini.getCipherAlgorithm());
 
@@ -161,7 +161,7 @@ public class DefaultMappingManagerTest extends AbstractTest 
{
     public void prepareAttrsForLinkedAccount() {
         User vivaldi = userDAO.findByUsername("vivaldi").orElseThrow();
         ExternalResource ldap = 
resourceDAO.findById("resource-ldap").orElseThrow();
-        Provision provision = 
ldap.getProvisionByAnyType(AnyTypeKind.USER.name()).get();
+        Provision provision = 
ldap.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow();
 
         LinkedAccount account = entityFactory.newEntity(LinkedAccount.class);
         account.setConnObjectKeyValue("admin");
@@ -264,13 +264,12 @@ public class DefaultMappingManagerTest extends 
AbstractTest {
 
         entityManager.flush();
 
-        // 2. verify that dynamic membership is in place
+        // 2. verify that dynamic membership is effective
         assertTrue(userDAO.findAllGroupKeys(user).contains(group.getKey()));
 
         // 3. check propagation attrs
         ExternalResource csv = 
resourceDAO.findById("resource-csv").orElseThrow();
-        Provision provision = 
csv.getProvisionByAnyType(AnyTypeKind.USER.name()).get();
-        assertNotNull(provision);
+        Provision provision = 
csv.getProvisionByAnyType(AnyTypeKind.USER.name()).orElseThrow();
 
         MappingManager.PreparedAttrs attrs = 
mappingManager.prepareAttrsFromAny(
                 user,
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
index 9787364315..95f3f4bd8f 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
@@ -341,4 +341,31 @@ public class MembershipITCase extends AbstractITCase {
             assertEquals(ClientExceptionType.InvalidMembership, e.getType());
         }
     }
+
+    @Test
+    public void issueSYNCOPE1944() {
+        TypeExtensionTO typeExt = new TypeExtensionTO();
+        typeExt.setAnyType(AnyTypeKind.USER.name());
+        typeExt.getAuxClasses().add("minimal user");
+
+        GroupCR gcr = GroupITCase.getBasicSample("syncope1944");
+        gcr.getTypeExtensions().add(typeExt);
+
+        GroupTO group = createGroup(gcr).getEntity();
+        assertNotNull(group.getKey());
+
+        UserCR ucr = 
UserITCase.getUniqueSample("[email protected]");
+        ucr.getMemberships().add(new MembershipTO.Builder(group.getKey()).
+                plainAttr(attr("fullname", ucr.getUsername())).
+                plainAttr(attr("userId", ucr.getUsername())).
+                plainAttr(attr("firstname", "Galileo")).
+                plainAttr(attr("surname", "Galilei")).build());
+
+        UserTO user = createUser(ucr).getEntity();
+        assertNotNull(user.getKey());
+
+        assertEquals(
+                "Galilei, Galileo",
+                
user.getMembership(group.getKey()).orElseThrow().getDerAttr("cn").orElseThrow().getValues().getFirst());
+    }
 }

Reply via email to