Question

I am currently testing out using OSGi. I am running this through Eclipse. I want to have my DAO layer as part of an OSGi solution, but my first stumbling block is this error:

Jun 29, 2009 6:12:37 PM org.hibernate.cfg.annotations.Version <clinit>
INFO: Hibernate Annotations 3.3.0.GA
Jun 29, 2009 6:12:37 PM org.hibernate.ejb.Version <clinit>
INFO: Hibernate EntityManager 3.3.0.GA
Jun 29, 2009 6:12:37 PM org.hibernate.ejb.Ejb3Configuration configure
INFO: Could not find any META-INF/persistence.xml file in the classpath

I have tried putting the persistence.xml file in a lot of different places, to no avail. Any ideas on what I am doing wrong?

Is there a way to manually load the persistence.xml?

The activator looks like this:

package com.activator;


public class PersistenceActivator implements BundleActivator {

    @Override
    public void start(BundleContext arg0) throws Exception {

        EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("postgres");
        EntityManager em = emf.createEntityManager();

        SimpleDaoImpl dao = new SimpleDaoImpl();
        dao.setEntityManager(em);

    }

    @Override
    public void stop(BundleContext arg0) throws Exception {
        // TODO Auto-generated method stub

    }

}

Here is what my directory structure looks like:

alt text http://www.freeimagehosting.net/uploads/7b7b7d2d30.jpg

Here is my Manifest.MF

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Dao Plug-in
Bundle-SymbolicName: Dao
Bundle-Version: 1.0.0
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.osgi.framework;version="1.4.0"
Bundle-Activator: com.activator.PersistenceActivator
Export-Package: com.dao.service
Require-Bundle: HibernateBundle;bundle-version="1.0.0"

HibernateBundle contains all of the Hibernate and Persistence Jars.

Here is my Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>

<persistence>

    <!-- Sample persistence using PostgreSQL. See postgres.txt. -->
    <persistence-unit name="postgres" transaction-type="RESOURCE_LOCAL">

        <properties>


            <property name="hibernate.archive.autodetection" value="class" />

            <!--
                Comment out if schema exists & you don't want the tables dropped.
            -->
            <property name="hibernate.hbm2ddl.auto" value="create-drop" /> <!-- drop/create tables @startup, drop tables @shutdown -->


            <!-- Database Connection Settings -->
            <property name="hibernate.connection.autocommit">true</property>
            <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.connection.username" value="postgres" />
            <property name="hibernate.connection.password" value="postgres" />
            <property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/test" />

            <!-- Not sure about these...  -->
            <property name="hibernate.max_fetch_depth">16</property>
            <property name="hibernate.jdbc.batch_size">1000</property>
            <property name="hibernate.use_outer_join">true</property>
            <property name="hibernate.default_batch_fetch_size">500</property>

            <!-- Hibernate Query Language (HQL) parser. -->
            <property name="hibernate.query.factory_class">
                org.hibernate.hql.ast.ASTQueryTranslatorFactory</property>

            <!-- Echo all executed SQL to stdout -->
            <property name="hibernate.show_sql">true</property>
            <property name="hibernate.format_sql">false</property>

            <!-- Use c3p0 for the JDBC connection pool -->
            <property name="hibernate.c3p0.min_size">3</property>
            <property name="hibernate.c3p0.max_size">100</property>
            <property name="hibernate.c3p0.max_statements">100</property>

            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider" />

        </properties>
    </persistence-unit>



</persistence>

Things I have tried in the Manifest's Classpath with no luck:

Bundle-ClassPath: ., META-INF/persistence.xml

Bundle-ClassPath: ., ../META-INF/persistence.xml

Bundle-ClassPath: ., /META-INF/persistence.xml

Bundle-ClassPath: ., ./META-INF/persistence.xml

Bundle-ClassPath: ., META-INF

Bundle-ClassPath: ., ../META-INF

Bundle-ClassPath: ., /META-INF

Bundle-ClassPath: ., ./META-INF

Bundle-ClassPath: ., C:\Workspaces\OSGiJPA\Dao\META-INF\persistence.xml

Bundle-ClassPath: ., C:\Workspaces\OSGiJPA\Dao\META-INF

Was it helpful?

Solution

I am not using persistence.xml but hibernate.cfg.xml which is similar:

src/main/resource/hibernate/hibernate.cfg.xml

In my Activator I am getting the file via the bundle context: Here is some example code how I do it and also reference that file:>

private void initHibernate(BundleContext context) {
        try {
            final AnnotationConfiguration cfg = new AnnotationConfiguration();
            cfg.configure(context.getBundle().getEntry("/src/main/resource/hibernate/hibernate.cfg.xml"));
            sessionFactory = cfg.buildSessionFactory();

        } catch (Exception e) {
            // TODO Auto-generated catch block
        }
    }

As you can see line which gets the config file is:

context.getBundle().getEntry("/src/main/resource/hibernate/hibernate.cfg.xml")

As you can see my hibernate.cfg.xml is NOT inside the META-INF folder. It is just in the root folder under /src/......

Hope that helps.

Christoph

OTHER TIPS

Use EclipseLink and forget about Hibernate and other implementations, because :

  • You'll have to play with the classloader too much... Thread.currentThread().setContextClassLoader(...)

  • You'll be tempted to set the bundle-classpath attribute and add dependencies manually instead of installing jar bundles.

  • You'll get provider not found errors or you might not be able to find persistence.xml

All the above efforts might not work after many attempts.

However, with EclipseLink it's a no brainer, the implementation was designed to work out of the box in an OSGI environment and there aren't any class loading headaches.

  1. (only a suggestion): Better if you use a lazy loader instead do the job into the activator. For example use a singleton that is invoked into SimpleDaoImpl contructor.
  2. Move META-INF/persistent.xml under src folder (src/META-INF/persistent.xml) because under develop META-INF folder is not in classpath, it works only in runtime mode.
  3. If you are using EclipseLink jpa OSGi, your MANIFEST.MF missing of JPA-PersistenceUnits entry. Add

    JPA-PersistenceUnits: postgres

    into the MANIFEST.MF.

  4. Then in your launch configuration set the start level of org.eclipse.persistence.jpa.osgi (for ecliselink 2.3.x otherwise org.eclipse.persistence.jpa for 2.1.x) to 2 and start level of javax.persistence to 1.

GOOD LUCK, actually 2.3 has a problem in deployment, doesn't handle bundleresource://xxxx URLs :(, 2.1.2 works very well ;)

You need to have the directory that contains META-INF on the classpath. Each directory is searched for META-INF and if found, then persistence.xml is searched for.

If you put "META-INF" on the classpath, then you'd need another META-INF in that directory.

Try using Bundle-ClassPath like this in your manifest

Bundle-ClassPath: ., /location/of/persistence.xml

The Meta-inf directory is not on the classpath. This should work by simply placing it under your src dirctory. If you want it in a separate location, then you will have to specify the Bundle-Classpath to include that directory. By default the classpath is '.'.

I'm getting the same problem.

I think eclipse link is the best option to use in a OSGi Environment. And there are no problem because you will work basically with the JPA implementation. When you need to move to Hibernate, just replace persintece.xml config and some libs.

you need to set property (for hibernate it will be different):

javax.persistence.provider=org.apache.openjpa.persistence.PersistenceProviderImpl

for call:

Persistence.createEntityManagerFactory(entityManagerFactoryName, properties)

to make it work.

And as mentioned before, you need classloader wrapping. You can use ClassloaderEntityManager from https://issues.apache.org/jira/browse/OPENJPA-1783 to do that.

Regards

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top