Skip to content

Commit

Permalink
add scheduled task example
Browse files Browse the repository at this point in the history
  • Loading branch information
dasniko committed Apr 18, 2024
1 parent 9b2245d commit 71d2539
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 0 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<module>initializer</module>
<module>actiontoken</module>
<module>admin-ui</module>
<module>scheduled-task</module>
</modules>

<properties>
Expand Down
62 changes: 62 additions & 0 deletions scheduled-task/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>dasniko.keycloak</groupId>
<artifactId>keycloak-extensions-demo</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>scheduled-task</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi-private</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.cronutils</groupId>
<artifactId>cron-utils</artifactId>
<version>9.2.1</version>
</dependency>
</dependencies>

<build>
<finalName>${project.groupId}-${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dasniko.keycloak.timer;

import lombok.extern.slf4j.Slf4j;
import org.keycloak.cluster.ClusterProvider;
import org.keycloak.timer.ScheduledTask;

@Slf4j
public class ExampleScheduledTaskProvider implements ScheduledTaskProvider {

@Override
public ScheduledTask getScheduledTask() {
return session -> {
//noinspection deprecation
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
cluster.executeIfNotExecuted(ExampleScheduledTaskProviderFactory.PROVIDER_ID + "::scheduled", 10000, () -> {
log.info("I'm being executed... realm: {}", session.getContext().getRealm());
return null;
});
};
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dasniko.keycloak.timer;

import com.google.auto.service.AutoService;
import org.keycloak.models.KeycloakSession;

@AutoService(ScheduledTaskProviderFactory.class)
public class ExampleScheduledTaskProviderFactory extends ScheduledTaskProviderFactory {

public static final String PROVIDER_ID = "example";

@Override
public ScheduledTaskProvider create(KeycloakSession session) {
return new ExampleScheduledTaskProvider();
}

@Override
public String getId() {
return PROVIDER_ID;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dasniko.keycloak.timer;

import org.keycloak.provider.Provider;
import org.keycloak.timer.ScheduledTask;

public interface ScheduledTaskProvider extends Provider {

ScheduledTask getScheduledTask();

@Override
default void close() {
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package dasniko.keycloak.timer;

import lombok.extern.slf4j.Slf4j;
import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.utils.PostMigrationEvent;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.timer.TimerProvider;

@Slf4j
public abstract class ScheduledTaskProviderFactory implements ProviderFactory<ScheduledTaskProvider> {

protected static int intervalSeconds = -1;

protected static final String CONFIG_INTERVAL_SECONDS = "intervalSeconds";
protected static final int CONFIG_INTERVAL_SECONDS_DEFAULT = -1;

private KeycloakSessionFactory keycloakSessionFactory;

@Override
public void init(Config.Scope config) {
intervalSeconds = config.getInt(CONFIG_INTERVAL_SECONDS, CONFIG_INTERVAL_SECONDS_DEFAULT);
}

@Override
public final void postInit(KeycloakSessionFactory keycloakSessionFactory) {
this.keycloakSessionFactory = keycloakSessionFactory;

if (intervalSeconds <= 0) {
log.info("Scheduled task {} provider is disabled.", getId());
return;
};

keycloakSessionFactory.register((event) -> {
if (event instanceof PostMigrationEvent) {
KeycloakSession session = keycloakSessionFactory.create();
TimerProvider provider = session.getProvider(TimerProvider.class);
ScheduledTaskProvider stp = create(session);
provider.scheduleTask(stp.getScheduledTask(), getInterval(), getId());
}
});
}

@Override
public final void close() {
try (KeycloakSession session = keycloakSessionFactory.create()) {
session.getProvider(TimerProvider.class).cancelTask(getId());
}
}

protected int getInterval() {
return intervalSeconds * 1000;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dasniko.keycloak.timer;

import com.google.auto.service.AutoService;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;

@AutoService(Spi.class)
public class ScheduledTaskSpi implements Spi {
@Override
public boolean isInternal() {
return true;
}

@Override
public String getName() {
return "scheduled-task";
}

@Override
public Class<? extends Provider> getProviderClass() {
return ScheduledTaskProvider.class;
}

@Override
public Class<? extends ProviderFactory<ScheduledTaskProvider>> getProviderFactoryClass() {
return ScheduledTaskProviderFactory.class;
}
}

0 comments on commit 71d2539

Please sign in to comment.