The custom attributes in realm configuration file remove the state of the realm
**Describe the bug**
If realm configuration contains any attribute in the `attributes` field, the realm state will be overwritten during its update. This leads to the fact that objects that are managed (provisioned) by the tool are forgotten, eg. clients.

**To Reproduce**
Add customer attributes in the realm config JSON, like:

```JSON
{
   ...,
   "attributes": {
       "host": "example.com"
   }
}
```
Create a client with such config and then try to delete the client from configuration and run the tool once again.

**Expected behavior**
The client removed from configuration is removed from the realm.

**Environment (please complete the following information):**
 - Keycloak Version: [11.0.3]
 - keycloak-config-cli Version: [4.0.1]
 - Java Version: [11]


diff --git a/CHANGELOG.md b/CHANGELOG.md
index 90d5ef55..f0c4d5cf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 - Print a warning if local keycloak-config-cli and keycloak are incompatible.
 - Terminate admin-cli session through `logout` REST endpoint
 
+### Fixed
+
+- Realm attributes in configuration file overwrite the realm's state when the realm is updated.
+
 ## [4.0.1] - 2021-06-19
 
 ### Changed
diff --git a/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java b/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java
index 0bd37e17..b1898b3a 100644
--- a/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java
+++ b/src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java
@@ -34,8 +34,10 @@ import javax.validation.constraints.Pattern;
 @Validated
 @SuppressWarnings({"java:S107"})
 public class ImportConfigProperties {
-    public static final String REALM_CHECKSUM_ATTRIBUTE_PREFIX_KEY = "de.adorsys.keycloak.config.import-checksum-{0}";
-    public static final String REALM_STATE_ATTRIBUTE_PREFIX_KEY = "de.adorsys.keycloak.config.state-{0}-{1}";
+
+    public static final String REALM_STATE_ATTRIBUTE_COMMON_PREFIX = "de.adorsys.keycloak.config";
+    public static final String REALM_CHECKSUM_ATTRIBUTE_PREFIX_KEY = REALM_STATE_ATTRIBUTE_COMMON_PREFIX + ".import-checksum-{0}";
+    public static final String REALM_STATE_ATTRIBUTE_PREFIX_KEY = REALM_STATE_ATTRIBUTE_COMMON_PREFIX + ".state-{0}-{1}";
 
     @NotBlank
     private final String path;
diff --git a/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java b/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java
index 2a659b9c..bb1d1e3c 100644
--- a/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java
+++ b/src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java
@@ -68,6 +68,29 @@ public class StateRepository {
         customAttributes = retrieveCustomAttributes(realmName);
     }
 
+    /**
+     * Loads custom attributes from existing ream and fill in
+     * the realm attributes with the realm configuration state values
+     * to prevent their removal, when the realm state is updated.
+     *
+     * @param realmForUpdating the {@link RealmRepresentation} instance which will be synchronized with the Keycloak
+     */
+    public void loadCustomAttributes(RealmRepresentation realmForUpdating) {
+        loadCustomAttributes(realmForUpdating.getRealm());
+
+        Map<String, String> attributes = realmForUpdating.getAttributes();
+
+        if (attributes == null) {
+            // There is no need to fill the state in, since it will not be overwritten
+            return;
+        }
+
+        customAttributes.entrySet()
+                .stream()
+                .filter(e -> e.getKey().startsWith(ImportConfigProperties.REALM_STATE_ATTRIBUTE_COMMON_PREFIX))
+                .forEach(e -> attributes.put(e.getKey(), e.getValue()));
+    }
+
     public List<String> getState(String entity) {
         List<String> stateValues = new ArrayList<>();
 
diff --git a/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java b/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java
index f606ae27..b513240f 100644
--- a/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java
+++ b/src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java
@@ -178,6 +178,7 @@ public class RealmImportService {
         // refresh the access token to update the scopes. See: https://github.com/adorsys/keycloak-config-cli/issues/339
         keycloakProvider.refreshToken();
 
+        stateService.loadState(realmImport);
         configureRealm(realmImport, realm);
     }
 
@@ -185,14 +186,17 @@ public class RealmImportService {
         logger.debug("Updating realm '{}'...", realmImport.getRealm());
 
         RealmRepresentation realm = CloneUtil.deepClone(realmImport, RealmRepresentation.class, ignoredPropertiesForRealmImport);
+
+        // The state must be loaded before we update realm to prevent
+        // the state erasure by custom attributes from configuration
+        stateService.loadState(realm);
+
         realmRepository.update(realm);
 
         configureRealm(realmImport, realm);
     }
 
     private void configureRealm(RealmImport realmImport, RealmRepresentation existingRealm) {
-        stateService.loadState(realmImport);
-
         clientScopeImportService.doImport(realmImport);
         clientScopeImportService.updateDefaultClientScopes(realmImport, existingRealm);
         clientImportService.doImport(realmImport);
diff --git a/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java b/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java
index b3e53937..08fafde8 100644
--- a/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java
+++ b/src/main/java/de/adorsys/keycloak/config/service/state/StateService.java
@@ -52,6 +52,16 @@ public class StateService {
         stateRepository.loadCustomAttributes(realmImport.getRealm());
     }
 
+    /**
+     * Loads the realm states and preserves it into the realm representation object
+     * to prevent state erasure during realm update
+     *
+     * @param realmImport the {@link RealmRepresentation} instance which will be synchronized with the Keycloak
+     */
+    public void loadState(RealmRepresentation realmImport) {
+        stateRepository.loadCustomAttributes(realmImport);
+    }
+
     public void doImport(RealmImport realmImport) {
         if (!importConfigProperties.isState()) {
             return;
diff --git a/src/test/java/de/adorsys/keycloak/config/service/ImportClientsIT.java b/src/test/java/de/adorsys/keycloak/config/service/ImportClientsIT.java
index 2787ce1d..60b0eeaf 100644
--- a/src/test/java/de/adorsys/keycloak/config/service/ImportClientsIT.java
+++ b/src/test/java/de/adorsys/keycloak/config/service/ImportClientsIT.java
@@ -25,6 +25,7 @@ import de.adorsys.keycloak.config.AbstractImportTest;
 import de.adorsys.keycloak.config.exception.ImportProcessingException;
 import de.adorsys.keycloak.config.exception.KeycloakRepositoryException;
 import de.adorsys.keycloak.config.model.RealmImport;
+import de.adorsys.keycloak.config.properties.ImportConfigProperties;
 import de.adorsys.keycloak.config.util.VersionUtil;
 import org.junit.jupiter.api.Order;
 import org.junit.jupiter.api.Test;
@@ -35,7 +36,9 @@ import org.keycloak.representations.idm.authorization.*;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.*;
@@ -77,6 +80,18 @@ class ImportClientsIT extends AbstractImportTest {
         // ... and has to be retrieved separately
         String clientSecret = getClientSecret(REALM_NAME, createdClient.getId());
         assertThat(clientSecret, is("my-special-client-secret"));
+
+        ClientRepresentation clientToDelete = getClientByClientId(realm, "client-to-be-deleted");
+
+        assertThat(clientToDelete, notNullValue());
+        assertThat(clientToDelete.getName(), is("client-to-be-deleted"));
+        assertThat(clientToDelete.getClientId(), is("client-to-be-deleted"));
+        assertThat(clientToDelete.isEnabled(), is(true));
+        assertThat(clientToDelete.getClientAuthenticatorType(), is("client-secret"));
+        assertThat(clientToDelete.getRedirectUris(), is(containsInAnyOrder("*")));
+        assertThat(clientToDelete.getWebOrigins(), is(containsInAnyOrder("*")));
+        assertThat(clientToDelete.getProtocolMappers(), is(nullValue()));
+
     }
 
     @Test
@@ -131,6 +146,12 @@ class ImportClientsIT extends AbstractImportTest {
         // ... and has to be retrieved separately
         clientSecret = getClientSecret(REALM_NAME, client.getId());
         assertThat(clientSecret, is("my-another-other-client-secret-without-client-id"));
+
+        // ... a client which shall be removed
+
+        ClientRepresentation clientToDelete = getClientByClientId(realm, "client-to-be-deleted");
+        assertThat(clientToDelete, nullValue());
+
     }
 
     @Test
@@ -1512,12 +1533,21 @@ class ImportClientsIT extends AbstractImportTest {
 
     @Test
     @Order(90)
-    void shouldNotUpdateRealmCreateClientWithError() throws IOException {
+    void shouldNotUpdateRealmCreateClientWithError_And_ReamStateSurvivesAttributesUpdate() throws IOException {
         RealmImport foundImport = getImport("90_update_realm__try-to-create-client.json");
 
+        // Given the state of the realm already exists
+        assertThat(getRealmState(foundImport.getRealm()), not(anEmptyMap()));
+        // and found import contains custom attributes
+        assertThat(foundImport.getAttributes().get("custom"), notNullValue());
+
         ImportProcessingException thrown = assertThrows(ImportProcessingException.class, () -> realmImportService.doImport(foundImport));
 
         assertThat(thrown.getMessage(), matchesPattern(".*Cannot create client 'new-client' in realm 'realmWithClients': .*"));
+
+        // Expect the experienced fatal exception has not led to the realm state erasure
+        // when the realm configuration contains custom attributes
+        assertThat(getRealmState(foundImport.getRealm()), not(anEmptyMap()));
     }
 
     @Test
@@ -1633,4 +1663,12 @@ class ImportClientsIT extends AbstractImportTest {
                 .findFirst()
                 .orElse(null);
     }
+
+    private Map<String, String> getRealmState(String realmName) {
+        return keycloakRepository.getRealmAttributes(realmName)
+                .entrySet()
+                .stream()
+                .filter(e -> e.getKey().startsWith(ImportConfigProperties.REALM_STATE_ATTRIBUTE_COMMON_PREFIX))
+                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+    }
 }
diff --git a/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java b/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java
index 06be68b0..48d6ab4f 100644
--- a/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java
+++ b/src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java
@@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
@@ -81,6 +82,12 @@ public class KeycloakRepository {
         return foundClients.get(0);
     }
 
+    public Map<String, String> getRealmAttributes(String realmName) {
+        return keycloakProvider.getInstance()
+                .realm(realmName)
+                .toRepresentation().getAttributes();
+    }
+
     public List<String> getUserClientLevelRoles(String realmName, String username, String clientId) {
         UserRepresentation user = getUser(realmName, username);
         ClientRepresentation client = getClient(realmName, clientId);
diff --git a/src/test/resources/import-files/clients/00_create_realm_with_client.json b/src/test/resources/import-files/clients/00_create_realm_with_client.json
index dcc95cb7..8a26e5f9 100644
--- a/src/test/resources/import-files/clients/00_create_realm_with_client.json
+++ b/src/test/resources/import-files/clients/00_create_realm_with_client.json
@@ -15,6 +15,23 @@
       "webOrigins": [
         "*"
       ]
+    },
+    {
+      "clientId": "client-to-be-deleted",
+      "name": "client-to-be-deleted",
+      "description": "Client which has to be removed after first config changes",
+      "enabled": true,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "my-special-client-secret",
+      "redirectUris": [
+        "*"
+      ],
+      "webOrigins": [
+        "*"
+      ]
     }
-  ]
+  ],
+  "attributes": {
+    "custom": "test"
+  }
 }
diff --git a/src/test/resources/import-files/clients/01_update_realm__add_client.json b/src/test/resources/import-files/clients/01_update_realm__add_client.json
index 3ce3094f..677fbfc0 100644
--- a/src/test/resources/import-files/clients/01_update_realm__add_client.json
+++ b/src/test/resources/import-files/clients/01_update_realm__add_client.json
@@ -55,5 +55,8 @@
         "*"
       ]
     }
-  ]
+  ],
+  "attributes": {
+    "custom": "test"
+  }
 }
