Welcome Guest  |  Register  |  Login
Login Name Password
  Index  | Recent Threads  | Unanswered Threads  | Who's Online  | User List  | Help
  Search  


Quick Go »

No member browsing this thread
Thread Status: Active
Total posts in this thread: 8
Post new Thread
Author
Previous Thread This topic has been viewed 549 times and has 7 replies
Male airwave209
Newbie




Joined: Jan 19, 2008
Post Count: 8
Status: Offline
Reply to this Post  Reply with Quote 
confused DataNucleus + Spring DM anyone?

Hi,

Anyone tried integrating JPOX/DataNucleus into Spring Dynamic Modules (Spring DM)?

Now that I have jars running as bundles inside the OSGi container, but does the same precautions described in JPOX+Spring+Eclipse RCP applies too for Spring DM + OSGi environments?

TIA
[Aug 9, 2008 5:07:53 AM] Show Printable Version of Post    View Member Profile    Send Private Message [Link] Report threatening or abusive post: please login first  Go to top 
Male airwave209
Newbie




Joined: Jan 19, 2008
Post Count: 8
Status: Offline
Reply to this Post  Reply with Quote 
confused Re: DataNucleus + Spring DM anyone?

Nobody?

I was planning to have an OSGi bundle to provide the PersistenceManagerFactory instance, using the entity object classes it can found on the imports in the manifest.

When setting up JDOPersistenceManagerFactory, I event explicitly set the property datanucleus.classLoaderResolverName in its options attribute, as I got an exception related to this (see below):


<entry key="datanucleus.classLoaderResolverName" value="jdo" />


But I got such an exception when the bundle started.
(Spring-related exception stack traces removed)


...
Caused by: org.datanucleus.exceptions.NucleusUserException: Persistence process has been specified to use a ClassLoaderResolver of name "" yet this has not been found by the DataNucleus plugin mechanism. Please check your CLASSPATH and plugin specification.
at org.datanucleus.OMFContext.getClassLoaderResolver(OMFContext.java:295)
at org.datanucleus.OMFContext.<init>(OMFContext.java:157)
at org.datanucleus.ObjectManagerFactoryImpl.initialiseOMFContext(ObjectManagerFactoryImpl.java:145)
at org.datanucleus.jdo.JDOPersistenceManagerFactory.initialiseProperties(JDOPersistenceManagerFactory.j
ava:281)
at org.datanucleus.jdo.JDOPersistenceManagerFactory.<init>(JDOPersistenceManagerFactory.java:188)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:100)
... 17 more


Anyone can help?

TIA.
[Aug 14, 2008 3:00:17 PM] Show Printable Version of Post    View Member Profile    Send Private Message [Link] Report threatening or abusive post: please login first  Go to top 
Male jfrantzius
Advanced Member
Member's Avatar

Germany
Joined: Jun 18, 2004
Post Count: 405
Status: Offline
Reply to this Post  Reply with Quote 
Re: DataNucleus + Spring DM anyone?

I didn't understand really, what is the exception you get when you do set "datanucleus.classLoaderResolverName=jdo", and which do you get when you don't set that property?

Or do you get that exception you quoted in both cases, i.e. no matter whether you set "datanucleus.classLoaderResolverName" or not?
[Aug 16, 2008 10:19:02 PM] Show Printable Version of Post    View Member Profile    Send Private Message    http://www.artnology.com [Link] Report threatening or abusive post: please login first  Go to top 
Male airwave209
Newbie




Joined: Jan 19, 2008
Post Count: 8
Status: Offline
Reply to this Post  Reply with Quote 
Re: DataNucleus + Spring DM anyone?

I didn't understand really, what is the exception you get when you do set "datanucleus.classLoaderResolverName=jdo", and which do you get when you don't set that property?

Or do you get that exception you quoted in both cases, i.e. no matter whether you set "datanucleus.classLoaderResolverName" or not?


Yes, both cases. Exception was thrown before and after I set this property.

Digging the stack trace a bit deeper revealed that it couldn't even find the plugin.xml on the classpath hierarchy; so I think it is really the classloader's problem.

As a part of the crash course, I also tried using EclipsePluginRegistry too:


<bean id="persistenceManagerFactory" class="org.datanucleus.jdo.JDOPersistenceManagerFactory">
<constructor-arg>
<map>
<entry key="datanucleus.plugin.pluginRegistryClassName" value="org.datanucleus.plugin.EclipsePluginRegistry" />
</map>
</constructor-arg>
<property name="connectionFactory">
<osgi:reference interface="javax.sql.DataSource" />
</property>
</bean>


