keycloak-aplcache

KEYCLOAK-2744 connectionsJpa: the databaseSchema 'validate'

4/4/2016 12:53:58 PM

Details

diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml b/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
index 7f0d631..d247c8d 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/server-installation.xml
@@ -186,7 +186,8 @@ bin/add-user-keycloak.[sh|bat] -r master -u <username> -p <password>
                         <term>databaseSchema</term>
                         <listitem>
                             <para>
-                                Specify if schema should be updated or validated. Valid values are "update" and "validate" ("update is default).
+                                Specify if schema should be updated or validated. Valid values are "update" and "validate". Value "update is default and means that DB schema will be updated to latest version.
+                                Value "validate" won't touch database schema, but it will fail to start if schema is not updated to latest version.
                             </para>
                         </listitem>
                     </varlistentry>
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
index cd7c6e3..11630e7 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
@@ -95,8 +95,6 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
 
                     Connection connection = null;
 
-                    String databaseSchema = config.get("databaseSchema");
-
                     Map<String, Object> properties = new HashMap<String, Object>();
 
                     String unitName = "keycloak-default";
@@ -127,14 +125,18 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
                         properties.put(JpaUtils.HIBERNATE_DEFAULT_SCHEMA, schema);
                     }
 
-                    if (databaseSchema != null) {
-                        if (databaseSchema.equals("development-update")) {
-                            properties.put("hibernate.hbm2ddl.auto", "update");
-                            databaseSchema = null;
-                        } else if (databaseSchema.equals("development-validate")) {
-                            properties.put("hibernate.hbm2ddl.auto", "validate");
-                            databaseSchema = null;
-                        }
+
+                    String databaseSchema = config.get("databaseSchema");
+                    if (databaseSchema == null) {
+                        throw new RuntimeException("Property 'databaseSchema' needs to be specified in the configuration");
+                    }
+                    
+                    if (databaseSchema.equals("development-update")) {
+                        properties.put("hibernate.hbm2ddl.auto", "update");
+                        databaseSchema = null;
+                    } else if (databaseSchema.equals("development-validate")) {
+                        properties.put("hibernate.hbm2ddl.auto", "validate");
+                        databaseSchema = null;
                     }
 
                     properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
index 61075c7..4a505a3 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/updater/liquibase/LiquibaseJpaUpdaterProvider.java
@@ -21,6 +21,7 @@ import liquibase.Contexts;
 import liquibase.Liquibase;
 import liquibase.changelog.ChangeSet;
 import liquibase.changelog.RanChangeSet;
+import liquibase.exception.LiquibaseException;
 import org.jboss.logging.Logger;
 import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
 import org.keycloak.connections.jpa.updater.liquibase.conn.LiquibaseConnectionProvider;
@@ -96,16 +97,27 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
 
     @Override
     public void validate(Connection connection, String defaultSchema) {
+        logger.debug("Validating if database is updated");
+
         try {
             Liquibase liquibase = getLiquibase(connection, defaultSchema);
 
-            liquibase.validate();
-        } catch (Exception e) {
+            List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null);
+            if (!changeSets.isEmpty()) {
+                List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
+                String errorMessage = String.format("Failed to validate database schema. Schema needs updating database from %s to %s. Please change databaseSchema to 'update' or use other database",
+                        ranChangeSets.get(ranChangeSets.size() - 1).getId(), changeSets.get(changeSets.size() - 1).getId());
+                throw new RuntimeException(errorMessage);
+            } else {
+                logger.debug("Validation passed. Database is up-to-date");
+            }
+
+        } catch (LiquibaseException e) {
             throw new RuntimeException("Failed to validate database", e);
         }
     }
 
-    private Liquibase getLiquibase(Connection connection, String defaultSchema) throws Exception {
+    private Liquibase getLiquibase(Connection connection, String defaultSchema) throws LiquibaseException {
         LiquibaseConnectionProvider liquibaseProvider = session.getProvider(LiquibaseConnectionProvider.class);
         return liquibaseProvider.getLiquibase(connection, defaultSchema);
     }