Not able to register a custom SPI

Update:
I could able to resolve this issue when I place the JAR file into KEYCLOAK_HOME/standalone/deployments/ jar file here
instead of "KEYCLOAK_HOME/providers/
Here is the references,
https://www.keycloak.org/docs/latest/server_development/#using-the-keycloak-deployer

In the older version of Keycloak 3.4.0.FINAL version, the “TokenIntrospectProviderFactory” used to recognize at run time.

after that I also faced one issue that I was seeing " ERROR [org.keycloak.services.error.KeycloakErrorHandler]"

I resolved this issue by adding the below plugin in POM.xml file,
http://docs.wildfly.org/17/Developer_Guide.html#ear-class-loading

	<build>
<plugins>
	<plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-jar-plugin</artifactId>
		<configuration>
			<archive>
				<manifestEntries>
					<Dependencies>org.keycloak.keycloak-services</Dependencies>
				</manifestEntries>
			</archive>
		</configuration>
	</plugin>
</plugins>
	</build>

Hi,

I have the same pb for my custom SPI.

I make in my jboss-deployment-structure.xml 3 modules:

name=“org.keycloak.keycloak-server-spi” export=“true”
name=“org.keycloak.keycloak-server-spi-private” export=“true”
name=“org.keycloak.keycloak-services” export=“true”

Do you think i miss one config ?

Hi everyone,

Answering my own question.

it took some time, but I now I figured out what made Keycloak not load the SPI.

When an SPI is created, a new provider factory interface (that extends Keycloak ProviderFactory class) needs to be created as well. This interface should be returned by the getProviderFactoryClass method. A file for this interface implementation need to be present in the META-INF/services.

I was skipping this step, and instead creating a provider factory class that directly implements the ProviderFactory. This causes Keycloak not to load the SPI, because Keycloak does not load an SPI when it does not find a ProviderFactory implementation that can be loaded using the java ServiceLoader, in other words it should be present in META-INF/services.

Example:

public class DemoSPI implements Spi {
    public boolean isInternal() {
        return false;
    }

    public String getName() {
        return "demoSPI";
    }

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

    public Class<? extends ProviderFactory> getProviderFactoryClass() {
        return DemoProviderFactory.class;
    }
}
public interface DemoProviderFactory extends ProviderFactory<DemoProvider> {
}

public interface DemoProvider extends Provider {

    void sayHi();
}

implementations:

public class SayHiProvider implements DemoProvider {

    public void close() {

    }

    @Override
    public void sayHi() {
        System.out.println("Hi there void provider!");
    }
}
public class SayHiProviderFactory implements DemoProviderFactory {

    public DemoProvider create(KeycloakSession session) {
        return new SayHiProvider();
    }

    public void init(Config.Scope config) {
        System.out.println(" init");
    }

    public void postInit(KeycloakSessionFactory factory) {

    }

    public void close() {

    }

    public String getId() {
        return "say-hi-provider";
    }
}

Now under META-INF services, there should be two files that contains the implementations

  • org.keycloak.provider.Spi
  • com.gwidgets.DemoProviderFactory
1 Like