diff --git a/src/test/resources/import-files/clients/90_update_realm__try-to-create-client.json b/src/test/resources/import-files/clients/90_update_realm__try-to-create-client.json
index 7b4a15ec..6a99d9ed 100644
--- a/src/test/resources/import-files/clients/90_update_realm__try-to-create-client.json
+++ b/src/test/resources/import-files/clients/90_update_realm__try-to-create-client.json
@@ -15,5 +15,8 @@
         "*"
       ]
     }
-  ]
+  ],
+  "attributes": {
+    "custom": "test"
+  }
 }
['src/test/resources/import-files/clients/01_update_realm__add_client.json', 'src/main/java/de/adorsys/keycloak/config/service/state/StateService.java', 'src/main/java/de/adorsys/keycloak/config/repository/StateRepository.java', 'src/main/java/de/adorsys/keycloak/config/properties/ImportConfigProperties.java', 'CHANGELOG.md', 'src/test/java/de/adorsys/keycloak/config/test/util/KeycloakRepository.java', 'src/main/java/de/adorsys/keycloak/config/service/RealmImportService.java', 'src/test/resources/import-files/clients/00_create_realm_with_client.json', 'src/test/java/de/adorsys/keycloak/config/service/ImportClientsIT.java', 'src/test/resources/import-files/clients/90_update_realm__try-to-create-client.json']