You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2021/08/14 18:44:21 UTC

[syncope] branch master updated (f6a3430 -> 8a2ef9f)

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

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


    from f6a3430  Upgrading Nimbus JOSE JWT and SLF4J
     new 6e69957  [SYNCOPE-1639] Replacing HashSet with TreeSet + Comparable
     new 8a2ef9f  [SYNCOPE-1640] fixed removal of empty enumeration key on multivalue p… (#286)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../client/console/audit/AuditHistoryDetails.java  | 80 +++++++++++++++++++++-
 .../client/console/commons/PropertyList.java       | 16 ++---
 .../client/console/panels/PlainSchemaDetails.java  |  2 +-
 .../wicket/markup/html/form/JsonDiffPanel.java     | 14 ++--
 .../java/org/apache/syncope/common/lib/Attr.java   | 13 +++-
 .../org/apache/syncope/common/lib/to/AnyTO.java    | 12 ++--
 .../apache/syncope/common/lib/to/ConnObjectTO.java |  4 +-
 .../apache/syncope/common/lib/to/DelegationTO.java |  4 +-
 .../syncope/common/lib/to/LinkedAccountTO.java     |  6 +-
 .../apache/syncope/common/lib/to/MembershipTO.java |  8 +--
 .../syncope/common/lib/to/NotificationTaskTO.java  |  4 +-
 .../org/apache/syncope/common/lib/to/RealmTO.java  |  6 +-
 .../org/apache/syncope/common/lib/to/RoleTO.java   |  6 +-
 .../org/apache/syncope/common/lib/to/UserTO.java   |  4 +-
 14 files changed, 126 insertions(+), 53 deletions(-)

[syncope] 02/02: [SYNCOPE-1640] fixed removal of empty enumeration key on multivalue p… (#286)

Posted by il...@apache.org.
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

commit 8a2ef9f3d26c988d7189d01aed5f067b74e24f06
Author: Andrea Patricelli <an...@apache.org>
AuthorDate: Sat Aug 14 19:59:08 2021 +0200

    [SYNCOPE-1640] fixed removal of empty enumeration key on multivalue p… (#286)
    
    * [SYNCOPE-1640] fixed removal of empty enumeration key on multivalue param and enum schema definition
---
 .../syncope/client/console/commons/PropertyList.java     | 16 ++++------------
 .../client/console/panels/PlainSchemaDetails.java        |  2 +-
 2 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PropertyList.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PropertyList.java
index eb1e0ab..654c2e6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PropertyList.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PropertyList.java
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 
@@ -171,18 +172,9 @@ public abstract class PropertyList<T> implements List<String> {
     }
 
     public static String getEnumValuesAsString(final List<String> enumerationValues) {
-        final StringBuilder builder = new StringBuilder();
-        int index = 0;
-        for (String str : enumerationValues) {
-            if (str != null) {
-                if (index > 0) {
-                    builder.append(SyncopeConstants.ENUM_VALUES_SEPARATOR);
-                }
-                index++;
-                builder.append(str.trim());
-            }
-        }
-        return builder.toString();
+        return enumerationValues.stream().
+                map(v -> StringUtils.isEmpty(v) ? StringUtils.EMPTY : v.trim()).
+                collect(Collectors.joining(SyncopeConstants.ENUM_VALUES_SEPARATOR));
     }
 
     public static List<String> getEnumValuesAsList(final String enumerationValues) {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
index cfcf5f7..80d9244 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
@@ -171,7 +171,7 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
         }.build(
                 "enumerationKeys",
                 "enumerationKeys",
-                new AjaxTextFieldPanel("panel", "enumerationKeys", new Model<String>()));
+                new AjaxTextFieldPanel("panel", "enumerationKeys", new Model<>(null)));
 
         WebMarkupContainer enumParams = new WebMarkupContainer("enumParams");
         enumParams.setOutputMarkupPlaceholderTag(true);

[syncope] 01/02: [SYNCOPE-1639] Replacing HashSet with TreeSet + Comparable

Posted by il...@apache.org.
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

commit 6e69957c6cf33407a465ce25e5d9c926ae491610
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Sat Aug 14 19:32:57 2021 +0200

    [SYNCOPE-1639] Replacing HashSet with TreeSet + Comparable
---
 .../client/console/audit/AuditHistoryDetails.java  | 80 +++++++++++++++++++++-
 .../wicket/markup/html/form/JsonDiffPanel.java     | 14 ++--
 .../java/org/apache/syncope/common/lib/Attr.java   | 13 +++-
 .../org/apache/syncope/common/lib/to/AnyTO.java    | 12 ++--
 .../apache/syncope/common/lib/to/ConnObjectTO.java |  4 +-
 .../apache/syncope/common/lib/to/DelegationTO.java |  4 +-
 .../syncope/common/lib/to/LinkedAccountTO.java     |  6 +-
 .../apache/syncope/common/lib/to/MembershipTO.java |  8 +--
 .../syncope/common/lib/to/NotificationTaskTO.java  |  4 +-
 .../org/apache/syncope/common/lib/to/RealmTO.java  |  6 +-
 .../org/apache/syncope/common/lib/to/RoleTO.java   |  6 +-
 .../org/apache/syncope/common/lib/to/UserTO.java   |  4 +-
 12 files changed, 121 insertions(+), 40 deletions(-)

diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
index 5911ecc..937279c 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/audit/AuditHistoryDetails.java
@@ -18,10 +18,23 @@
  */
 package org.apache.syncope.client.console.audit;
 
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.StreamReadFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import java.io.IOException;
 import java.io.Serializable;
 import java.util.Date;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeMap;
+import java.util.TreeSet;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.MultilevelPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.JsonDiffPanel;
@@ -44,7 +57,68 @@ public abstract class AuditHistoryDetails<T extends Serializable> extends Multil
 
     private static final Logger LOG = LoggerFactory.getLogger(AuditHistoryDetails.class);
 
-    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private static class SortingNodeFactory extends JsonNodeFactory {
+
+        private static final long serialVersionUID = 1870252010670L;
+
+        @Override
+        public ObjectNode objectNode() {
+            return new ObjectNode(this, new TreeMap<>());
+        }
+    }
+
+    private static class SortedSetJsonSerializer extends StdSerializer<Set<?>> {
+
+        private static final long serialVersionUID = 3849059774309L;
+
+        SortedSetJsonSerializer(final Class<Set<?>> clazz) {
+            super(clazz);
+        }
+
+        @Override
+        public void serialize(
+                final Set<?> set,
+                final JsonGenerator gen,
+                final SerializerProvider sp) throws IOException {
+
+            if (set == null) {
+                gen.writeNull();
+                return;
+            }
+
+            gen.writeStartArray();
+
+            if (!set.isEmpty()) {
+                Set<?> sorted = set;
+
+                // create sorted set only if it itself is not already SortedSet
+                if (!SortedSet.class.isAssignableFrom(set.getClass())) {
+                    Object item = set.iterator().next();
+                    if (Comparable.class.isAssignableFrom(item.getClass())) {
+                        // and only if items are Comparable
+                        sorted = new TreeSet<>(set);
+                    } else {
+                        LOG.debug("Cannot sort items of type {}", item.getClass());
+                    }
+                }
+
+                for (Object item : sorted) {
+                    gen.writeObject(item);
+                }
+            }
+
+            gen.writeEndArray();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> Class<T> cast(final Class<?> aClass) {
+        return (Class<T>) aClass;
+    }
+
+    private static final ObjectMapper MAPPER = JsonMapper.builder().
+            nodeFactory(new SortingNodeFactory()).build().
+            registerModule(new SimpleModule().addSerializer(new SortedSetJsonSerializer(cast(Set.class))));
 
     public AuditHistoryDetails(
             final MultilevelPanel mlp,
@@ -114,7 +188,9 @@ public abstract class AuditHistoryDetails<T extends Serializable> extends Multil
                     ? MAPPER.readTree(auditEntry.getOutput()).get("entity").toPrettyString()
                     : auditEntry.getBefore();
 
-            T entity = MAPPER.readValue(content, reference);
+            T entity = MAPPER.reader().
+                    with(StreamReadFeature.STRICT_DUPLICATE_DETECTION).
+                    readValue(content, reference);
             if (entity instanceof UserTO) {
                 UserTO userTO = (UserTO) entity;
                 userTO.setPassword(null);
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonDiffPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonDiffPanel.java
index 8c5b80e..2ebc7bc 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonDiffPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonDiffPanel.java
@@ -30,10 +30,6 @@ public class JsonDiffPanel extends AbstractModalPanel<String> {
 
     private static final long serialVersionUID = -5110368813584745668L;
 
-    private final IModel<String> first;
-
-    private final IModel<String> second;
-
     public JsonDiffPanel(
             final BaseModal<String> modal,
             final IModel<String> first,
@@ -41,13 +37,13 @@ public class JsonDiffPanel extends AbstractModalPanel<String> {
             final PageReference pageRef) {
 
         super(modal, pageRef);
-        this.second = second;
-        this.first = first;
-        TextArea<String> jsonEditorInfoDefArea1 = new TextArea<>("jsonEditorInfo1", this.first);
-        TextArea<String> jsonEditorInfoDefArea2 = new TextArea<>("jsonEditorInfo2", this.second);
+
+        TextArea<String> jsonEditorInfoDefArea1 = new TextArea<>("jsonEditorInfo1", first);
         jsonEditorInfoDefArea1.setMarkupId("jsonEditorInfo1").setOutputMarkupPlaceholderTag(true);
-        jsonEditorInfoDefArea2.setMarkupId("jsonEditorInfo2").setOutputMarkupPlaceholderTag(true);
         add(jsonEditorInfoDefArea1);
+
+        TextArea<String> jsonEditorInfoDefArea2 = new TextArea<>("jsonEditorInfo2", second);
+        jsonEditorInfoDefArea2.setMarkupId("jsonEditorInfo2").setOutputMarkupPlaceholderTag(true);
         add(jsonEditorInfoDefArea2);
     }
 
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/Attr.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/Attr.java
index a555bff..5b920ff 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/Attr.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/Attr.java
@@ -25,10 +25,11 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import javax.ws.rs.PathParam;
+import org.apache.commons.lang3.builder.CompareToBuilder;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 
-public class Attr implements BaseBean {
+public class Attr implements Comparable<Attr>, BaseBean {
 
     private static final long serialVersionUID = 4941691338796323623L;
 
@@ -98,6 +99,16 @@ public class Attr implements BaseBean {
     }
 
     @Override
+    public int compareTo(final Attr other) {
+        return equals(other)
+                ? 0
+                : new CompareToBuilder().
+                        append(schema, other.schema).
+                        append(values, other.values).
+                        toComparison();
+    }
+
+    @Override
     public int hashCode() {
         return new HashCodeBuilder().
                 append(schema).
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
index 942ffc0..bdc9a8a 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
@@ -28,7 +28,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashSet;
+import java.util.TreeSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
@@ -82,15 +82,15 @@ public abstract class AnyTO implements EntityTO, RealmMember {
 
     private String status;
 
-    private final Set<String> auxClasses = new HashSet<>();
+    private final Set<String> auxClasses = new TreeSet<>();
 
-    private final Set<Attr> plainAttrs = new HashSet<>();
+    private final Set<Attr> plainAttrs = new TreeSet<>();
 
-    private final Set<Attr> derAttrs = new HashSet<>();
+    private final Set<Attr> derAttrs = new TreeSet<>();
 
-    private final Set<Attr> virAttrs = new HashSet<>();
+    private final Set<Attr> virAttrs = new TreeSet<>();
 
-    private final Set<String> resources = new HashSet<>();
+    private final Set<String> resources = new TreeSet<>();
 
     @Schema(name = "_class", required = true)
     public abstract String getDiscriminator();
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
index 9b72672..921364d 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
@@ -21,9 +21,9 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import java.util.LinkedHashSet;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.syncope.common.lib.Attr;
@@ -35,7 +35,7 @@ public class ConnObjectTO implements BaseBean {
 
     private String fiql;
 
-    private final Set<Attr> attrs = new LinkedHashSet<>();
+    private final Set<Attr> attrs = new TreeSet<>();
 
     public String getFiql() {
         return fiql;
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
index 3d567c2..36c75b7 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/DelegationTO.java
@@ -22,8 +22,8 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.ws.rs.PathParam;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -39,7 +39,7 @@ public class DelegationTO extends AbstractStartEndBean implements EntityTO {
 
     private String delegated;
 
-    private final Set<String> roles = new HashSet<>();
+    private final Set<String> roles = new TreeSet<>();
 
     @Schema(accessMode = Schema.AccessMode.READ_ONLY)
     @Override
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/LinkedAccountTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/LinkedAccountTO.java
index 72dd158..1d149da 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/LinkedAccountTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/LinkedAccountTO.java
@@ -21,9 +21,9 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import java.util.HashSet;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.syncope.common.lib.Attr;
@@ -78,9 +78,9 @@ public class LinkedAccountTO implements EntityTO {
 
     private boolean suspended;
 
-    private final Set<Attr> plainAttrs = new HashSet<>();
+    private final Set<Attr> plainAttrs = new TreeSet<>();
 
-    private final Set<String> privileges = new HashSet<>();
+    private final Set<String> privileges = new TreeSet<>();
 
     @Override
     public String getKey() {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
index 591f2ad..72477b2 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
@@ -26,10 +26,10 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.syncope.common.lib.BaseBean;
@@ -90,11 +90,11 @@ public class MembershipTO implements BaseBean, Attributable {
 
     private String groupName;
 
-    private final Set<Attr> plainAttrs = new HashSet<>();
+    private final Set<Attr> plainAttrs = new TreeSet<>();
 
-    private final Set<Attr> derAttrs = new HashSet<>();
+    private final Set<Attr> derAttrs = new TreeSet<>();
 
-    private final Set<Attr> virAttrs = new HashSet<>();
+    private final Set<Attr> virAttrs = new TreeSet<>();
 
     public String getGroupKey() {
         return groupKey;
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTaskTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTaskTO.java
index 18bc4ad..1036ed5 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTaskTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTaskTO.java
@@ -22,8 +22,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import java.util.HashSet;
 import java.util.Set;
+import java.util.TreeSet;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -40,7 +40,7 @@ public class NotificationTaskTO extends TaskTO {
 
     private String entityKey;
 
-    private final Set<String> recipients = new HashSet<>();
+    private final Set<String> recipients = new TreeSet<>();
 
     private String sender;
 
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
index 6e7158f..7673f17 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RealmTO.java
@@ -22,10 +22,8 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import javax.ws.rs.PathParam;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -56,7 +54,7 @@ public class RealmTO implements NamedEntityTO, TemplatableTO {
 
     private final Map<String, AnyTO> templates = new HashMap<>();
 
-    private final Set<String> resources = new HashSet<>();
+    private final List<String> resources = new ArrayList<>();
 
     @Override
     public String getKey() {
@@ -148,7 +146,7 @@ public class RealmTO implements NamedEntityTO, TemplatableTO {
 
     @JacksonXmlElementWrapper(localName = "resources")
     @JacksonXmlProperty(localName = "resource")
-    public Set<String> getResources() {
+    public List<String> getResources() {
         return resources;
     }
 
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
index 3be4d55..bf4b22e 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/RoleTO.java
@@ -21,9 +21,9 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.TreeSet;
 import javax.ws.rs.PathParam;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -34,7 +34,7 @@ public class RoleTO implements EntityTO {
 
     private String key;
 
-    private final Set<String> entitlements = new HashSet<>();
+    private final Set<String> entitlements = new TreeSet<>();
 
     private final List<String> realms = new ArrayList<>();
 
@@ -42,7 +42,7 @@ public class RoleTO implements EntityTO {
 
     private String dynMembershipCond;
 
-    private final Set<String> privileges = new HashSet<>();
+    private final Set<String> privileges = new TreeSet<>();
 
     @Override
     public String getKey() {
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
index 6b46f70..0417837 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
@@ -25,10 +25,10 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeSet;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -70,7 +70,7 @@ public class UserTO extends AnyTO implements GroupableRelatableTO {
 
     private final List<String> dynRoles = new ArrayList<>();
 
-    private final Set<String> privileges = new HashSet<>();
+    private final Set<String> privileges = new TreeSet<>();
 
     private final List<LinkedAccountTO> linkedAccounts = new ArrayList<>();