6 Replies Latest reply on Oct 4, 2014 4:57 AM by bender_futur

    Error while creating a Wildfly 8.1.0Final extension that uses Hibernate 4

    bender_futur

      I'm creating an extension for Wildfly 8.1.0 that retrieves some runtime attributes (metrics) from the AS's model and puts them into a database. I'm trying to establish the connection to the wildfly's default datasource and in-memory db, so that I could verify that this approach is possible. For accessing it I use Hibernate 4.3.5 that is part of the AS. I got stuck on injecting EntityManagerFactory as a PersistenceUnit, it won't be injected and my emf is always null.

       

      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_2_0.xsd"
                   version="2.0">
          <persistence-unit name="SelfmonitorPU" transaction-type="JTA">
              <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
              <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
              <class>org.jboss.as.selfmonitor.entity.Metric</class>
              <properties>
                <property name="hibernate.hbm2ddl.auto" value="create"/>
                <property name="hibernate.show_sql" value="false"/>
                <property name="hibernate.format_sql" value="true"/>
                <property name="hibernate.listeners.envers.autoRegister" value="false"/>
                <property name="javax.persistence.validation.mode" value="none"/>
                <property name="hibernate.connection.driver_class" 
                            value="org.h2.jdbcx.JdbcDataSource"/>
                <property name="hibernate.connection.username" value="sa"/>
                <property name="hibernate.connection.password" value="sa"/>
                <property name="hibernate.connection.url" 
                          value="jdbc:h2:mem:test;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1"/>
              </properties>
          </persistence-unit>
      </persistence>
      

       

      Metric.java

       

      @Entity
      @Table(name = "metric")
      public class Metric implements Serializable{
          
          @Id
          @GeneratedValue(strategy = GenerationType.AUTO)
          private Long id;
          @Column(name = "metric_name")
          private String name;
          @Column(name = "metric_path")
          private String path;
      
          public Metric(){
          }
          
          public Metric(String name, String path) {
              this.name = name;
              this.path = path;
          }
          
          public Long getId() {
              return id;
          }
      
          public void setId(Long id) {
              this.id = id;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public String getPath() {
              return path;
          }
      
          public void setPath(String path) {
              this.path = path;
          }
      }
      
      

       

      DatabaseCreator.java

       

      public class DatabaseCreator {
          
          @PersistenceUnit(unitName="SelfmonitorPU")
          private static EntityManagerFactory emf;
          
          public DatabaseCreator(){
          }
      
          public static void initDatabase(){
              if(emf != null){
                  EntityManager em = emf.createEntityManager();
                  Metric m = new Metric("testName", "testPath");
                  em.persist(m);
                  String queryString = "SELECT m FROM metric m";
                  Query q = em.createQuery(queryString);
                  List<Metric> metrics = q.getResultList();
                  Metric foundMetric = (Metric) metrics.get(0);
                  System.out.println("---------------------------------");
                  System.out.println("metric " + foundMetric.getName());
                  System.out.println("---------------------------------");
                  em.close();
              }
              else{
                  System.out.println("---------------------------------");
                  System.out.println("emf is null");
                  System.out.println("---------------------------------");
              }
          }
      }
      

       

      The initDatabase is invoked while constructing my service during AS's startup. Whatever I do, my output from this method is always "emf is null". I've tried to create the EntityManagerFactory with the Persistence.createEntityManagerFactory("SelfmonitorPU") but in this case I keep getting " javax.persistence.PersistenceException: No Persistence provider for EntityManager named SelfmonitorPU" and "HHH000318: Could not find any META-INF/persistence.xml file in the classpath". Seems like in this case hibernate doesn't see my persistence.xml even though it's located in a proper place (src/main/resources/META-INF) and is valid (I've tried to deploy a simple app that used this persistence.xml and it worked fine).

       

      Does this have anything to do with class loading? Or would in-code configuration help? What can I do to make it work with hibernate?

       

      Any help will be higly appreciated.

      Thanks.

        • 1. Re: Error while creating a Wildfly 8.1.0Final extension that uses Hibernate 4
          jaikiran

          1) Injection into random classes isn't supported by the server. The DatabaseCreator appears to be a random (unmanaged) class.

          2) Injection into static fields isn't supported either.

           

          What you could do is, make the DatabaseCreator a managed component (for example, a @Singleton @Startup EJB) and let the initDatabase happen in a @PostConstruct method. Something like:

          @javax.ejb.Singleton
          @javax.ejb.Startup
          public class DatabaseCreator {  
                
              @PersistenceUnit(unitName="SelfmonitorPU")  
              private EntityManagerFactory emf;  
                
              public DatabaseCreator(){  
              }  
            
              @PostConstruct  
              private void initDatabase(){  
                  if(emf != null){  
                      EntityManager em = emf.createEntityManager();  
                      Metric m = new Metric("testName", "testPath");  
                      em.persist(m);  
                      String queryString = "SELECT m FROM metric m";  
                      Query q = em.createQuery(queryString);  
                      List<Metric> metrics = q.getResultList();  
                      Metric foundMetric = (Metric) metrics.get(0);  
                      System.out.println("---------------------------------");  
                      System.out.println("metric " + foundMetric.getName());  
                      System.out.println("---------------------------------");  
                      em.close();  
                  }  
                  else{  
                      System.out.println("---------------------------------");  
                      System.out.println("emf is null");  
                      System.out.println("---------------------------------");  
                  }  
              }  
          }
          
          • 2. Re: Error while creating a Wildfly 8.1.0Final extension that uses Hibernate 4
            ctomc

            What extension are you talking about? A subsystem?

            something along the lines of https://docs.jboss.org/author/display/WFLY8/Extending+WildFly+8

             

            or a user deployment that tries to access this?

            • 3. Re: Error while creating a Wildfly 8.1.0Final extension that uses Hibernate 4
              bender_futur

              I've tried to implement it the way you suggest but the emf is always null. It's a subsystem, thanks Tomaz for the link, I have already gone through this docs and haven't found anything that would help me with communication between a Wildfly module and persistence.

              • 4. Re: Error while creating a Wildfly 8.1.0Final extension that uses Hibernate 4
                ctomc

                EE injections & JNDI don't work when you are inside extension, that are deployment scoped capabilities.

                 

                For your use case, what you will need to do is bit different, create a MSC service that has InjectedValue<PersistenceUnitService>

                 

                and in your add handler configure dependency to your persistence unit.

                All you will need is service name which you can get by JPAServiceNames.getPUServiceName("name-of-your-pu").

                (you get all this in jpa subsystem, so make sure you add maven&module dependency to it)

                 

                when all this is done and wired up your service will get properly initialized and start() method on it called.

                what you want to do from there on it is up to you.

                 

                for more probably smarlow will know.

                • 5. Re: Error while creating a Wildfly 8.1.0Final extension that uses Hibernate 4
                  smarlow

                  Instead of EE container managed, he should use the standalone edition way of bootstrapping Hibernate, almost as if he was developing a standalone Java program.  Something like:

                   

                  EntityManagerFactory entityManagerFactory =  javax.persistence.Persistence.createEntityManagerFactory("CustomPersistenceUnitName");

                   

                  As long as the JPA subsystem as already started, the above code should find the Hibernate persistence provider.  A subsystem service can depend on the JPAServiceNames.getJPAServiceName() service to know that a persistence provider has been registered. 

                   

                  Prior to the JPA subsystem starting, the javax.persistence.Persistence.createEntityManagerFactory() will see zero persistence providers to load the persistence.xml associated with the passed persistence unit name.  So, the call will fail.

                  • 6. Re: Error while creating a Wildfly 8.1.0Final extension that uses Hibernate 4
                    bender_futur

                    After some dubegging I found out that the JPA subsystem's state is "UP" prior to javax.persistence.Persistence.createEntityManagerFactory("CustomPersistenceUnitName") call but I keep getting the following error:

                    18:23:18,313 INFO  [org.hibernate.jpa.boot.internal.PersistenceXmlParser] (Thread-72) HHH000318: Could not find any META-INF/persistence.xml file in the classpath.

                    Do you think that in-code configuration would solve this?