keycloak-memoizeit

Added ServletContextListener for start of embedded MongoDB

10/10/2013 4:31:16 AM

Details

diff --git a/examples/as7-eap-demo/server/pom.xml b/examples/as7-eap-demo/server/pom.xml
index f7e619e..3282368 100755
--- a/examples/as7-eap-demo/server/pom.xml
+++ b/examples/as7-eap-demo/server/pom.xml
@@ -124,6 +124,10 @@
             <artifactId>mongo-java-driver</artifactId>
         </dependency>
         <dependency>
+            <groupId>de.flapdoodle.embed</groupId>
+            <artifactId>de.flapdoodle.embed.mongo</artifactId>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <version>4.1</version>
diff --git a/examples/as7-eap-demo/server/src/main/webapp/WEB-INF/web.xml b/examples/as7-eap-demo/server/src/main/webapp/WEB-INF/web.xml
index 6829b0e..fafd744 100755
--- a/examples/as7-eap-demo/server/src/main/webapp/WEB-INF/web.xml
+++ b/examples/as7-eap-demo/server/src/main/webapp/WEB-INF/web.xml
@@ -21,6 +21,10 @@
         <async-supported>true</async-supported>
     </servlet>
 
+    <listener>
+        <listener-class>org.keycloak.services.listeners.MongoRunnerListener</listener-class>
+    </listener>
+
     <filter>
         <filter-name>Keycloak Session Management</filter-name>
         <filter-class>org.keycloak.services.filters.KeycloakSessionServletFilter</filter-class>

services/pom.xml 2(+1 -1)

diff --git a/services/pom.xml b/services/pom.xml
index 9cee9f5..6421497 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -163,7 +163,7 @@
         <dependency>
             <groupId>de.flapdoodle.embed</groupId>
             <artifactId>de.flapdoodle.embed.mongo</artifactId>