With the manifest declared as follows:


Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Evos JdoPersistenceManagerFactory module
Bundle-SymbolicName: com.everbrightmfg.evos.JdoPersistenceManagerFactory
Bundle-Version: 1.0.0
Bundle-Vendor: s2.alpha.system
Require-Bundle: com.everbrightmfg.evos.datasource;bundle-version="1.0.0",
com.everbrightmfg.evos.customer;bundle-version="1.0.0",
org.datanucleus;bundle-version="1.0.0",
org.datanucleus.cache;bundle-version="1.0.0",
org.datanucleus.enhancer;bundle-version="1.0.0",
org.datanucleus.java5;bundle-version="1.0.0",
org.datanucleus.store.rdbms;bundle-version="1.0.0",
org.eclipse.osgi;bundle-version="3.4.0",
org.eclipse.equinox.registry;bundle-version="3.4.0"
Eclipse-RegisterBuddy: com.everbrightmfg.evos.customer
Import-Package: org.apache.log4j;version="1.2.15"


The exception thrown changed to


Caused by: java.lang.NoClassDefFoundError: org/osgi/framework/Bundle
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2406)
at java.lang.Class.getConstructor0(Class.java:2716)
at java.lang.Class.getConstructor(Class.java:1674)
at org.datanucleus.plugin.PluginRegistryFactory.newInstance(PluginRegistryFactory.java:98)
at org.datanucleus.plugin.PluginRegistryFactory.newPluginRegistry(PluginRegistryFactory.java:61)
at org.datanucleus.plugin.PluginManager.<init>(PluginManager.java:46)
at org.datanucleus.OMFContext.<init>(OMFContext.java:140)
at org.datanucleus.ObjectManagerFactoryImpl.initialiseOMFContext(ObjectManagerFactoryImpl.java:145)
at org.datanucleus.jdo.JDOPersistenceManagerFactory.initialiseProperties(JDOPersistenceManagerFactory.j
ava:281)
at org.datanucleus.jdo.JDOPersistenceManagerFactory.<init>(JDOPersistenceManagerFactory.java:188)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:100)
... 17 more
Caused by: java.lang.ClassNotFoundException: org.osgi.framework.Bundle
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClassInternal(BundleLoader.java:481)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:397)
at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:385)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:87)
at java.lang.ClassLoader.loadClass(ClassLoader.java:268)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:336)
... 33 more


Which is quite weird, as the Eclipse Equinox jar is imported too. sad
[Aug 18, 2008 3:14:27 AM] Show Printable Version of Post    View Member Profile    Send Private Message [Link] Report threatening or abusive post: please login first  Go to top 
Male airwave209
Newbie




Joined: Jan 19, 2008
Post Count: 8
Status: Offline
Reply to this Post  Reply with Quote 
Re: DataNucleus + Spring DM anyone?

Sorry to dig this back up, but my integration effort is rather hobbyist than required :) that's why it's moving so slowly, though I do hope my effort will eventually make DataNucleus a citizen the same class as Hibernate in the OSGi environment.

Anyway, I think the problems ahead might require people with knowledge in OSGi to answer them.

My strategy turned to using a Spring's FactoryBean to do all the initializations, then expose it to the OSGi environment via Spring DM. As a (desperate) attempt, I wrote this:

package system.alpha.s2.core.dao.jdo;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jdo.PersistenceManagerFactory;

import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.jdo.JDOPersistenceManagerFactory;
import org.datanucleus.plugin.ConfigurationElement;
import org.datanucleus.plugin.ExtensionPoint;
import org.datanucleus.plugin.PluginRegistry;
import org.datanucleus.plugin.Bundle.BundleDescription;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.packageadmin.RequiredBundle;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.osgi.context.BundleContextAware;
import org.springframework.osgi.util.OsgiBundleUtils;

