Added ServletContextListener for start of embedded MongoDB at Keycloak deploy. Added PropertiesManager
This commit is contained in:
parent
71cd9cffa4
commit
453e1c5cf7
9 changed files with 166 additions and 27 deletions
|
@ -123,6 +123,10 @@
|
|||
<groupId>org.mongodb</groupId>
|
||||
<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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue