keycloak-uncached

Details

diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java
index c2b3eb2..eec80ee 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java
@@ -114,6 +114,34 @@ public class LDAPConfig {
         return config.getFirst(LDAPConstants.CONNECTION_POOLING);
     }
 
+    public String getConnectionPoolingAuthentication() {
+        return config.getFirst(LDAPConstants.CONNECTION_POOLING_AUTHENTICATION);
+    }
+
+    public String getConnectionPoolingDebug() {
+        return config.getFirst(LDAPConstants.CONNECTION_POOLING_DEBUG);
+    }
+
+    public String getConnectionPoolingInitSize() {
+        return config.getFirst(LDAPConstants.CONNECTION_POOLING_INITSIZE);
+    }
+
+    public String getConnectionPoolingMaxSize() {
+        return config.getFirst(LDAPConstants.CONNECTION_POOLING_MAXSIZE);
+    }
+
+    public String getConnectionPoolingPrefSize() {
+        return config.getFirst(LDAPConstants.CONNECTION_POOLING_PREFSIZE);
+    }
+
+    public String getConnectionPoolingProtocol() {
+        return config.getFirst(LDAPConstants.CONNECTION_POOLING_PROTOCOL);
+    }
+
+    public String getConnectionPoolingTimeout() {
+        return config.getFirst(LDAPConstants.CONNECTION_POOLING_TIMEOUT);
+    }
+
     public String getConnectionTimeout() {
         return config.getFirst(LDAPConstants.CONNECTION_TIMEOUT);
     }
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPIdentityStoreRegistry.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPIdentityStoreRegistry.java
index f6be118..91077f8 100644
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPIdentityStoreRegistry.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPIdentityStoreRegistry.java
@@ -81,21 +81,26 @@ public class LDAPIdentityStoreRegistry {
      * Create LDAPIdentityStore to be cached in the local registry
      */
     public static LDAPIdentityStore createLdapIdentityStore(LDAPConfig cfg) {
-        checkSystemProperty("com.sun.jndi.ldap.connect.pool.authentication", "none simple");
-        checkSystemProperty("com.sun.jndi.ldap.connect.pool.initsize", "1");
-        checkSystemProperty("com.sun.jndi.ldap.connect.pool.maxsize", "1000");
-        checkSystemProperty("com.sun.jndi.ldap.connect.pool.prefsize", "5");
-        checkSystemProperty("com.sun.jndi.ldap.connect.pool.timeout", "300000");
-        checkSystemProperty("com.sun.jndi.ldap.connect.pool.protocol", "plain");
-        checkSystemProperty("com.sun.jndi.ldap.connect.pool.debug", "off");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.authentication", cfg.getConnectionPoolingAuthentication(), "none simple");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.initsize", cfg.getConnectionPoolingInitSize(), "1");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.maxsize", cfg.getConnectionPoolingMaxSize(), "1000");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.prefsize", cfg.getConnectionPoolingPrefSize(), "5");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.timeout", cfg.getConnectionPoolingTimeout(), "300000");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.protocol", cfg.getConnectionPoolingProtocol(), "plain");
+        checkSystemProperty("com.sun.jndi.ldap.connect.pool.debug", cfg.getConnectionPoolingDebug(), "off");
 
         return new LDAPIdentityStore(cfg);
     }
 
