diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 75b4b73..ac285a8 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -741,6 +741,21 @@ public class RepresentationToModel {
if (rep.getRealm() != null) {
renameRealm(realm, rep.getRealm());
}
+
+ // Import attributes first, so the stuff saved directly on representation (displayName, bruteForce etc) has bigger priority
+ if (rep.getAttributes() != null) {
+ Set<String> attrsToRemove = new HashSet<>(realm.getAttributes().keySet());
+ attrsToRemove.removeAll(rep.getAttributes().keySet());
+
+ for (Map.Entry<String, String> entry : rep.getAttributes().entrySet()) {
+ realm.setAttribute(entry.getKey(), entry.getValue());
+ }
+
+ for (String attr : attrsToRemove) {
+ realm.removeAttribute(attr);
+ }
+ }
+
if (rep.getDisplayName() != null) realm.setDisplayName(rep.getDisplayName());
if (rep.getDisplayNameHtml() != null) realm.setDisplayNameHtml(rep.getDisplayNameHtml());
if (rep.isEnabled() != null) realm.setEnabled(rep.isEnabled());
@@ -843,13 +858,6 @@ public class RepresentationToModel {
if (rep.getClientAuthenticationFlow() != null) {
realm.setClientAuthenticationFlow(realm.getFlowByAlias(rep.getClientAuthenticationFlow()));
}
-
- if (rep.getAttributes() != null) {
- for (Map.Entry<String, String> entry : rep.getAttributes().entrySet()) {
- realm.setAttribute(entry.getKey(), entry.getValue());
- }
- }
-
}
// Basic realm stuff
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
index 5bf2cc1..53a3615 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/realm/RealmTest.java
@@ -239,15 +239,6 @@ public class RealmTest extends AbstractAdminTest {
assertEquals(Boolean.FALSE, rep.isRegistrationEmailAsUsername());
assertEquals(Boolean.FALSE, rep.isEditUsernameAllowed());
- // attributes
- rep.getAttributes().put("foo", "bar");
-
- realm.update(rep);
- assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);
-
- rep = realm.toRepresentation();
- assertEquals("bar", rep.getAttributes().get("foo"));
-
}
@Test
@@ -278,6 +269,45 @@ public class RealmTest extends AbstractAdminTest {
}
@Test
+ public void updateRealmAttributes() {
+ // first change
+ RealmRepresentation rep = new RealmRepresentation();
+ rep.setAttributes(new HashMap<>());
+ rep.getAttributes().put("foo1", "bar1");
+ rep.getAttributes().put("foo2", "bar2");
+
+ rep.setBruteForceProtected(true);
+ rep.setDisplayName("dn1");
+
+ realm.update(rep);
+ assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);
+
+ rep = realm.toRepresentation();
+
+ assertEquals("bar1", rep.getAttributes().get("foo1"));
+ assertEquals("bar2", rep.getAttributes().get("foo2"));
+ assertTrue(rep.isBruteForceProtected());
+ assertEquals("dn1", rep.getDisplayName());
+
+ // second change
+ rep.setBruteForceProtected(false);
+ rep.setDisplayName("dn2");
+ rep.getAttributes().put("foo1", "bar11");
+ rep.getAttributes().remove("foo2");
+
+ realm.update(rep);
+ assertAdminEvents.assertEvent(realmId, OperationType.UPDATE, Matchers.nullValue(String.class), rep, ResourceType.REALM);
+
+ rep = realm.toRepresentation();
+
+ assertFalse(rep.isBruteForceProtected());
+ assertEquals("dn2", rep.getDisplayName());
+
+ assertEquals("bar11", rep.getAttributes().get("foo1"));
+ assertFalse(rep.getAttributes().containsKey("foo2"));
+ }
+
+ @Test
public void getRealmRepresentation() {
RealmRepresentation rep = realm.toRepresentation();
Assert.assertEquals(REALM_NAME, rep.getRealm());