Hi.
My goal is to write a Keycloak user storage SPI to interface with a legacy MySQL database.
I have a small project that can query the database successfully in my test
-module.
My issue is that once I deploy my main
-module to Keycloak/Wildfly, it can’t seem to find my persistent-unit:
17:04:44,398 INFO [org.hibernate.jpa.boot.internal.PersistenceXmlParser] (default task-3) HHH000318: Could not find any META-INF/persistence.xml file in the classpath
17:04:44,399 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-3) Uncaught server error: com.fasterxml.jackson.databind.JsonMappingException: No Persistence provider for EntityManager named CRM
I am not sure which of the following is really relevant to this, but I will describe my setup:
I am using live deployment of the .jar, because that’s what the Keycloak doc recommends
(Server Developer Guide) and so I can use hot/re-deployment.
As far as I know, this means that I can’t use external dependencies other than the modules I manually install in keycloak as well. So I set my dependencies in gradle to compileOnly
:
dependencies {
compileOnly 'org.keycloak:keycloak-server-spi:15.0.2'
compileOnly 'mysql:mysql-connector-java:8.0.27'
compileOnly 'org.hibernate:hibernate-core:5.3.20.Final'
}
I installed the module mysql:mysql-connector-java
manually to Keycloak/Wildfly and it is working (tested using the Wildfly Management Console webinterface) correctly.
So, as I am only using dependencies that are already installed in the Keycloak/Wildfly system, I figured, I would need an additional file to tell Wildfly, what my SPI depends on. So I created src/main/resources/META-INF/jboss-deployment-structure.xml
, although I am not exactly sure if this is doing anything:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.keycloak.keycloak-core" export="true" />
<module name="org.keycloak.keycloak-server-spi" export="true" />
<module name="org.keycloak.keycloak-server-spi-private" export="true" />
<module name="org.keycloak.keycloak-services" export="true" />
<module name="com.mysql" export="true" />
<module name="org.hibernate" export="true" />
</dependencies>
</deployment>
</jboss-deployment-structure>
I’m simply building my SPI with gradlew build
and am deploying it with the following command: $KEYCLOAK_HOME/bin/jboss-cli.sh -c --command="deploy --force keycloak-spi-1.0-SNAPSHOT.jar"
.
The SPI is properly recognised in Keycloak and deployment, as well as activating it in Keycloak, works without error. But once I try to use it (query the database using the Keycloak webinterface), it throws aforementioned error.
Here’s my persistence.xml
, which resides in src/main/resources/META-INF/persistence.xml
.
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="CRM">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<class>de.example.myspi.models.User</class>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/example?useSSL=false&characterEncoding=UTF-8" />
<property name="javax.persistence.jdbc.user" value="keycloak" />
<property name="javax.persistence.jdbc.password" value="keycloak" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
This persistence.xml
works well within my test
-module. If I unpack the .jar
, I can also find it in there in /META-INF/persistence.xml
.
Somehow, Keycloak ist not picking up the file and I have no idea how to solve this.
What’s the classpath
of Keycloak or Wildfly?
How do I make it, so the file can be read by Keycloak?