public class CustomJdoPmfFactoryBean implements FactoryBean, InitializingBean, BundleContextAware
{
private BundleContext bundleContext;

private PersistenceManagerFactory persistenceManagerFactory;

private Map<String, Object> options;

private Object connectionFactory;

public void setOptions(Map<String, Object> options)
{
this.options = options;
}

public void setConnectionFactory(Object connectionFactory)
{
this.connectionFactory = connectionFactory;
}

public void setBundleContext(BundleContext ctx)
{
this.bundleContext = ctx;
}

public Object getObject() throws Exception
{
return persistenceManagerFactory;
}

public Class getObjectType()
{
return (persistenceManagerFactory != null) ? persistenceManagerFactory.getClass() : PersistenceManagerFactory.class;
}

public boolean isSingleton()
{
return true;
}

public void afterPropertiesSet() throws Exception
{
if(options == null)
options = new HashMap<String, Object>();

ClassLoader classLoader = bundleContext.getBundle().loadClass(JDOPersistenceManagerFactory.class.getName()).getClassLoader();

options.put("datanucleus.plugin.pluginRegistryClassName", system.alpha.s2.core.dao.jdo.CustomJdoPmfFactoryBean.CustomPluginRegistry.class.getName());
options.put("datanucleus.primaryClassLoader", classLoader);
options.put("datanucleus.ConnectionFactory", connectionFactory);

persistenceManagerFactory = new JDOPersistenceManagerFactory(options);
}

public final class CustomPluginRegistry implements PluginRegistry
{
private boolean registeredExtensions;

private Map<String, ExtensionPoint> extensionPoints;

private ClassLoaderResolver classLoaderResolver;

public CustomPluginRegistry(ClassLoaderResolver classLoaderResolver)
{
this.classLoaderResolver = classLoaderResolver;
}

public Object createExecutableExtension(ConfigurationElement confElm, String name, Class[] argsClass, Object[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
{
Class<?> clazz = OsgiBundleUtils.findBundleBySymbolicName(bundleContext, confElm.getExtension().getPlugin().getSymbolicName()).loadClass(confElm.getAttribute(name));
Constructor<?> constructor = clazz.getConstructor(argsClass);
return constructor.newInstance(args);
}

public org.datanucleus.plugin.Bundle[] getBundles()
{
List<org.datanucleus.plugin.Bundle> bundles = new ArrayList<org.datanucleus.plugin.Bundle>();
for(Bundle bundle : bundleContext.getBundles())
{
org.datanucleus.plugin.Bundle bd = DataNucleusPluginUtils.newDataNucleusBundle(bundle);
List<BundleDescription> descs = new ArrayList<BundleDescription>();
for(RequiredBundle requiredBundle : getPackageAdmin().getRequiredBundles(bundle.getSymbolicName()))
{
descs.add(DataNucleusPluginUtils.getBundleDescription(requiredBundle));
}
bd.setRequireBundle(descs);
bundles.add(bd);
}
return bundles.toArray(new org.datanucleus.plugin.Bundle[bundles.size()]);
}

public ExtensionPoint getExtensionPoint(String id)
{
return extensionPoints.get(id);
}

public ExtensionPoint[] getExtensionPoints()
{
return extensionPoints.values().toArray(new ExtensionPoint[extensionPoints.size()]);
}

public Class loadClass(String id, String clazzName) throws ClassNotFoundException
{
return OsgiBundleUtils.findBundleBySymbolicName(bundleContext, id).loadClass(clazzName);
}

public void registerExtensionPoints()
{
registerExtensions();
}

public void registerExtensions()
{
if(registeredExtensions) return;
else
{
for(Bundle bundle : bundleContext.getBundles())
{
URL url = bundle.getResource("/plugin.xml");
if(url != null)
{

}
}
registeredExtensions = true;
}
}

public void resolveConstraints()
{
//not implemented as it's done by underlying OSGi container
}

public URL resolveURLAsFileURL(URL url) throws IOException
{
return url;
}

private PackageAdmin getPackageAdmin()
{
org.osgi.framework.ServiceReference ref = bundleContext.getServiceReference((org.osgi.service.packageadmin.PackageAdmin.class).getName());
if(ref == null)
throw new IllegalStateException((org.osgi.service.packageadmin.PackageAdmin.class).getName() + " service is required");
else
return (PackageAdmin)bundleContext.getService(ref);
}
}
}


It's using Spring's API directly, but I think it's not difficult to write one with OSGi Activator interface. Also you can see it's not finished yet, as I was still stuck with class loading problems - please read on.

The PluginRegistry is internal to this FactoryBean as it need to access the BundleContext of the OSGi environment.

But when it starts, the PluginRegistryFactory complained (using JDK 1.4 logging here):

04-Sep-2008 11:54:11 org.datanucleus.plugin.PluginRegistryFactory newInstance
FINE: Plugin Registry "system.alpha.s2.core.dao.jdo.CustomJdoPmfFactoryBean$CustomPluginRegistry" not found. Falling back to DataNucleus registry. Reason : system.alpha.s2.core.dao.jdo.CustomJdoPmfFactoryBean$CustomPluginRegistry.<init>(org.datanucleus.ClassLoaderResolver).
04-Sep-2008 11:54:11 org.datanucleus.plugin.PluginRegistryFactory newPluginRegistry
FINE: Using PluginRegistry org.datanucleus.plugin.EclipsePluginRegistry


I think I might gave a wrong ClassLoader to DataNucleus again... sad

To move forward, the question (before thinking if my code was wrong) becomes: which class's ClassLoader should I use?

Or I shouldn't use inner classes at all? If so what should I do?
----------------------------------------
[Edit 1 times, last edit by airwave209 at Sep 4, 2008 5:06:53 AM]
[Sep 4, 2008 5:05:25 AM] Show Printable Version of Post    View Member Profile    Send Private Message [Link] Report threatening or abusive post: please login first  Go to top 
Male andy
Expert
Member's Avatar

UK / EspaƱa
Joined: Mar 13, 2004
Post Count: 4882
Status: Offline
Reply to this Post  Reply with Quote 
Re: DataNucleus + Spring DM anyone?

Why not ask Spring people? They claim to be contributing so much to OSGi, so they must know what is different in their environment to what an OSGi container like Equinox/Felix offer (and enough people have it working in those) - I've not had the time to use either. They should also be looking to get as wide as support as possible for data persistence, hence should know how to handle JDO class loading.
----------------------------------------
-Andy smile

[Sep 5, 2008 10:45:41 AM] Show Printable Version of Post    View Member Profile    Send Private Message    Hidden to Guest [Link] Report threatening or abusive post: please login first  Go to top 
Male airwave209
Newbie




Joined: Jan 19, 2008
Post Count: 8
Status: Offline
Reply to this Post  Reply with Quote 
Re: DataNucleus + Spring DM anyone?

OK, I'll ask them and post the results back. smile
[Sep 5, 2008 2:26:15 PM] Show Printable Version of Post    View Member Profile    Send Private Message [Link] Report threatening or abusive post: please login first  Go to top 
Male KermitTheFragger
Newbie




Joined: Nov 30, 2008
Post Count: 1
Status: Offline
Reply to this Post  Reply with Quote 
Re: DataNucleus + Spring DM anyone?

Coincidently I was experimenting with a similar setup: OSGi (equinox 3.4) and Spring DM and ran into the same issue. I think the issue is not directly related to SpringDM; It also surfaces in a normal 'vanilla' Equinox OSGi environment (without eclipse). So IMHO it looks more like a Datanuclues issue. It's not a bug; It's just something thats not really obvious when you use OSGi and Datanucleus together for the first time.

I created the following class which is a subclass of the LocalPersistenceManagerFactoryBean as a quick test/fix:


public class DatanucleusOSGiLocalPersistenceManagerFactoryBean extends LocalPersistenceManagerFactoryBean implements BundleContextAware {

private BundleContext bundleContext;

@Override
protected PersistenceManagerFactory newPersistenceManagerFactory(String name) {
return JDOHelper.getPersistenceManagerFactory(name, getClassLoader());
}

@Override
protected PersistenceManagerFactory newPersistenceManagerFactory(Map props) {
ClassLoader classLoader = getClassLoader();

props.put("datanucleus.primaryClassLoader", classLoader);

return JDOHelper.getPersistenceManagerFactory(props, classLoader);
}

private ClassLoader getClassLoader() {
ClassLoader classloader = null;
Bundle[] bundles = bundleContext.getBundles();

for (int x=0; x < bundles.length; x++) {

if ("org.datanucleus.store.rdbms".equals(bundles[x].getSymbolicName())) {
try {
classloader = bundles[x].loadClass("org.datanucleus.JDOClassLoaderResolver").getClassLoader();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}

return classloader;
}

@Override
public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;

}
}


With this class you can create a Persistent Bean in Spring DM like you would normally do in standalone spring:


<!-- Persistence Manager Factory Bean -->
<bean id="pmf" class="foo.package.DatanucleusOSGiLocalPersistenceManagerFactoryBean">

<property name="jdoProperties">
<props>
<prop key="javax.jdo.PersistenceManagerFactoryClass">org.datanucleus.jdo.JDOPersistenceManagerFactory</prop>
<prop key="javax.jdo.option.ConnectionURL">jdbc:postgresql://localhost/foo_db</prop>
<prop key="javax.jdo.option.ConnectionUserName">foo</prop>
<prop key="javax.jdo.option.ConnectionPassword">bar</prop>
<prop key="javax.jdo.option.ConnectionDriverName">org.postgresql.Driver</prop>
<prop key="javax.jdo.option.NontransactionalRead">true</prop>
<prop key="datanucleus.classLoaderResolverName">jdo</prop>

<prop key="datanucleus.autoCreateTables">true</prop>
</props>
</property>
</bean>


If you want to use Datanucleus with OSGi WITHOUT Spring DM then you will need something similar; get an instance of the BundleContext (for example in the activator) and from there find the classloader of JDOClassLoaderResolver.

Since I'm relatively new to OSGi, Spring DM and Datanucleus I have no idea if this is the correct way of doing things (Maybe someone can comment on that ?) , I just know it works smile

Something to keep in mind with all this is that a Eclipse Plugin != 100% OSGi Bundle. The MANIFEST.MF defines the OSGi bundle part, however the plugin.xml is part of a special eclipse infrastructure for plugin extensionpoints which is not present in a vanilla OSGi implementation like Eclipse Equinox or Apache Felix. Thats why using "org.datanucleus.plugin.EclipsePluginRegistry" in a plain OSGi environment won't work.
[Dec 1, 2008 6:33:10 PM] Show Printable Version of Post    View Member Profile    Send Private Message [Link] Report threatening or abusive post: please login first  Go to top 
Show Printable Version of Thread  Post new Thread