-    private static void checkSystemProperty(String name, String defaultValue) {
-        if (System.getProperty(name) == null) {
-            System.setProperty(name, defaultValue);
+    private static void checkSystemProperty(String name, String cfgValue, String defaultValue) {
+        String value = System.getProperty(name);
+        if(cfgValue != null) {
+            value = cfgValue;
         }
+        if(value == null) {
+            value = defaultValue;
+        }
+        System.setProperty(name, value);
     }
 
 
diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java
index 6c33cac..a401e9c 100755
--- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java
+++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPStorageProviderFactory.java
@@ -154,6 +154,27 @@ public class LDAPStorageProviderFactory implements UserStorageProviderFactory<LD
                 .type(ProviderConfigProperty.BOOLEAN_TYPE)
                 .defaultValue("true")
                 .add()
+                .property().name(LDAPConstants.CONNECTION_POOLING_AUTHENTICATION)
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(LDAPConstants.CONNECTION_POOLING_DEBUG)
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(LDAPConstants.CONNECTION_POOLING_INITSIZE)
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(LDAPConstants.CONNECTION_POOLING_MAXSIZE)
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(LDAPConstants.CONNECTION_POOLING_PREFSIZE)
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(LDAPConstants.CONNECTION_POOLING_PROTOCOL)
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
+                .property().name(LDAPConstants.CONNECTION_POOLING_TIMEOUT)
+                .type(ProviderConfigProperty.STRING_TYPE)
+                .add()
                 .property().name(LDAPConstants.CONNECTION_TIMEOUT)
                 .type(ProviderConfigProperty.STRING_TYPE)
                 .add()
diff --git a/server-spi-private/src/main/java/org/keycloak/models/LDAPConstants.java b/server-spi-private/src/main/java/org/keycloak/models/LDAPConstants.java
index 75bcac7..0396e49 100644
--- a/server-spi-private/src/main/java/org/keycloak/models/LDAPConstants.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/LDAPConstants.java
@@ -57,6 +57,13 @@ public class LDAPConstants {
 
     public static final String SEARCH_SCOPE = "searchScope";
     public static final String CONNECTION_POOLING = "connectionPooling";
+    public static final String CONNECTION_POOLING_AUTHENTICATION = "connectionPoolingAuthentication";
+    public static final String CONNECTION_POOLING_DEBUG = "connectionPoolingDebug";
+    public static final String CONNECTION_POOLING_INITSIZE = "connectionPoolingInitSize";
+    public static final String CONNECTION_POOLING_MAXSIZE = "connectionPoolingMaxSize";
+    public static final String CONNECTION_POOLING_PREFSIZE = "connectionPoolingPrefSize";
+    public static final String CONNECTION_POOLING_PROTOCOL = "connectionPoolingProtocol";
+    public static final String CONNECTION_POOLING_TIMEOUT = "connectionPoolingTimeout";
     public static final String CONNECTION_TIMEOUT = "connectionTimeout";
     public static final String READ_TIMEOUT = "readTimeout";
     public static final String PAGINATION = "pagination";
diff --git a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/LdapUserProviderForm.java b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/LdapUserProviderForm.java
index 65510eb..086de37 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/LdapUserProviderForm.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/main/java/org/keycloak/testsuite/console/page/federation/LdapUserProviderForm.java
@@ -120,6 +120,30 @@ public class LdapUserProviderForm extends Form {
     @FindBy(xpath = ".//div[contains(@class,'onoffswitch') and ./input[@id='changedSyncEnabled']]")
     private OnOffSwitch periodicChangedUsersSync;
 
+    @FindByJQuery("a:contains('Connection Pooling Settings')")
+    private WebElement connectionPoolingSettingsButton;
+
+    @FindBy(id = "connectionPoolingAuthentication")
+    private WebElement connectionPoolingAuthenticationInput;
+
+    @FindBy(id = "connectionPoolingDebug")
+    private WebElement connectionPoolingDebugInput;
+
+    @FindBy(id = "connectionPoolingInitSize")
+    private WebElement connectionPoolingInitSizeInput;
+
+    @FindBy(id = "connectionPoolingMaxSize")
+    private WebElement connectionPoolingMaxSizeInput;
+
+    @FindBy(id = "connectionPoolingPrefSize")
+    private WebElement connectionPoolingPrefSizeInput;
+
+    @FindBy(id = "connectionPoolingProtocol")
+    private WebElement connectionPoolingProtocolInput;
+
+    @FindBy(id = "connectionPoolingTimeout")
+    private WebElement connectionPoolingTimeoutInput;
+
     public void setConsoleDisplayNameInput(String name) {
         setInputValue(consoleDisplayNameInput, name);
     }
@@ -256,6 +280,38 @@ public class LdapUserProviderForm extends Form {
         this.periodicChangedUsersSync.setOn(periodicChangedUsersSyncEnabled);
     }
 
+    public void connectionPoolingSettings() {
+        connectionPoolingSettingsButton.click();
+    }
+
+    public void setConnectionPoolingAuthentication(String connectionPoolingAuthentication) {
+        setInputValue(connectionPoolingAuthenticationInput, connectionPoolingAuthentication);
+    }
+
+    public void setConnectionPoolingDebug(String connectionPoolingDebug) {
+        setInputValue(connectionPoolingDebugInput, connectionPoolingDebug);
+    }
+
+    public void setConnectionPoolingInitSize(String connectionPoolingInitSize) {
+        setInputValue(connectionPoolingInitSizeInput, connectionPoolingInitSize);
+    }
+
+    public void setConnectionPoolingMaxSize(String connectionPoolingMaxSize) {
+        setInputValue(connectionPoolingMaxSizeInput, connectionPoolingMaxSize);
+    }
+
+    public void setConnectionPoolingPrefSize(String connectionPoolingPrefSize) {
+        setInputValue(connectionPoolingPrefSizeInput, connectionPoolingPrefSize);
+    }
+
+    public void setConnectionPoolingProtocol(String connectionPoolingProtocol) {
+        setInputValue(connectionPoolingProtocolInput, connectionPoolingProtocol);
+    }
+
+    public void setConnectionPoolingTimeout(String connectionPoolingTimeout) {
+        setInputValue(connectionPoolingTimeoutInput, connectionPoolingTimeout);
+    }
+
     public void testConnection() {
         testConnectionButton.click();
     }
diff --git a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/federation/LdapUserFederationTest.java b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/federation/LdapUserFederationTest.java
index 2f4fb40..d65829a 100644
--- a/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/federation/LdapUserFederationTest.java
+++ b/testsuite/integration-arquillian/tests/other/console/src/test/java/org/keycloak/testsuite/console/federation/LdapUserFederationTest.java
@@ -3,6 +3,7 @@ package org.keycloak.testsuite.console.federation;
 import org.apache.commons.configuration.ConfigurationException;
 import org.jboss.arquillian.graphene.page.Page;
 import org.junit.Test;
+import org.keycloak.models.LDAPConstants;
 import org.keycloak.representations.idm.ComponentRepresentation;
 import org.keycloak.testsuite.console.AbstractConsoleTest;
 import org.keycloak.testsuite.console.page.federation.CreateLdapUserProvider;
@@ -176,6 +177,35 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
         assertTrue("Vendors list doesn't match", vendorsExpected.containsAll(vendorsActual));
     }
 
+    @Test
+    public void configureConnectionPooling() {
+        createLdapUserProvider.navigateTo();
+        createLdapUserProvider.form().selectVendor(ACTIVE_DIRECTORY);
+        createLdapUserProvider.form().setConsoleDisplayNameInput("ldap");
+        createLdapUserProvider.form().selectEditMode(WRITABLE);
+        createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
+        createLdapUserProvider.form().setLdapBindDnInput("KEYCLOAK/Administrator");
+        createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
+        createLdapUserProvider.form().setLdapBindCredentialInput("secret");
+
+        createLdapUserProvider.form().connectionPoolingSettings();
+        createLdapUserProvider.form().setConnectionPoolingAuthentication("none");
+        createLdapUserProvider.form().setConnectionPoolingDebug("fine");
+        createLdapUserProvider.form().setConnectionPoolingInitSize("10");
+        createLdapUserProvider.form().setConnectionPoolingMaxSize("12");
+        createLdapUserProvider.form().setConnectionPoolingPrefSize("11");
+        createLdapUserProvider.form().setConnectionPoolingProtocol("ssl");
+        createLdapUserProvider.form().setConnectionPoolingTimeout("500");
+
+        createLdapUserProvider.form().save();
+        assertAlertSuccess();
+
+        ComponentRepresentation ufpr = testRealmResource().components()
+                .query(null, "org.keycloak.storage.UserStorageProvider").get(0);
+
+        assertLdapConnectionPoolSettings(ufpr, "none","fine","10","12","11","ssl","500");
+   }
+
     private void assertLdapProviderSetting(ComponentRepresentation ufpr, String name, String priority,
             String editMode, String syncRegistrations, String vendor, String searchScope, String connectionPooling,
             String pagination, String enableAccountAfterPasswordUpdate) {
@@ -216,6 +246,17 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
         assertEquals(periodicChangedUsersSync, ufpr.getConfig().get("changedSyncPeriod").get(0));
     }
 
+    private void assertLdapConnectionPoolSettings(ComponentRepresentation ufpr, String authentication, String debug,
+            String initsize, String maxsize, String prefsize, String protocol, String timeout) {
+        assertEquals(authentication, ufpr.getConfig().get(LDAPConstants.CONNECTION_POOLING_AUTHENTICATION).get(0));
+        assertEquals(debug, ufpr.getConfig().get(LDAPConstants.CONNECTION_POOLING_DEBUG).get(0));
+        assertEquals(initsize, ufpr.getConfig().get(LDAPConstants.CONNECTION_POOLING_INITSIZE).get(0));
+        assertEquals(maxsize, ufpr.getConfig().get(LDAPConstants.CONNECTION_POOLING_MAXSIZE).get(0));
+        assertEquals(prefsize, ufpr.getConfig().get(LDAPConstants.CONNECTION_POOLING_PREFSIZE).get(0));
+        assertEquals(protocol, ufpr.getConfig().get(LDAPConstants.CONNECTION_POOLING_PROTOCOL).get(0));
+        assertEquals(timeout, ufpr.getConfig().get(LDAPConstants.CONNECTION_POOLING_TIMEOUT).get(0));
+    }
+
     private LDAPEmbeddedServer startEmbeddedLdapServer() throws Exception {
         Properties defaultProperties = new Properties();
         defaultProperties.setProperty(LDAPEmbeddedServer.PROPERTY_DSF, LDAPEmbeddedServer.DSF_INMEMORY);
diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 690b88f..239a7ce 100644
--- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -838,12 +838,34 @@ use-truststore-spi=Use Truststore SPI
 ldap.use-truststore-spi.tooltip=Specifies whether LDAP connection will use the truststore SPI with the truststore configured in standalone.xml/domain.xml. 'Always' means that it will always use it. 'Never' means that it won't use it. 'Only for ldaps' means that it will use if your connection URL use ldaps. Note even if standalone.xml/domain.xml is not configured, the default Java cacerts or certificate specified by 'javax.net.ssl.trustStore' property will be used.
 validate-password-policy=Validate Password Policy
 connection-pooling=Connection Pooling
+connection-pooling-settings=Connection Pooling Settings
+connection-pooling-authentication=Connection Pooling Authentication
+connection-pooling-authentication-default=none simple
+connection-pooling-debug=Connection Pool Debug Level
+connection-pooling-debug-default=off
+connection-pooling-initsize=Connection Pool Initial Size
+connection-pooling-initsize-default=1
+connection-pooling-maxsize=Connection Pool Maximum Size
+connection-pooling-maxsize-default=1000
+connection-pooling-prefsize=Connection Pool Preferred Size
+connection-pooling-prefsize-default=5
+connection-pooling-protocol=Connection Pool Protocol
+connection-pooling-protocol-default=plain
+connection-pooling-timeout=Connection Pool Timeout
+connection-pooling-timeout-default=300000
 ldap-connection-timeout=Connection Timeout
 ldap.connection-timeout.tooltip=LDAP Connection Timeout in milliseconds
 ldap-read-timeout=Read Timeout
 ldap.read-timeout.tooltip=LDAP Read Timeout in milliseconds. This timeout applies for LDAP read operations
 ldap.validate-password-policy.tooltip=Does Keycloak should validate the password with the realm password policy before updating it
 ldap.connection-pooling.tooltip=Does Keycloak should use connection pooling for accessing LDAP server
+ldap.connection-pooling.authentication.tooltip=A list of space-separated authentication types of connections that may be pooled. Valid types are "none", "simple", and "DIGEST-MD5".
+ldap.connection-pooling.debug.tooltip=A string that indicates the level of debug output to produce. Valid values are "fine" (trace connection creation and removal) and "all" (all debugging information).
+ldap.connection-pooling.initsize.tooltip=The string representation of an integer that represents the number of connections per connection identity to create when initially creating a connection for the identity.
+ldap.connection-pooling.maxsize.tooltip=The string representation of an integer that represents the maximum number of connections per connection identity that can be maintained concurrently.
+ldap.connection-pooling.prefsize.tooltip=The string representation of an integer that represents the preferred number of connections per connection identity that should be maintained concurrently.
+ldap.connection-pooling.protocol.tooltip=A list of space-separated protocol types of connections that may be pooled. Valid types are "plain" and "ssl".
+ldap.connection-pooling.timeout.tooltip=The string representation of an integer that represents the number of milliseconds that an idle connection may remain in the pool without being closed and removed from the pool.
 ldap.pagination.tooltip=Does the LDAP server support pagination.
 kerberos-integration=Kerberos Integration
 allow-kerberos-authentication=Allow Kerberos authentication
diff --git a/themes/src/main/resources/theme/base/admin/resources/partials/user-storage-ldap.html b/themes/src/main/resources/theme/base/admin/resources/partials/user-storage-ldap.html
index abf9045..eff3eae 100755
--- a/themes/src/main/resources/theme/base/admin/resources/partials/user-storage-ldap.html
+++ b/themes/src/main/resources/theme/base/admin/resources/partials/user-storage-ldap.html
@@ -203,6 +203,58 @@
                     <input ng-model="instance.config['connectionPooling'][0]" name="connectionPooling" id="connectionPooling" onoffswitchvalue on-text="{{:: 'onText' | translate}}" off-text="{{:: 'offText' | translate}}" />
                 </div>
                 <kc-tooltip>{{:: 'ldap.connection-pooling.tooltip' | translate}}</kc-tooltip>
+                <div class="col-sm-4" data-ng-show="instance.config['connectionPooling'][0] == 'true'">
+                    <a class="btn btn-primary" data-ng-init="connectionPoolSettings=false" data-ng-click="connectionPoolSettings=!connectionPoolSettings">{{:: 'connection-pooling-settings' | translate}}</a>
+                </div>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config['connectionPooling'][0] == 'true' && connectionPoolSettings">
+                <label class="col-md-2 control-label" for="connectionPoolingAuthentication">{{:: 'connection-pooling-authentication' | translate}}</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="connectionPoolingAuthentication" type="text" ng-model="instance.config['connectionPoolingAuthentication'][0]" placeholder="{{:: 'connection-pooling-authentication-default' | translate}}"/>
+                </div>
+                <kc-tooltip>{{:: 'ldap.connection-pooling.authentication.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config['connectionPooling'][0] == 'true' && connectionPoolSettings">
+                <label class="col-md-2 control-label" for="connectionPoolingDebug">{{:: 'connection-pooling-debug' | translate}}</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="connectionPoolingDebug" type="text" ng-model="instance.config['connectionPoolingDebug'][0]"  placeholder="{{:: 'connection-pooling-debug-default' | translate}}"/>
+                </div>
+                <kc-tooltip>{{:: 'ldap.connection-pooling.debug.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config['connectionPooling'][0] == 'true' && connectionPoolSettings">
+                <label class="col-md-2 control-label" for="connectionPoolingInitSize">{{:: 'connection-pooling-initsize' | translate}}</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="connectionPoolingInitSize" type="text" ng-model="instance.config['connectionPoolingInitSize'][0]" placeholder="{{:: 'connection-pooling-initsize-default' | translate}}"/>
+                </div>
+                <kc-tooltip>{{:: 'ldap.connection-pooling.initsize.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config['connectionPooling'][0] == 'true' && connectionPoolSettings">
+                <label class="col-md-2 control-label" for="connectionPoolingMaxSize">{{:: 'connection-pooling-maxsize' | translate}}</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="connectionPoolingMaxSize" type="text" ng-model="instance.config['connectionPoolingMaxSize'][0]" placeholder="{{:: 'connection-pooling-maxsize-default' | translate}}"/>
+                </div>
+                <kc-tooltip>{{:: 'ldap.connection-pooling.maxsize.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config['connectionPooling'][0] == 'true' && connectionPoolSettings">
+                <label class="col-md-2 control-label" for="connectionPoolingPrefSize">{{:: 'connection-pooling-prefsize' | translate}}</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="connectionPoolingPrefSize" type="text" ng-model="instance.config['connectionPoolingPrefSize'][0]" placeholder="{{:: 'connection-pooling-prefsize-default' | translate}}"/>
+                </div>
+                <kc-tooltip>{{:: 'ldap.connection-pooling.prefsize.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config['connectionPooling'][0] == 'true' && connectionPoolSettings">
+                <label class="col-md-2 control-label" for="connectionPoolingProtocol">{{:: 'connection-pooling-protocol' | translate}}</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="connectionPoolingProtocol" type="text" ng-model="instance.config['connectionPoolingProtocol'][0]" placeholder="{{:: 'connection-pooling-protocol-default' | translate}}"/>
+                </div>
+                <kc-tooltip>{{:: 'ldap.connection-pooling.protocol.tooltip' | translate}}</kc-tooltip>
+            </div>
+            <div class="form-group clearfix" data-ng-show="instance.config['connectionPooling'][0] == 'true' && connectionPoolSettings">
+                <label class="col-md-2 control-label" for="connectionPoolingTimeout">{{:: 'connection-pooling-timeout' | translate}}</label>
+                <div class="col-md-6">
+                    <input class="form-control" id="connectionPoolingTimeout" type="text" ng-model="instance.config['connectionPoolingTimeout'][0]" placeholder="{{:: 'connection-pooling-timeout-default' | translate}}"/>
+                </div>
+                <kc-tooltip>{{:: 'ldap.connection-pooling.timeout.tooltip' | translate}}</kc-tooltip>
             </div>
             <div class="form-group clearfix">
                 <label class="col-md-2 control-label" for="connectionTimeout">{{:: 'ldap-connection-timeout' | translate}}</label>