12 Replies Latest reply on Aug 17, 2015 4:00 PM by trispad

    persistence.xml in module not read

    trispad Newbie

      Hi All,

       

      I am writing a custom Keycloak user federation module. I have followed the instructions from Keycloak to implement the WildFly module. The module is picked up by Keycloak and executed, but it does not see the persistence.xml in the module/jar.

       

      Here is where my module is placed:

      modules/com/

      `-- cbm

          `-- my

              `-- my-user-federation

                  `-- main

                      |-- module.xml

                      |-- module.xml~

                      `-- my-user-federation-1.0-SNAPSHOT.jar

       

      Here is my jar:

      my-user-federation-1.0-SNAPSHOT/

      |-- com

      |   `-- cbm

      |       `-- my

      |           `-- keycloak

      |               |-- MyKeycloakUser.class

      |               |-- MyUserFederationProvider.class

      |               |-- MyUserFederationProviderFactory$1.class

      |               `-- MyUserFederationProviderFactory.class

      `-- META-INF

          |-- MANIFEST.MF

          |-- maven

          |   `-- com.cbm.my

          |       `-- my-user-federation

          |           |-- pom.properties

          |           `-- pom.xml

          |-- persistence.xml

          `-- services

              `-- org.keycloak.models.UserFederationProviderFactory

       

      This is the exception I am getting:

      Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named my-user-federation

        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)

      when call the following code in 'MyUserFederationProviderFactory':

      Map<String, Object> properties = new HashMap<String, Object>();
      properties.put(AvailableSettings.NON_JTA_DATASOURCE, dataSource);
      properties.put("hibernate.show_sql", config.getBoolean("showSql", false));
      properties.put("hibernate.format_sql", config.getBoolean("formatSql", false));
      logger.info("Creating My-User-Federation EntityManagerFactory");
      entityManagerFactory = Persistence.createEntityManagerFactory("my-user-federation",properties);
      

      ( I followed this as an example to create my EntityManagerFactory keycloak/DefaultJpaConnectionProviderFactory.java at master · keycloak/keycloak · GitHub)


      I am going to be self-managing the transactions as they are read-only and the objects are not instantiated  by the 'container' but by Keycloak.


      I have debugged through, and the Keycloak persistence.xml is being picked up, but the one from my module. I would prefer to not do straight JDBC.

      I am working with WF-9.0.1 and Keycloak 1.4.0

       

      Thanks for any help/ideas,

       

      Tristan

        • 1. Re: persistence.xml in module not read
          Scott Marlow Master
          I have debugged through, and the Keycloak persistence.xml is being picked up, but the one from my module. I would prefer to not do straight JDBC.

          I am working with WF-9.0.1 and Keycloak 1.4.0

           

          Which javax.persistence.spi.PersistenceProviderResolver implementation is being used?  The Hibernate implementation in javax.persistence?  Or perhaps the WildFly JPA subsystem org.jboss.as.jpa.persistenceprovider.PersistenceProviderResolverImpl?

          • 2. Re: persistence.xml in module not read
            Tomaz Cerar Master

            also does your module that contains jpa classes, have jandex index for it?

            • 3. Re: persistence.xml in module not read
              trispad Newbie

              The Hibernate implementation (org.hibernate.jpa.HibernatePersistenceProvider). I believe that this is what Keycloak is also using, but I am not 100% sure of that.

               

              Tristan

              • 4. Re: persistence.xml in module not read
                trispad Newbie

                The module does not contain any JPA classes. I am writing a @NamedNativeQuery and mapping it to an @SqlResultSetMapping. I am being lazy as there is only one table to access but wanted to take advantage of JPA map it to a result set. Would not having any classes associated with the persistence unit cause the xml to not be loaded?

                 

                Tristan

                • 5. Re: persistence.xml in module not read
                  Scott Marlow Master

                  How early during WildFly startup does your Keycloak custom federation module start initializing?  It sounds to me like the WildFly JPA subsystem has not yet started.  Is there a WildFly "custom federation module" service that perhaps could depend on the JPA service? 

                  • 6. Re: persistence.xml in module not read
                    trispad Newbie

                    I am not sure at what point the jar is loaded by the class-loader, but the code to create my entity manager factory is called by clicking a button in the Keycloak admin console. Given that I would assume the JPA subsystem is up and going. As I debug through, I see the persistence.xml for keycloak checked for the persistence unit name, but my persistence.xml is never put in the list of available persistence units.

                    • 7. Re: persistence.xml in module not read
                      Scott Marlow Master

                      Please show us the contents of the your persistence.xml.

                      • 8. Re: persistence.xml in module not read
                        trispad Newbie

                        Here is my persistence.xml

                        <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
                          version="1.0">
                          <persistence-unit name="my-user-federation" transaction-type="RESOURCE_LOCAL">
                            <provider>org.hibernate.jpa.HibernatePersistence</provider>
                            <exclude-unlisted-classes>true</exclude-unlisted-classes>
                            <properties>
                              <property name="jboss.as.jpa.managed" value="false" />
                            </properties>
                          </persistence-unit>
                        </persistence>
                        
                        • 9. Re: persistence.xml in module not read
                          Scott Marlow Master

                          Sounds like Hibernate is not seeing the persistence.xml.  You probably could set a breakpoint in the org.hibernate.jpa.HibernatePersistence (set a breakpoint in createEntityManagerFactory(String persistenceUnitName, Map properties)) to find out why.  Does it make a difference if you set the thread context classloader to your custom module classloader during the call to Persistence.createEntityManagerFactory("my-user-federation",properties)?  You could try that in the debugger as well.

                          • 10. Re: persistence.xml in module not read
                            trispad Newbie

                            Setting the classloader did the trick.

                             

                            ...
                            Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
                            entityManagerFactory = Persistence.createEntityManagerFactory("my-user-federation",properties);
                            ...
                            
                            

                             

                            Classloaders generally being some sort of voodoo to me, will there be adverse effects of this? Should I save the original class loader and re-set it once I have the EntityManagerFactory?

                            • 11. Re: persistence.xml in module not read
                              Scott Marlow Master

                              If you set the context classloader, you should definitely restore the previous classloader once you have the EntityManagerFactory (via a try {} finally {} to ensure it the original classloader is restored even if an exception is thrown.

                               

                              org.wildfly.extension.picketlink.idm.service.JPAIdentityStoreService is one example of similar code.  A better example might be org.jboss.as.weld.services.bootstrap.WeldExecutorServices which checks if a security manager is enabled and uses a PrivilegedAction.

                              • 12. Re: persistence.xml in module not read
                                trispad Newbie

                                Awesome, thanks so much for the help!

                                 

                                Tristan