Equinox (OSGi) and JPA / Hibernate - Search Objects

I am trying to use Hibernate / Spring in OSGi (Equinox) environment. It works fine if I explicitly point it to the Entity classes in Persistence.xml:

<class>com.es.t.eee.domain.StuffSource</class> <class>com.es.t.eee.domain.PostalAddress</class> 

I want Hibernate to “find” all Entity classes in the same way as outside of OSGi.

Hibernate is looking for the right set for @Entities:

 Searching mapped entities in jar/par: bundleresource://34/ WARN 27-07 15:30:24,235 (InputStreamZippedJarVisitor.java:doProcessElements:41): Unable to find file (ignored): bundleresource://34/ 

It seems like it should work, but when it comes to the search point in the Bundle Jar for @Entities, an exception is thrown and I'm not sure why. I have included important parts of the magazine that Hibernate is spitting out.

Does anyone have any ideas what I'm doing wrong or what is the problem here?

I use:

  • Hibernate Core 3.3.0.SP1
  • Hibernate Annotations 3.4.0.GA
  • Hibernate Commons Annotations 3.1.0.GA
  • Hibernate EntityManager 3.4.0.GA
  • Equinox 3.4
  • Spring Dynamic Modules 1.2.0

Here Hibernate parses Persistence.xml

 INFO 27-07 15:30:24,110 (Version.java:<clinit>:15): Hibernate Annotations 3.4.0.GA INFO 27-07 15:30:24,110 (Environment.java:<clinit>:543): Hibernate 3.3.0.SP1 INFO 27-07 15:30:24,110 (Environment.java:<clinit>:576): hibernate.properties not found INFO 27-07 15:30:24,126 (Environment.java:buildBytecodeProvider:709): Bytecode provider name : javassist INFO 27-07 15:30:24,126 (Environment.java:<clinit>:627): using JDK 1.4 java.sql.Timestamp handling INFO 27-07 15:30:24,157 (Version.java:<clinit>:14): Hibernate Commons Annotations 3.1.0.GA INFO 27-07 15:30:24,157 (Version.java:<clinit>:16): Hibernate EntityManager 3.4.0.GA DEBUG 27-07 15:30:24,219 (Ejb3Configuration.java:configure:312): Processing PersistenceUnitInfo [ name: unit.postgresql persistence provider classname: null classloader: BundleDelegatingClassLoader for [DatabaseObjects (DatabaseObjects)] Temporary classloader: org.springframework.instrument.classloading.SimpleThrowawayClassLoader@11b50a1 excludeUnlistedClasses: true JTA datasource: null Non JTA datasource: com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 1000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1012f6d821goxcok12zcw86|174f02c, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.postgresql.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1012f6d821goxcok12zcw86|174f02c, idleConnectionTestPeriod -> 0, initialPoolSize -> 5, jdbcUrl -> jdbc:postgresql://localhost:5432/test2, lastAcquisitionFailureDefaultUser -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 100, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ] Transaction type: RESOURCE_LOCAL PU root URL: bundleresource://34/ Jar files URLs [] Managed classes names [] Mapping files names [] Properties [ hibernate.default_batch_fetch_size: 500 hibernate.cache.provider_class: net.sf.ehcache.hibernate.EhCacheProvider hibernate.dialect: org.hibernate.dialect.PostgreSQLDialect hibernate.max_fetch_depth: 5 hibernate.query.factory_class: org.hibernate.hql.ast.ASTQueryTranslatorFactory hibernate.format_sql: false hibernate.jdbc.batch_size: 1000 hibernate.use_outer_join: true hibernate.archive.autodetection: class hibernate.show_sql: false hibernate.bytecode.provider: cglib] 

This raises an error because it is trying to find objects:

 DEBUG 27-07 15:30:24,235 (Ejb3Configuration.java:getDetectedArtifacts:562): Detect class: true; detect hbm: false DEBUG 27-07 15:30:24,235 (Ejb3Configuration.java:getDetectedArtifacts:562): Detect class: true; detect hbm: false DEBUG 27-07 15:30:24,235 (AbstractJarVisitor.java:unqualify:116): Searching mapped entities in jar/par: bundleresource://34/ WARN 27-07 15:30:24,235 (InputStreamZippedJarVisitor.java:doProcessElements:41): Unable to find file (ignored): bundleresource://34/ java.lang.NullPointerException: in is null at java.util.zip.ZipInputStream.<init>(Unknown Source) at java.util.jar.JarInputStream.<init>(Unknown Source) at java.util.jar.JarInputStream.<init>(Unknown Source) at org.hibernate.ejb.packaging.InputStreamZippedJarVisitor.doProcessElements(InputStreamZippedJarVisitor.java:37) at org.hibernate.ejb.packaging.AbstractJarVisitor.getMatchingEntries(AbstractJarVisitor.java:139) at org.hibernate.ejb.Ejb3Configuration.addScannedEntries(Ejb3Configuration.java:287) at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:614) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:360) at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:131) at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:224) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:291) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409) at java.security.AccessController.doPrivileged(Native Method) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) at org.springframework.beans.factory.support.AbstractBeanFactory.isSingleton(AbstractBeanFactory.java:366) at org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean.afterPropertiesSet(OsgiServiceFactoryBean.java:235) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409) at java.security.AccessController.doPrivileged(Native Method) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:423) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728) at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:288) at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:145) at java.lang.Thread.run(Unknown Source) 
+4
spring hibernate equinox
source share
2 answers

This blog post shows how it can be handled using Spring Dynamic Modules. Based on this blog, you will create bean definitions for DAO and Service beans in the context of your application. The DAO has a link to the hibernate sessionFactory bean:

 <bean id="stuffDao" class="com.es.t.eee.domain.dao.StuffSourceDaoImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="stuffService" class="com.es.t.eee.domain.dao.StuffServiceImpl"> <property name="stuffDao" ref="stuffDao"/> </bean> <bean id="stuffSource" class="com.es.t.eee.domain.StuffSource" scope="prototype"/> 

StuffSourceDaoImpl implements the store () method to store the StuffSource, it passes the StuffSource to the HibernateTemplate to actually do the persistence.

To avoid having to define persistence.xml files or specify each Entity, you can use AnnotationSessionFactoryBean and a wildcard to include all types in the package (s) containing your objects (you can set the packagesToScan property instead, I have not tried this, and it can return you to the original problem):

 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="hibernateProperties"> <props> <!--etc--> </props> </property> <!-- set either one of these properties --> <property name="annotatedClasses"> <list> <value>com.es.t.eee.domain.StuffSource</value> <value>com.es.t.eee.domain.PostalAddress</value> </list> </property> <property name="packagesToScan"> <list> <value>com.es.t.eee.domain</value> </list> </property> </bean> 

To use this, you will get a BundleContext, get the service and bean from the context, and then continue as usual:

 String serviceName = StuffService .class.getName(); StuffService service = (StuffService )context.getService(context.getServiceReference(serviceName)); String stuffName = StuffSource.class.getName(); StuffSource stuffSource = (StuffSource) context.getService(context.getServiceReference(stuffName )); //do whatever with StuffSource ... service.store(stuffSource ); 

You can also watch this OSGi Alliance blog , which discusses some of the issues raised. From the Alliance OSGi Blog:

Hibernate manages the classpath, and such programs usually work poorly with OSGi-based systems. The reason is that in many systems, class visibility between modules is more or less unlimited. Within OSGi, class paths are defined and limited. This gives us a lot of nice features, but it also gives us pain when we want to use a library that has a tendency to become a class loader when it grows ....

To work with Hibernate, you need a Session object. You can get the Session object from SessionFactory. To get a SessionFactory, you need to create it using the Configuration object. The Configuration object is created from the configuration configuration file. By default, Hibernate loads this from the root of your JAR file, however you can add classes manually to the configuration if necessary.

+5
source share

The previous answer, which mentions an OSGi blog post about Hibernate and OSGi issues, is informative.

I suggest stepping back and thinking about the assumptions that are true in a traditional Java application, and how they no longer work inside OSGi:

OSGi is dynamic

How will your application work if the Hibernate package is run before any packages that provide entity classes? Even if scanning for entity classes worked, it would not find.

In traditional Java, all classes are available at startup due to the flat class path, but in OSGi classes are only available if the running package is running and you import packages.

Explicit Dependencies

OSGi requires explicit posting of dependencies; if you do not import the package / package, then you cannot see the classes in these packages / packages.

Since you are saying that explicitly setting up entity classes works, I assume that you are using one of the following to post dependencies:

  • Import package
  • Require bundle
  • Dynamic import
  • The equinox policy.

A seller’s rich offer should work (I haven’t tested it), but you still have to import packages containing entity classes, although I don’t see anything bad in it, and the proposed solution allows you to scan packages, rather than explicitly specifying each entity class.

suggestions

  • Use the Rich Seller solution, but keep in mind that the solution is not dynamic (this may not matter for your application).
  • Implement an extender pattern for entity classes so that you can recreate a Hibernate factory session when the pools and stops that provide entities start and stop.

Now option 1 is simple, and option 2 involves a lot of work. It all depends on your requirement to automatically add / remove entity classes from Hibernate without having to explicitly specify packages / classes.

+1
source share

All Articles