-            <scope>test</scope>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>junit</groupId>
diff --git a/services/src/main/java/org/keycloak/services/listeners/MongoRunnerListener.java b/services/src/main/java/org/keycloak/services/listeners/MongoRunnerListener.java
new file mode 100644
index 0000000..f0df0a6
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/listeners/MongoRunnerListener.java
@@ -0,0 +1,53 @@
+package org.keycloak.services.listeners;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.config.MongodConfig;
+import de.flapdoodle.embed.mongo.distribution.Version;
+import de.flapdoodle.embed.process.runtime.Network;
+import org.jboss.resteasy.logging.Logger;
+import org.keycloak.services.utils.PropertiesManager;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class MongoRunnerListener implements ServletContextListener {
+
+    protected static final Logger logger = Logger.getLogger(MongoRunnerListener.class);
+
+    private MongodExecutable mongodExe;
+    private MongodProcess mongod;
+
+    @Override
+    public void contextInitialized(ServletContextEvent sce) {
+        if (PropertiesManager.bootstrapEmbeddedMongoAtContextInit()) {
+            int port = PropertiesManager.getMongoPort();
+            logger.info("Going to start embedded MongoDB on port=" + port);
+
+            try {
+                mongodExe = MongodStarter.getDefaultInstance().prepare(new MongodConfig(Version.V2_0_5, port, Network.localhostIsIPv6()));
+                mongod = mongodExe.start();
+            } catch (Exception e) {
+                logger.warn("Couldn't start Embedded Mongo on port " + port + ". Maybe it's already started? Cause: " + e.getClass() + " " + e.getMessage());
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Failed to start MongoDB", e);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void contextDestroyed(ServletContextEvent sce) {
+        if (mongodExe != null) {
+            if (mongod != null) {
+                logger.info("Going to stop embedded MongoDB.");
+                mongod.stop();
+            }
+            mongodExe.stop();
+        }
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index a642bc9..df8eec3 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -8,6 +8,7 @@ import org.keycloak.models.picketlink.PicketlinkKeycloakSession;
 import org.keycloak.models.picketlink.PicketlinkKeycloakSessionFactory;
 import org.keycloak.models.picketlink.mappings.ApplicationEntity;
 import org.keycloak.models.picketlink.mappings.RealmEntity;
+import org.keycloak.services.utils.PropertiesManager;
 import org.keycloak.social.SocialRequestManager;
 import org.picketlink.idm.PartitionManager;
 import org.picketlink.idm.config.IdentityConfigurationBuilder;
@@ -31,15 +32,6 @@ import java.util.Set;
  */
 public class KeycloakApplication extends Application {
 
-    public static final String SESSION_FACTORY = "keycloak.sessionFactory";
-    public static final String SESSION_FACTORY_PICKETLINK = "picketlink";
-    public static final String SESSION_FACTORY_MONGO = "mongo";
-    public static final String MONGO_HOST = "keycloak.mongodb.host";
-    public static final String MONGO_PORT = "keycloak.mongodb.port";
-    public static final String MONGO_DB_NAME = "keycloak.mongodb.databaseName";
-    public static final String MONGO_DROP_DB_ON_STARTUP = "keycloak.mongodb.dropDatabaseOnStartup";
-
-
     protected Set<Object> singletons = new HashSet<Object>();
     protected Set<Class<?>> classes = new HashSet<Class<?>>();
 
@@ -65,11 +57,12 @@ public class KeycloakApplication extends Application {
     }
 
     public static KeycloakSessionFactory buildSessionFactory() {
-        String sessionFactoryType = System.getProperty(SESSION_FACTORY, SESSION_FACTORY_PICKETLINK);
-        if (SESSION_FACTORY_MONGO.equals(sessionFactoryType)) {
+        if (PropertiesManager.isMongoSessionFactory()) {
             return buildMongoDBSessionFactory();
-        } else {
+        } else if (PropertiesManager.isPicketlinkSessionFactory()) {
             return buildPicketlinkSessionFactory();
+        } else {
+            throw new IllegalStateException("Unknown session factory type: " + PropertiesManager.getSessionFactoryType());
         }
     }
 
@@ -79,10 +72,10 @@ public class KeycloakApplication extends Application {
     }
 
     private static KeycloakSessionFactory buildMongoDBSessionFactory() {
-        String host = System.getProperty(MONGO_HOST, "localhost");
-        int port = Integer.parseInt(System.getProperty(MONGO_PORT, "27017"));
-        String dbName = System.getProperty(MONGO_DB_NAME, "keycloak");
-        boolean dropDatabaseOnStartup = Boolean.parseBoolean(System.getProperty(MONGO_DROP_DB_ON_STARTUP, "true"));
+        String host = PropertiesManager.getMongoHost();
+        int port = PropertiesManager.getMongoPort();
+        String dbName = PropertiesManager.getMongoDbName();
+        boolean dropDatabaseOnStartup = PropertiesManager.dropDatabaseOnStartup();
         return new MongoDBSessionFactory(host, port, dbName, dropDatabaseOnStartup);
     }
 
diff --git a/services/src/main/java/org/keycloak/services/utils/PropertiesManager.java b/services/src/main/java/org/keycloak/services/utils/PropertiesManager.java
new file mode 100644
index 0000000..ee16547
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/utils/PropertiesManager.java
@@ -0,0 +1,82 @@
+package org.keycloak.services.utils;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class PropertiesManager {
+
+    private static final String SESSION_FACTORY = "keycloak.sessionFactory";
+    public static final String SESSION_FACTORY_PICKETLINK = "picketlink";
+    public static final String SESSION_FACTORY_MONGO = "mongo";
+
+    private static final String MONGO_HOST = "keycloak.mongodb.host";
+    private static final String MONGO_PORT = "keycloak.mongodb.port";
+    private static final String MONGO_DB_NAME = "keycloak.mongodb.databaseName";
+    private static final String MONGO_DROP_DB_ON_STARTUP = "keycloak.mongodb.dropDatabaseOnStartup";
+    private static final String BOOTSTRAP_EMBEDDED_MONGO_AT_CONTEXT_INIT = "keycloak.mongodb.bootstrapEmbeddedMongoAtContextInit";
+
+    // Port where embedded MongoDB will be started during keycloak bootstrap. Same port will be used by KeycloakApplication then
+    private static final int MONGO_DEFAULT_PORT_KEYCLOAK_WAR_EMBEDDED = 37017;
+
+    // Port where MongoDB instance is normally started on linux. This port should be used if we're not starting embedded instance (keycloak.mongodb.bootstrapEmbeddedMongoAtContextInit is false)
+    private static final int MONGO_DEFAULT_PORT_KEYCLOAK_WAR = 27017;
+
+    // Port where unit tests will start embedded MongoDB instance
+    public static final int MONGO_DEFAULT_PORT_UNIT_TESTS = 27777;
+
+    public static String getSessionFactoryType() {
+        return System.getProperty(SESSION_FACTORY, SESSION_FACTORY_PICKETLINK);
+    }
+
+    public static void setSessionFactoryType(String sessionFactoryType) {
+        System.setProperty(SESSION_FACTORY, sessionFactoryType);
+    }
+
+    public static void setDefaultSessionFactoryType() {
+        System.setProperty(SESSION_FACTORY, SESSION_FACTORY_PICKETLINK);
+    }
+
+    public static boolean isMongoSessionFactory() {
+        return getSessionFactoryType().equals(SESSION_FACTORY_MONGO);
+    }
+
+    public static boolean isPicketlinkSessionFactory() {
+        return getSessionFactoryType().equals(SESSION_FACTORY_PICKETLINK);
+    }
+
+    public static String getMongoHost() {
+        return System.getProperty(MONGO_HOST, "localhost");
+    }
+
+    public static void setMongoHost(String mongoHost) {
+        System.setProperty(MONGO_HOST, mongoHost);
+    }
+
+    public static int getMongoPort() {
+        return Integer.parseInt(System.getProperty(MONGO_PORT, String.valueOf(MONGO_DEFAULT_PORT_KEYCLOAK_WAR_EMBEDDED)));
+    }
+
+    public static void setMongoPort(int mongoPort) {
+        System.setProperty(MONGO_PORT, String.valueOf(mongoPort));
+    }
+
+    public static String getMongoDbName() {
+        return System.getProperty(MONGO_DB_NAME, "keycloak");
+    }
+
+    public static void setMongoDbName(String mongoMongoDbName) {
+        System.setProperty(MONGO_DB_NAME, mongoMongoDbName);
+    }
+
+    public static boolean dropDatabaseOnStartup() {
+        return Boolean.parseBoolean(System.getProperty(MONGO_DROP_DB_ON_STARTUP, "true"));
+    }
+
+    public static void setDropDatabaseOnStartup(boolean dropDatabaseOnStartup) {
+        System.setProperty(MONGO_DROP_DB_ON_STARTUP, String.valueOf(dropDatabaseOnStartup));
+    }
+
+    public static boolean bootstrapEmbeddedMongoAtContextInit() {
+        return isMongoSessionFactory() && Boolean.parseBoolean(System.getProperty(BOOTSTRAP_EMBEDDED_MONGO_AT_CONTEXT_INIT, "true"));
+    }
+}
diff --git a/services/src/test/java/org/keycloak/test/common/MongoDBSessionFactoryTestContext.java b/services/src/test/java/org/keycloak/test/common/MongoDBSessionFactoryTestContext.java
index ece90a1..def3f34 100644
--- a/services/src/test/java/org/keycloak/test/common/MongoDBSessionFactoryTestContext.java
+++ b/services/src/test/java/org/keycloak/test/common/MongoDBSessionFactoryTestContext.java
@@ -8,6 +8,7 @@ import de.flapdoodle.embed.mongo.distribution.Version;
 import de.flapdoodle.embed.process.runtime.Network;
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.utils.PropertiesManager;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -15,7 +16,7 @@ import org.keycloak.services.resources.KeycloakApplication;
 public class MongoDBSessionFactoryTestContext implements SessionFactoryTestContext {
 
     protected static final Logger logger = Logger.getLogger(MongoDBSessionFactoryTestContext.class);
-    private static final int PORT = 27777;
+    private static final int PORT = PropertiesManager.MONGO_DEFAULT_PORT_UNIT_TESTS;
 
     private MongodExecutable mongodExe;
     private MongodProcess mongod;
@@ -42,16 +43,16 @@ public class MongoDBSessionFactoryTestContext implements SessionFactoryTestConte
         }
         logger.info("MongoDB stopped successfully");
 
-        // Null this, so other tests are not affected
-        System.setProperty(KeycloakApplication.SESSION_FACTORY, "");
+        // Reset this, so other tests are not affected
+        PropertiesManager.setDefaultSessionFactoryType();
     }
 
     @Override
     public void initEnvironment() {
-        System.setProperty(KeycloakApplication.SESSION_FACTORY, KeycloakApplication.SESSION_FACTORY_MONGO);
-        System.setProperty(KeycloakApplication.MONGO_HOST, "localhost");
-        System.setProperty(KeycloakApplication.MONGO_PORT, String.valueOf(PORT));
-        System.setProperty(KeycloakApplication.MONGO_DB_NAME, "keycloakTest");
-        System.setProperty(KeycloakApplication.MONGO_DROP_DB_ON_STARTUP, "true");
+        PropertiesManager.setSessionFactoryType(PropertiesManager.SESSION_FACTORY_MONGO);
+        PropertiesManager.setMongoHost("localhost");
+        PropertiesManager.setMongoPort(PORT);
+        PropertiesManager.setMongoDbName("keycloakTest");
+        PropertiesManager.setDropDatabaseOnStartup(true);
     }
 }
diff --git a/services/src/test/java/org/keycloak/test/common/PicketlinkSessionFactoryTestContext.java b/services/src/test/java/org/keycloak/test/common/PicketlinkSessionFactoryTestContext.java
index 1f757bf..80b2cbc 100644
--- a/services/src/test/java/org/keycloak/test/common/PicketlinkSessionFactoryTestContext.java
+++ b/services/src/test/java/org/keycloak/test/common/PicketlinkSessionFactoryTestContext.java
@@ -1,6 +1,7 @@
 package org.keycloak.test.common;
 
 import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.utils.PropertiesManager;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -19,6 +20,6 @@ public class PicketlinkSessionFactoryTestContext implements SessionFactoryTestCo
 
     @Override
     public void initEnvironment() {
-        System.setProperty(KeycloakApplication.SESSION_FACTORY, KeycloakApplication.SESSION_FACTORY_PICKETLINK);
+        PropertiesManager.setSessionFactoryType(PropertiesManager.SESSION_FACTORY_PICKETLINK);
     }
 }
diff --git a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/RemoveUsersWorker.java b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/RemoveUsersWorker.java
index f239772..c5b3633 100644
--- a/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/RemoveUsersWorker.java
+++ b/testsuite/performance/src/test/java/org/keycloak/testsuite/performance/RemoveUsersWorker.java
@@ -9,6 +9,7 @@ import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.mongo.keycloak.adapters.RealmAdapter;
 import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.services.utils.PropertiesManager;
 
 /**
  * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@@ -51,7 +52,7 @@ public class RemoveUsersWorker implements Worker {
 
         // TODO: Not supported in model actually. We support operation just in MongoDB
         // UserModel user = realm.removeUser(username);
-        if (KeycloakApplication.SESSION_FACTORY_MONGO.equals(System.getProperty(KeycloakApplication.SESSION_FACTORY))) {
+        if (PropertiesManager.isMongoSessionFactory()) {
             RealmAdapter mongoRealm = (RealmAdapter)realm;
             mongoRealm.removeUser(username);
         } else {