keycloak-aplcache
Changes
connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java 30(+16 -14)
connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java 4(+2 -2)
connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java 28(+15 -13)
connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java 4(+2 -2)
Details
diff --git a/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java b/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
index e011e11..d5bfdcb 100755
--- a/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
+++ b/connections/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
@@ -1,18 +1,5 @@
package org.keycloak.connections.jpa;
-import org.hibernate.ejb.AvailableSettings;
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
-import org.keycloak.connections.jpa.util.JpaUtils;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-
-import javax.naming.InitialContext;
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.Persistence;
-import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
@@ -22,10 +9,25 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
+import javax.naming.InitialContext;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.sql.DataSource;
+
+import org.hibernate.ejb.AvailableSettings;
+import org.jboss.logging.Logger;
+import org.keycloak.Config;
+import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
+import org.keycloak.connections.jpa.util.JpaUtils;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ServerInfoAwareProviderFactory;
+
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory {
+public class DefaultJpaConnectionProviderFactory implements JpaConnectionProviderFactory, ServerInfoAwareProviderFactory {
private static final Logger logger = Logger.getLogger(DefaultJpaConnectionProviderFactory.class);
diff --git a/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java b/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java
index 288e403..2fc645d 100644
--- a/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java
+++ b/connections/jpa/src/main/java/org/keycloak/connections/jpa/JpaConnectionProviderFactory.java
@@ -1,10 +1,10 @@
package org.keycloak.connections.jpa;
-import org.keycloak.provider.ServerInfoAwareProviderFactory;
+import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-public interface JpaConnectionProviderFactory extends ServerInfoAwareProviderFactory<JpaConnectionProvider> {
+public interface JpaConnectionProviderFactory extends ProviderFactory<JpaConnectionProvider> {
}
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
index 00f3386..ae9701b 100755
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
@@ -1,11 +1,12 @@
package org.keycloak.connections.mongo;
-import com.mongodb.DB;
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoClientURI;
-import com.mongodb.MongoCredential;
-import com.mongodb.ServerAddress;
+import java.lang.reflect.Method;
+import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.net.ssl.SSLSocketFactory;
import org.jboss.logging.Logger;
import org.keycloak.Config;
@@ -15,18 +16,19 @@ import org.keycloak.connections.mongo.impl.context.TransactionMongoStoreInvocati
import org.keycloak.connections.mongo.updater.MongoUpdaterProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.provider.ServerInfoAwareProviderFactory;
-import javax.net.ssl.SSLSocketFactory;
-import java.lang.reflect.Method;
-import java.net.UnknownHostException;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoClientURI;
+import com.mongodb.MongoCredential;
+import com.mongodb.ServerAddress;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory {
+public class DefaultMongoConnectionFactoryProvider implements MongoConnectionProviderFactory, ServerInfoAwareProviderFactory {
// TODO Make it dynamic
private String[] entities = new String[]{
diff --git a/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java b/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java
index bce5fe4..e787ce6 100644
--- a/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java
+++ b/connections/mongo/src/main/java/org/keycloak/connections/mongo/MongoConnectionProviderFactory.java
@@ -1,9 +1,9 @@
package org.keycloak.connections.mongo;
-import org.keycloak.provider.ServerInfoAwareProviderFactory;
+import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
-public interface MongoConnectionProviderFactory extends ServerInfoAwareProviderFactory<MongoConnectionProvider> {
+public interface MongoConnectionProviderFactory extends ProviderFactory<MongoConnectionProvider> {
}
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml b/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
index eda5aca..71c2919 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/providers.xml
@@ -16,7 +16,7 @@
</para>
<para>
For example to implement the Event Listener SPI you start by implementing EventListenerProviderFactory:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
package org.acme.provider;
import ...
@@ -43,7 +43,7 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact
}
}
-}]]></programlisting>
+]]></programlisting>
The example uses an imagined MaxList which has a maximum size and is concurrency safe. When the maximum size is reached
and new entries are added the oldest entry is removed. Keycloak creates a single instance of
EventListenerProviderFactory which makes it possible to store state for multiple requests. EventListenerProvider
@@ -51,7 +51,7 @@ public class MyEventListenerProviderFactory implements EventListenerProviderFact
</para>
<para>
Next you would implement EventListenerProvider:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
package org.acme.provider;
import ...
@@ -75,13 +75,61 @@ public class MyEventListenerProvider implements EventListenerProvider {
}
}
-}]]></programlisting>
+]]></programlisting>
</para>
<para>
The file <literal>META-INF/services/org.keycloak.events.EventListenerProviderFactory</literal> should
contain the full name of your ProviderFactory implementation:
<programlisting><![CDATA[org.acme.provider.MyEventListenerProviderFactory]]></programlisting>
</para>
+
+ <section>
+ <title>Show info from you SPI implementation in Keycloak admin console</title>
+ <para>
+ Sometimes it is useful to show additional info about your Provider to a Keycloak administrator.
+ You can show provider build time informations (eg. version of custom provider currently installed),
+ current configuration of the provider (eg. url of remote system your provider talks to) or some operational
+ info (average time of response from remote system your provider talks to).
+ Keycloak admin console provides Server Info page to show this kind of information.
+ </para>
+ <para>
+ To show info from your provider it is enough to implement
+ <literal>org.keycloak.provider.ServerInfoAwareProviderFactory</literal> interface in your ProviderFactory.
+ Example implementation for MyEventListenerProviderFactory from previous example:
+ <programlisting><![CDATA[
+package org.acme.provider;
+
+import ...
+
+public class MyEventListenerProviderFactory implements EventListenerProviderFactory, ServerInfoAwareProviderFactory {
+
+ private List<Event> events;
+ private int max;
+
+...
+
+ @Override
+ public void init(Config.Scope config) {
+ max = config.getInt("max");
+ events = new MaxList(max);
+ }
+
+...
+
+ @Override
+ public Map<String, String> getOperationalInfo() {
+ Map<String, String> ret = new LinkedHashMap<>();
+ ret.put("version", "1.0");
+ ret.put("listSizeMax", max + "");
+ ret.put("listSizeCurrent", events.size() + "");
+ return ret;
+ }
+
+}
+]]></programlisting>
+
+ </para>
+ </section>
</section>
<section>
@@ -98,13 +146,13 @@ public class MyEventListenerProvider implements EventListenerProvider {
To register a provider using Modules first create a module. To do this you can either use the jboss-cli
script or manually create a folder inside KEYCLOAK_HOME/modules and add your jar and a <literal>module.xml</literal>.
For example to add the event listener sysout example provider using the jboss-cli script execute:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.event-sysout --resources=target/event-listener-sysout-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-model-api,org.keycloak.keycloak-events-api"
-}]]></programlisting>
+]]></programlisting>
Or to manually create it start by creating the folder <literal>KEYCLOAK_HOME/modules/org/keycloak/examples/event-sysout/main</literal>.
Then copy <literal>event-listener-sysout-example.jar</literal> to this folder and create <literal>module.xml</literal>
with the following content:
-<programlisting><![CDATA[{
+<programlisting><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.examples.event-sysout">
<resources>
@@ -116,7 +164,7 @@ public class MyEventListenerProvider implements EventListenerProvider {
<module name="org.keycloak.keycloak-events-api"/>
</dependencies>
</module>
-}]]></programlisting>
+]]></programlisting>
</para>
<para>
Once you've created the module you need to register this module with Keycloak. This is done by editing
diff --git a/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java b/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java
index 97d17b1..7674047 100644
--- a/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java
+++ b/model/api/src/main/java/org/keycloak/provider/ServerInfoAwareProviderFactory.java
@@ -3,15 +3,15 @@ package org.keycloak.provider;
import java.util.Map;
/**
- * Marker interface for ProviderFactory of Provider which wants to show some info on "Server Info" page in Admin console.
+ * Marker interface for {@link ProviderFactory} of Provider which wants to show some info on "Server Info" page in Admin console.
*
* @author Vlastimil Elias (velias at redhat dot com)
*/
-public interface ServerInfoAwareProviderFactory<T extends Provider> extends ProviderFactory<T> {
+public interface ServerInfoAwareProviderFactory {
/**
- * Get operational info about given provider. This info contains informations about providers configuration and operational conditions (eg. errors in connection to remote systems etc) which is
- * shown on "Server Info" page.
+ * Return actual info about the provider. This info contains informations about providers configuration and operational conditions (eg. errors in connection to remote systems etc) which is
+ * shown on "Server Info" page then.
*
* @return Map with keys describing value and relevant values itself
*/
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
index 4ef2a63..660b1c4 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
@@ -1,5 +1,17 @@
package org.keycloak.services.resources.admin.info;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.core.Context;
+
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.events.EventType;
@@ -21,10 +33,6 @@ import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
import org.keycloak.social.SocialIdentityProvider;
-import javax.ws.rs.GET;
-import javax.ws.rs.core.Context;
-import java.util.*;
-
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@@ -73,7 +81,6 @@ public class ServerInfoAdminResource {
for (Spi spi : spis) {
SpiInfoRepresentation spiRep = new SpiInfoRepresentation();
spiRep.setInternal(spi.isInternal());
- spiRep.setSystemInfo(ServerInfoAwareProviderFactory.class.isAssignableFrom(spi.getProviderFactoryClass()));
List<String> providerIds = new LinkedList<>(session.listProviderIds(spi.getProviderClass()));
Collections.sort(providerIds);
@@ -83,8 +90,9 @@ public class ServerInfoAdminResource {
if (providerIds != null) {
for (String name : providerIds) {
ProviderRepresentation provider = new ProviderRepresentation();
- if (spiRep.isSystemInfo()) {
- provider.setOperationalInfo(((ServerInfoAwareProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name)).getOperationalInfo());
+ ProviderFactory<?> pi = session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name);
+ if (ServerInfoAwareProviderFactory.class.isAssignableFrom(pi.getClass())) {
+ provider.setOperationalInfo(((ServerInfoAwareProviderFactory) pi).getOperationalInfo());
}
providers.put(name, provider);
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java b/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java
index 3f94a5a..1277f8c 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/SpiInfoRepresentation.java
@@ -8,7 +8,6 @@ import java.util.Map;
public class SpiInfoRepresentation {
private boolean internal;
- private boolean systemInfo;
private Map<String, ProviderRepresentation> providers;
@@ -20,14 +19,6 @@ public class SpiInfoRepresentation {
this.internal = internal;
}
- public boolean isSystemInfo() {
- return systemInfo;
- }
-
- public void setSystemInfo(boolean systemInfo) {
- this.systemInfo = systemInfo;
- }
-
public Map<String, ProviderRepresentation> getProviders() {
return providers;
}