You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cayenne.apache.org by Cristiano Ghersi <cr...@abodata.com> on 2013/01/31 13:42:43 UTC

Cayenne under OSGi

Good morning,

My company (Abodata, www.abodata.com) has ported Cayenne into OSGi
environment, and we would like to contribute to Cayenne project with this
enhancement as I posted under user mailing list on October 2012.

Following your instructions, we have uploaded the full content under the
github repo:
https://github.com/cristianoghersi/CayenneOSGi

Basically, we have packaged the source code of 3.1 version into an OSGi
bundle called cayenne-osgi, adding some stuff to manage the particular
classloading features of OSGi.
Then we added also another bundle, called Cayenne-3.1-Dependencies, that
packages all the required dependencies.

I'm at complete disposal for every clarification you need.

I'll wait for your feedback.

Best
cghersi

Re: Cayenne under OSGi

Posted by Cristiano Ghersi <cr...@gmail.com>.
Hi Andrus
We need to be very careful in osgi environment in class loading issues.
Every bundle has its own classloader and this is why we need to register
the class loader explicitly from the bundle that effectively uses Cayenne.
Regarding the dependencies, it is far more manageable to use a separate
bundle for them, to collect the osgi-friendly version of them...
Let me know if you need further clarification
Thanks
Cghersi
Il giorno 03/mar/2013 10:23, "Andrus Adamchik" <an...@objectstyle.org> ha
scritto:

> Ok, I think understand the task in general, but some details still do not
> fully connect in my head. I guess I need to dive into OSGi and to tie all
> the loose ends in Cayenne class loading. E.g. it would be nice to avoid
> registering each class manually, and just pass the right ClassLoader
> somehow, preferably via DI instead of a static method. Your code and this
> discussion certainly make it much easier.
>
> Also something I haven't explored yet is this separate dependencies bundle.
>
> As usual, the toughest part is finding time to do this work. And I'll be
> certainly happy if someone with OSGi experience takes it over. Will be
> happy to apply the patches :) But otherwise, I'll put it in my Cayenne
> queue.
>
> Thanks,
> Andrus
>
> On Mar 1, 2013, at 11:53 AM, Cristiano Ghersi <
> cristiano.ghersi@abodata.com> wrote:
>
> > Hi Andrus,
> >
> > you perfectly caught the point: the difference is in the class loading.
> > The class loaders are populated from the application that uses Cayenne,
> > with the following example snippet:
> >
> > ServerRuntime myRuntime = new ServerRuntime("myDomain.xml");
> > ...
> > ClassRegistry.registerClass(MyPersistentClass1.class);
> > ClassRegistry.registerClass(MyPersistentClass2.class);
> > //call ClassRegistry.registerClass(Class) for each class created by
> > CayenneModeler
> >
> > you can find ClassRegistry class in org.apache.cayenne.di.spi package; it
> > is the other brick added by ourselves in order to correctly run under
> OSGi
> >
> > Let me know if you need any further information!
> >
> > Thanks
> > Cristiano
> >
> > 2013/2/28 Andrus Adamchik <an...@objectstyle.org>
> >
> >> Hi Cristiano,
> >>
> >> So I guess our goal is to tweak the Cayenne build process (and code if
> >> needed) so that it builds OSGI-compatible jars.
> >>
> >> Let's start with the code… I created a diff to better demonstrate the
> >> change in DefaultAdhocObjectFactory between Cayenne and your code:
> >>
> >> +import java.util.List;
> >> +
> >> import org.apache.cayenne.CayenneRuntimeException;
> >> import org.apache.cayenne.di.AdhocObjectFactory;
> >> import org.apache.cayenne.di.Inject;
> >> @@ -102,6 +104,16 @@
> >>             return Class.forName(className, true, classLoader);
> >>         }
> >>         catch (ClassNotFoundException e) {
> >> +                       //try with the class loader registry
> >> +                       List<ClassLoader> registeredClassLoaders =
> >> ClassLoaderRegistry.registeredClassLoaders();
> >> +                       for (ClassLoader loader :
> registeredClassLoaders) {
> >> +                               try {
> >> +                                       return
> loader.loadClass(className);
> >> +                               }
> >> +                               catch (ClassNotFoundException cnfe) {
> >> +                               }
> >> +                       }
> >> +
> >>             if (!className.endsWith("[]")) {
> >>                 if ("byte".equals(className)) {
> >>                     return Byte.TYPE;
> >>
> >>
> >> I guess this is what you described in the previous message (only
> slightly
> >> different naming - ClassLoaderRegistry). I couldn't find who actually
> >> populates those extra class loaders inside ClassLoaderRegistry? Could
> you
> >> comment on this please?
> >>
> >> So other than that, I guess all we need is changing cayenne-server
> >> packaging from "jar" to "bundle" (and configuring the bundle plugin in
> the
> >> pom).
> >>
> >> Andrus
> >>
> >>
> >>
> >> On Feb 28, 2013, at 12:19 PM, Cristiano Ghersi <
> >> cristiano.ghersi@abodata.com> wrote:
> >>> Hi Andrus,
> >>>
> >>> I know you have been very busy with the new upcoming release of
> Cayenne.
> >>>
> >>> I'd like to know if and when we can resume the task of Cayenne
> >>> OSGi-fication.
> >>>
> >>> I'm at your disposal for every clarification.
> >>>
> >>> Thank you very much
> >>> Best
> >>> Cristiano
> >>
> >>
> >>
>
>
>

Re: Cayenne under OSGi

Posted by Andrus Adamchik <an...@objectstyle.org>.
Ok, I think understand the task in general, but some details still do not fully connect in my head. I guess I need to dive into OSGi and to tie all the loose ends in Cayenne class loading. E.g. it would be nice to avoid registering each class manually, and just pass the right ClassLoader somehow, preferably via DI instead of a static method. Your code and this discussion certainly make it much easier. 

Also something I haven't explored yet is this separate dependencies bundle. 

As usual, the toughest part is finding time to do this work. And I'll be certainly happy if someone with OSGi experience takes it over. Will be happy to apply the patches :) But otherwise, I'll put it in my Cayenne queue.

Thanks,
Andrus

On Mar 1, 2013, at 11:53 AM, Cristiano Ghersi <cr...@abodata.com> wrote:

> Hi Andrus,
> 
> you perfectly caught the point: the difference is in the class loading.
> The class loaders are populated from the application that uses Cayenne,
> with the following example snippet:
> 
> ServerRuntime myRuntime = new ServerRuntime("myDomain.xml");
> ...
> ClassRegistry.registerClass(MyPersistentClass1.class);
> ClassRegistry.registerClass(MyPersistentClass2.class);
> //call ClassRegistry.registerClass(Class) for each class created by
> CayenneModeler
> 
> you can find ClassRegistry class in org.apache.cayenne.di.spi package; it
> is the other brick added by ourselves in order to correctly run under OSGi
> 
> Let me know if you need any further information!
> 
> Thanks
> Cristiano
> 
> 2013/2/28 Andrus Adamchik <an...@objectstyle.org>
> 
>> Hi Cristiano,
>> 
>> So I guess our goal is to tweak the Cayenne build process (and code if
>> needed) so that it builds OSGI-compatible jars.
>> 
>> Let's start with the code… I created a diff to better demonstrate the
>> change in DefaultAdhocObjectFactory between Cayenne and your code:
>> 
>> +import java.util.List;
>> +
>> import org.apache.cayenne.CayenneRuntimeException;
>> import org.apache.cayenne.di.AdhocObjectFactory;
>> import org.apache.cayenne.di.Inject;
>> @@ -102,6 +104,16 @@
>>             return Class.forName(className, true, classLoader);
>>         }
>>         catch (ClassNotFoundException e) {
>> +                       //try with the class loader registry
>> +                       List<ClassLoader> registeredClassLoaders =
>> ClassLoaderRegistry.registeredClassLoaders();
>> +                       for (ClassLoader loader : registeredClassLoaders) {
>> +                               try {
>> +                                       return loader.loadClass(className);
>> +                               }
>> +                               catch (ClassNotFoundException cnfe) {
>> +                               }
>> +                       }
>> +
>>             if (!className.endsWith("[]")) {
>>                 if ("byte".equals(className)) {
>>                     return Byte.TYPE;
>> 
>> 
>> I guess this is what you described in the previous message (only slightly
>> different naming - ClassLoaderRegistry). I couldn't find who actually
>> populates those extra class loaders inside ClassLoaderRegistry? Could you
>> comment on this please?
>> 
>> So other than that, I guess all we need is changing cayenne-server
>> packaging from "jar" to "bundle" (and configuring the bundle plugin in the
>> pom).
>> 
>> Andrus
>> 
>> 
>> 
>> On Feb 28, 2013, at 12:19 PM, Cristiano Ghersi <
>> cristiano.ghersi@abodata.com> wrote:
>>> Hi Andrus,
>>> 
>>> I know you have been very busy with the new upcoming release of Cayenne.
>>> 
>>> I'd like to know if and when we can resume the task of Cayenne
>>> OSGi-fication.
>>> 
>>> I'm at your disposal for every clarification.
>>> 
>>> Thank you very much
>>> Best
>>> Cristiano
>> 
>> 
>> 


Re: Cayenne under OSGi

Posted by Cristiano Ghersi <cr...@abodata.com>.
Hi Michael,

Yes, with a bit of reflection surely can be done, in that snippet I would
focus on the simple behavior :)
Just make sure you are using the class loader of the bundle that uses
Cayenne

2013/3/4 Michael Gentry <mg...@masslight.net>

> Hi Cristiano,
>
> ClassRegistry.registerClass(MyPersistentClass1.class);
> > ClassRegistry.registerClass(MyPersistentClass2.class);
> >
>
> Wouldn't it be better to iterate over all of the classes in the DataMap to
> register them instead of manually registering them?
>
> mrg
>

Re: Cayenne under OSGi

Posted by Michael Gentry <mg...@masslight.net>.
Hi Cristiano,

ClassRegistry.registerClass(MyPersistentClass1.class);
> ClassRegistry.registerClass(MyPersistentClass2.class);
>

Wouldn't it be better to iterate over all of the classes in the DataMap to
register them instead of manually registering them?

mrg

Re: Cayenne under OSGi

Posted by Cristiano Ghersi <cr...@abodata.com>.
Hi Andrus,

you perfectly caught the point: the difference is in the class loading.
The class loaders are populated from the application that uses Cayenne,
with the following example snippet:

ServerRuntime myRuntime = new ServerRuntime("myDomain.xml");
...
ClassRegistry.registerClass(MyPersistentClass1.class);
ClassRegistry.registerClass(MyPersistentClass2.class);
//call ClassRegistry.registerClass(Class) for each class created by
CayenneModeler

you can find ClassRegistry class in org.apache.cayenne.di.spi package; it
is the other brick added by ourselves in order to correctly run under OSGi

Let me know if you need any further information!

Thanks
Cristiano

2013/2/28 Andrus Adamchik <an...@objectstyle.org>

> Hi Cristiano,
>
> So I guess our goal is to tweak the Cayenne build process (and code if
> needed) so that it builds OSGI-compatible jars.
>
> Let's start with the code… I created a diff to better demonstrate the
> change in DefaultAdhocObjectFactory between Cayenne and your code:
>
> +import java.util.List;
> +
>  import org.apache.cayenne.CayenneRuntimeException;
>  import org.apache.cayenne.di.AdhocObjectFactory;
>  import org.apache.cayenne.di.Inject;
> @@ -102,6 +104,16 @@
>              return Class.forName(className, true, classLoader);
>          }
>          catch (ClassNotFoundException e) {
> +                       //try with the class loader registry
> +                       List<ClassLoader> registeredClassLoaders =
> ClassLoaderRegistry.registeredClassLoaders();
> +                       for (ClassLoader loader : registeredClassLoaders) {
> +                               try {
> +                                       return loader.loadClass(className);
> +                               }
> +                               catch (ClassNotFoundException cnfe) {
> +                               }
> +                       }
> +
>              if (!className.endsWith("[]")) {
>                  if ("byte".equals(className)) {
>                      return Byte.TYPE;
>
>
> I guess this is what you described in the previous message (only slightly
> different naming - ClassLoaderRegistry). I couldn't find who actually
> populates those extra class loaders inside ClassLoaderRegistry? Could you
> comment on this please?
>
> So other than that, I guess all we need is changing cayenne-server
> packaging from "jar" to "bundle" (and configuring the bundle plugin in the
> pom).
>
> Andrus
>
>
>
> On Feb 28, 2013, at 12:19 PM, Cristiano Ghersi <
> cristiano.ghersi@abodata.com> wrote:
> > Hi Andrus,
> >
> > I know you have been very busy with the new upcoming release of Cayenne.
> >
> > I'd like to know if and when we can resume the task of Cayenne
> > OSGi-fication.
> >
> > I'm at your disposal for every clarification.
> >
> > Thank you very much
> > Best
> > Cristiano
>
>
>

Re: Cayenne under OSGi

Posted by Andrus Adamchik <an...@objectstyle.org>.
Hi Cristiano,

So I guess our goal is to tweak the Cayenne build process (and code if needed) so that it builds OSGI-compatible jars.

Let's start with the code… I created a diff to better demonstrate the change in DefaultAdhocObjectFactory between Cayenne and your code:

+import java.util.List;
+
 import org.apache.cayenne.CayenneRuntimeException;
 import org.apache.cayenne.di.AdhocObjectFactory;
 import org.apache.cayenne.di.Inject;
@@ -102,6 +104,16 @@
             return Class.forName(className, true, classLoader);
         }
         catch (ClassNotFoundException e) {
+			//try with the class loader registry
+			List<ClassLoader> registeredClassLoaders = ClassLoaderRegistry.registeredClassLoaders();
+			for (ClassLoader loader : registeredClassLoaders) {
+				try {
+					return loader.loadClass(className);
+				}
+				catch (ClassNotFoundException cnfe) {
+				}
+			}
+
             if (!className.endsWith("[]")) {
                 if ("byte".equals(className)) {
                     return Byte.TYPE;


I guess this is what you described in the previous message (only slightly different naming - ClassLoaderRegistry). I couldn't find who actually populates those extra class loaders inside ClassLoaderRegistry? Could you comment on this please?

So other than that, I guess all we need is changing cayenne-server packaging from "jar" to "bundle" (and configuring the bundle plugin in the pom). 

Andrus



On Feb 28, 2013, at 12:19 PM, Cristiano Ghersi <cr...@abodata.com> wrote:
> Hi Andrus,
> 
> I know you have been very busy with the new upcoming release of Cayenne.
> 
> I'd like to know if and when we can resume the task of Cayenne
> OSGi-fication.
> 
> I'm at your disposal for every clarification.
> 
> Thank you very much
> Best
> Cristiano


Re: Cayenne under OSGi

Posted by Cristiano Ghersi <cr...@abodata.com>.
Hi Andrus,

I know you have been very busy with the new upcoming release of Cayenne.

I'd like to know if and when we can resume the task of Cayenne
OSGi-fication.

I'm at your disposal for every clarification.

Thank you very much
Best
Cristiano

2013/2/1 Cristiano Ghersi <cr...@abodata.com>

> Hi Andrus,
>
> given your re-engineering of the structure, perhaps I can tell you the
> changes we have plugged in in order to make the stuff work. They are quite
> simple changes to the code, so perhaps is simpler for you to add these
> pieces of code than trying to cope with the complete structure.
>
> We just added ClassRegistry class in the *org.apache.cayenne.di.spi*
>  package.
> Moreover, the class *org.apache.cayenne.di.spi.DefaultAdhocObjectFactory* has
> also been modified to be able to search in the ClassRegistry for classes:
>
> public Class<?> getJavaClass(String className) throws ClassNotFoundException {
>
>                 // is there a better way to get array class from string name?
>
>                 if (className == null) {
>                         throw new ClassNotFoundException("Null class name");
>                 }
>
>                 ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
>
>                 if (classLoader == null) {
>                         classLoader = DefaultAdhocObjectFactory.class.getClassLoader();
>                 }
>
>                 //first for OSGi Environment: look for class in registry.
>                 //try with the class loader registry
>                 Class<?> registryClass = ClassRegistry.getClassByName(className);
>                 if (registryClass != null) {
>                         try {
>                                 return registryClass.getClassLoader().loadClass(className);
>                         }
>                         catch (ClassNotFoundException cnfe) {
>                         }
>                 }
>
>                 // use custom logic on failure only, assuming primitives and arrays are not that
>                 // common
>                 try {
>                         return Class.forName(className, true, classLoader);
>                 }
>
>                 if (!className.endsWith("[]")) {
>                         if ("byte".equals(className)) {
>                                 return Byte.TYPE;
>                         }
>                         ...}
>
>
>
>
> Generate an OSGi Bundle
>
>
> To generate an OSGi bundle some changes are needed in the *pom.xml*. First of all it is necessary to change the *packaging* type of the project from *jar* to *bundle* as it is show in this snippet:
>
> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
>         <modelVersion>4.0.0</modelVersion>
>         <parent>
>                 <groupId>org.apache.cayenne</groupId>
>                 <artifactId>cayenne-parent</artifactId>
>                 <version>3.1B2-SNAPSHOT</version>
>                 <relativePath>../../pom.xml</relativePath>
>         </parent>
>         <groupId>org.apache.cayenne.osgi</groupId>
>         <artifactId>cayenne-osgi</artifactId>
>         <name>Cayenne OSGified</name>     <packaging>bundle</packaging>  <url>http://maven.apache.org</url>
>
> Then it is necessary to add a *plugin* to the *build* section:
>
> <plugins>
>         ...
>
> <plugin>
>                 <groupId>org.apache.felix</groupId>
>                 <artifactId>maven-bundle-plugin</artifactId>
>                 <version>2.3.7</version>
>                 <extensions>true</extensions>
>                 <configuration>
>                         <instructions>
>                                 <Export-Package>org.apache.cayenne, org.apache.cayenne.*</Export-Package>
>                                 <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
>                         </instructions>
>                 </configuration>
>         </plugin>
>
>         ...</plugins>
>
> Finally you can generate the bundle jar
>
> $ cd cayenne-osgi # or navigate to the root directory of the cayenne osgi project
> $ mvn org.apache.felix:maven-bundle-plugin:bundle
>
> The bundle jar can be found in *cayenne-osgi/target/cayenne-osgi.jar.*
>
> *
> *
>
> *
> *
>
> To use the Cayenne OSGi bundle the following steps must be performed:
>
>    1. Import the .jar bundle generated with the above procedure
>    2. Create and import a Cayenne *dependencies* bundle containing all
>    the .jar files needed to satisfy the import packages of Cayenne bundle (the
>    ones added to folder Cayenne-Dependencies folder in the github repo)
>    3. Create a Fragment bundle (setting as the host Cayenne bundle) for
>    each cayenne project. In the *src* folder of the fragment add the two
>    cayenne xml files.
>
>
> Hope this can help the integration.
>
> Let me know if you need further clarification, I'm at complete disposal.
>
> Best
> cghersi
>
>
>
> 2013/2/1 Andrus Adamchik <an...@objectstyle.org>
>
>> Hi cghersi,
>>
>> Thanks!
>>
>> Trying to make sense of the GitHub project structure and what is
>> different from Cayenne. From what I can tell we need this piece in the pom:
>>
>>         <plugin>
>>                 <groupId>org.apache.felix</groupId>
>>                 <artifactId>maven-bundle-plugin</artifactId>
>>                 <version>2.3.7</version>
>>                 <extensions>true</extensions>
>>                 <configuration>
>>                         <instructions>
>>                                 <Export-Package>org.apache.cayenne,
>> org.apache.cayenne.*</Export-Package>
>>
>> <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
>>                         </instructions>
>>                 </configuration>
>>         </plugin>
>>
>> and also the META-INF dir (
>> https://github.com/cristianoghersi/CayenneOSGi/tree/master/cayenne-osgi/META-INF) ?
>>
>> Or is META-INF generated?
>>
>> Also integrating this into our convoluted build structure will be a
>> challenge. One of the 3.2 undeclared goals is simplifying the build
>> structure, so maybe once we start looking into it, we might consider the
>> OSGi aspect. And in any event it is very helpful for us, even we can't
>> simply patch Cayenne from what's on the GitHub. It gives a clear idea of
>> what we need to do to make ours jars OSGi-friendly.
>>
>> Cheers,
>> Andrus
>>
>> On Jan 31, 2013, at 3:42 PM, Cristiano Ghersi <
>> cristiano.ghersi@abodata.com> wrote:
>> > Good morning,
>> >
>> > My company (Abodata, www.abodata.com) has ported Cayenne into OSGi
>> > environment, and we would like to contribute to Cayenne project with
>> this
>> > enhancement as I posted under user mailing list on October 2012.
>> >
>> > Following your instructions, we have uploaded the full content under the
>> > github repo:
>> > https://github.com/cristianoghersi/CayenneOSGi
>> >
>> > Basically, we have packaged the source code of 3.1 version into an OSGi
>> > bundle called cayenne-osgi, adding some stuff to manage the particular
>> > classloading features of OSGi.
>> > Then we added also another bundle, called Cayenne-3.1-Dependencies, that
>> > packages all the required dependencies.
>> >
>> > I'm at complete disposal for every clarification you need.
>> >
>> > I'll wait for your feedback.
>> >
>> > Best
>> > cghersi
>>
>>
>>
>

Re: Cayenne under OSGi

Posted by Cristiano Ghersi <cr...@abodata.com>.
Hi Andrus,

given your re-engineering of the structure, perhaps I can tell you the
changes we have plugged in in order to make the stuff work. They are quite
simple changes to the code, so perhaps is simpler for you to add these
pieces of code than trying to cope with the complete structure.

We just added ClassRegistry class in the *org.apache.cayenne.di.spi*
 package.
Moreover, the class *org.apache.cayenne.di.spi.DefaultAdhocObjectFactory* has
also been modified to be able to search in the ClassRegistry for classes:

public Class<?> getJavaClass(String className) throws ClassNotFoundException {

                // is there a better way to get array class from string name?

                if (className == null) {
                        throw new ClassNotFoundException("Null class name");
                }

                ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();

                if (classLoader == null) {
                        classLoader =
DefaultAdhocObjectFactory.class.getClassLoader();
                }

                //first for OSGi Environment: look for class in registry.
                //try with the class loader registry
                Class<?> registryClass =
ClassRegistry.getClassByName(className);
                if (registryClass != null) {
                        try {
                                return
registryClass.getClassLoader().loadClass(className);
                        }
                        catch (ClassNotFoundException cnfe) {
                        }
                }

                // use custom logic on failure only, assuming
primitives and arrays are not that
                // common
                try {
                        return Class.forName(className, true, classLoader);
                }

                if (!className.endsWith("[]")) {
                        if ("byte".equals(className)) {
                                return Byte.TYPE;
                        }
                        ...}




Generate an OSGi Bundle

To generate an OSGi bundle some changes are needed in the *pom.xml*.
First of all it is necessary to change the *packaging* type of the
project from *jar* to *bundle* as it is show in this snippet:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <groupId>org.apache.cayenne</groupId>
                <artifactId>cayenne-parent</artifactId>
                <version>3.1B2-SNAPSHOT</version>
                <relativePath>../../pom.xml</relativePath>
        </parent>
        <groupId>org.apache.cayenne.osgi</groupId>
        <artifactId>cayenne-osgi</artifactId>
        <name>Cayenne OSGified</name>
<packaging>bundle</packaging>  <url>http://maven.apache.org</url>

Then it is necessary to add a *plugin* to the *build* section:

<plugins>
        ...
        <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.3.7</version>
                <extensions>true</extensions>
                <configuration>
                        <instructions>
                                <Export-Package>org.apache.cayenne,
org.apache.cayenne.*</Export-Package>

<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                        </instructions>
                </configuration>
        </plugin>
        ...</plugins>

Finally you can generate the bundle jar

$ cd cayenne-osgi # or navigate to the root directory of the cayenne
osgi project
$ mvn org.apache.felix:maven-bundle-plugin:bundle

The bundle jar can be found in *cayenne-osgi/target/cayenne-osgi.jar.*

*
*

*
*

To use the Cayenne OSGi bundle the following steps must be performed:

   1. Import the .jar bundle generated with the above procedure
   2. Create and import a Cayenne *dependencies* bundle containing all the
   .jar files needed to satisfy the import packages of Cayenne bundle (the
   ones added to folder Cayenne-Dependencies folder in the github repo)
   3. Create a Fragment bundle (setting as the host Cayenne bundle) for
   each cayenne project. In the *src* folder of the fragment add the two
   cayenne xml files.


Hope this can help the integration.

Let me know if you need further clarification, I'm at complete disposal.

Best
cghersi



2013/2/1 Andrus Adamchik <an...@objectstyle.org>

> Hi cghersi,
>
> Thanks!
>
> Trying to make sense of the GitHub project structure and what is different
> from Cayenne. From what I can tell we need this piece in the pom:
>
>         <plugin>
>                 <groupId>org.apache.felix</groupId>
>                 <artifactId>maven-bundle-plugin</artifactId>
>                 <version>2.3.7</version>
>                 <extensions>true</extensions>
>                 <configuration>
>                         <instructions>
>                                 <Export-Package>org.apache.cayenne,
> org.apache.cayenne.*</Export-Package>
>
> <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
>                         </instructions>
>                 </configuration>
>         </plugin>
>
> and also the META-INF dir (
> https://github.com/cristianoghersi/CayenneOSGi/tree/master/cayenne-osgi/META-INF) ?
>
> Or is META-INF generated?
>
> Also integrating this into our convoluted build structure will be a
> challenge. One of the 3.2 undeclared goals is simplifying the build
> structure, so maybe once we start looking into it, we might consider the
> OSGi aspect. And in any event it is very helpful for us, even we can't
> simply patch Cayenne from what's on the GitHub. It gives a clear idea of
> what we need to do to make ours jars OSGi-friendly.
>
> Cheers,
> Andrus
>
> On Jan 31, 2013, at 3:42 PM, Cristiano Ghersi <
> cristiano.ghersi@abodata.com> wrote:
> > Good morning,
> >
> > My company (Abodata, www.abodata.com) has ported Cayenne into OSGi
> > environment, and we would like to contribute to Cayenne project with this
> > enhancement as I posted under user mailing list on October 2012.
> >
> > Following your instructions, we have uploaded the full content under the
> > github repo:
> > https://github.com/cristianoghersi/CayenneOSGi
> >
> > Basically, we have packaged the source code of 3.1 version into an OSGi
> > bundle called cayenne-osgi, adding some stuff to manage the particular
> > classloading features of OSGi.
> > Then we added also another bundle, called Cayenne-3.1-Dependencies, that
> > packages all the required dependencies.
> >
> > I'm at complete disposal for every clarification you need.
> >
> > I'll wait for your feedback.
> >
> > Best
> > cghersi
>
>
>

Re: Cayenne under OSGi

Posted by Andrus Adamchik <an...@objectstyle.org>.
Hi cghersi,

Thanks! 

Trying to make sense of the GitHub project structure and what is different from Cayenne. From what I can tell we need this piece in the pom:

	<plugin>
		<groupId>org.apache.felix</groupId>
		<artifactId>maven-bundle-plugin</artifactId>
		<version>2.3.7</version>
		<extensions>true</extensions>
		<configuration>
			<instructions>
				<Export-Package>org.apache.cayenne, org.apache.cayenne.*</Export-Package>
				<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
			</instructions>
		</configuration>
	</plugin>

and also the META-INF dir ( https://github.com/cristianoghersi/CayenneOSGi/tree/master/cayenne-osgi/META-INF ) ?

Or is META-INF generated?

Also integrating this into our convoluted build structure will be a challenge. One of the 3.2 undeclared goals is simplifying the build structure, so maybe once we start looking into it, we might consider the OSGi aspect. And in any event it is very helpful for us, even we can't simply patch Cayenne from what's on the GitHub. It gives a clear idea of what we need to do to make ours jars OSGi-friendly.

Cheers,
Andrus

On Jan 31, 2013, at 3:42 PM, Cristiano Ghersi <cr...@abodata.com> wrote:
> Good morning,
> 
> My company (Abodata, www.abodata.com) has ported Cayenne into OSGi
> environment, and we would like to contribute to Cayenne project with this
> enhancement as I posted under user mailing list on October 2012.
> 
> Following your instructions, we have uploaded the full content under the
> github repo:
> https://github.com/cristianoghersi/CayenneOSGi
> 
> Basically, we have packaged the source code of 3.1 version into an OSGi
> bundle called cayenne-osgi, adding some stuff to manage the particular
> classloading features of OSGi.
> Then we added also another bundle, called Cayenne-3.1-Dependencies, that
> packages all the required dependencies.
> 
> I'm at complete disposal for every clarification you need.
> 
> I'll wait for your feedback.
> 
> Best
> cghersi


Re: Cayenne under OSGi

Posted by Cristiano Ghersi <cr...@abodata.com>.
Hi Andrus, great job!

I have to say that we always used it under Equinox implementation, so
perhaps in Felix seems to be simpler.

Just two notes on our experience under OSGi that may help to overcome
eventual problems of class/resource loading.
1) OSGi load of resources like xml config file: this sometimes is tricky
under OSGi. We solved our problems creating another bundle as a fragment
host of cayenne-osgi bundle, where we place the **.map.xml, the
cayenne-MyDomain.xml and (optionally) the dbcp.properties (as we use
org.apache.commons.dbcp for pooled connections).
2) Class loading: if your bundle expose some methods to interact with DB,
the lazy load of the classes inside OSGi environment may bring you some
headache, as you cannot be sure on the order of class loading among the
different bundles (this is why we provided the ClassRegistry and force the
load of such classes in the start() of the bundle: to be sure that such
classes are correctly loaded from the correct bundle when we want!). This
strange behavior was discovered after one year that we were using Cayenne
under OSGi! So, perhaps, the fact that now with the test bundle Andrus
provided everything seems working can be misleading. But I cannot prove my
sentence as this is a bug very difficult to reproduce.

So, at the end, the implementation of Andrus seems effective and works well
for me, but the test of someone else may give us more feeling about the
resolution of the issue.

Bye
cghersi


2013/11/24 Andrus Adamchik <an...@objectstyle.org>

> So this is done. Cristiano, appreciate if you could try it in your
> environment. An example of how to use Cayenne with OSGi is available on
> GitHub [1]. Here is how you bootstrap it in your own module:
>
>   Module osgiModule =
> OsgiModuleBuilder.forProject(Activator.class).withDriver(Driver.class).module();
>   return new ServerRuntime("cayenne-osgi-example.xml", osgiModule);
>
> As you see, no need to enumerate your classes. Also I suspect instead of
> binding the driver, in a real OSGi environment Cayenne stack will need to
> refer to some OSGi service that encapsulates the DataSource. We can provide
> integrations for that too. And don’t forget to stop it when you your bundle
> is stopped, as you don’t want to keep Cayenne threads and other resources
> hanging around, eventually killing your container:
>
>   cayenneRuntime.shutdown();
>
> Cheers,
> Andrus
>
>
> [1] https://github.com/andrus/cayenne-osgi-example
>
>

Re: Cayenne under OSGi

Posted by Andrus Adamchik <an...@objectstyle.org>.
So this is done. Cristiano, appreciate if you could try it in your environment. An example of how to use Cayenne with OSGi is available on GitHub [1]. Here is how you bootstrap it in your own module:

  Module osgiModule = OsgiModuleBuilder.forProject(Activator.class).withDriver(Driver.class).module();
  return new ServerRuntime("cayenne-osgi-example.xml", osgiModule);

As you see, no need to enumerate your classes. Also I suspect instead of binding the driver, in a real OSGi environment Cayenne stack will need to refer to some OSGi service that encapsulates the DataSource. We can provide integrations for that too. And don’t forget to stop it when you your bundle is stopped, as you don’t want to keep Cayenne threads and other resources hanging around, eventually killing your container:

  cayenneRuntime.shutdown();

Cheers,
Andrus


[1] https://github.com/andrus/cayenne-osgi-example

Re: Cayenne under OSGi

Posted by Cristiano Ghersi <cr...@abodata.com>.
Hi All,

Great job Andrus!!

For the next step you were talking about, I think we can use this example:
http://www.snip2code.com/Snippet/12372/Use-Apache-Cayenne-under-OSGi-environmen
where you can see an example of a bundle activator.

Hope this can help in the following steps...

Bye
cghersi


2013/11/20 Andrus Adamchik <an...@objectstyle.org>

> After today’s round of changes (CAY-1886), I am able to start Cayenne
> bundles in an OSGi container (Felix). Here are the prerequisites (shown as
> “install” commands inside the Felix container). As you see we can’t use
> some of the direct dependencies of Cayenne, specifically commons-logging
> and velocity, in an OSGi container. However there are suitable replacements
> out there:
>
> install
> file:/Users/cayenne/.m2/repository/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar
> install
> file:/Users/cayenne/.m2/repository/org/slf4j/jcl-over-slf4j/1.7.5/jcl-over-slf4j-1.7.5.jar
> install
> file:/Users/cayenne/.m2/repository/org/slf4j/slf4j-api/1.7.5/slf4j-api-1.7.5.jar
> install
> file:/Users/cayenne/.m2/repository/org/slf4j/slf4j-simple/1.7.5/slf4j-simple-1.7.5.jar
> install
> file:/Users/cayenne/.m2/repository//org/apache/servicemix/bundles/org.apache.servicemix.bundles.velocity/1.7_6/org.apache.servicemix.bundles.velocity-1.7_6.jar
> install
> file:/Users/cayenne/.m2/repository/commons-lang/commons-lang/2.4/commons-lang-2.4.jar
>
> ... now finally install 2 Cayenne bundles ...
>
> install
> file:/Users/cayenne/work/cayenne/cayenne-di/target/cayenne-di-3.2.M2-SNAPSHOT.jar
> install
> file:/Users/cayenne/work/cayenne/cayenne-server/target/cayenne-server-3.2.M2-SNAPSHOT.jar
>
> after that cayenne-server can be started, and I end up with the following
> container state:
>
> g! lb
> START LEVEL 1
>    ID|State      |Level|Name
>     0|Active     |    0|System Bundle (4.2.1)
>     1|Active     |    1|Apache Felix Bundle Repository (1.6.6)
>     2|Active     |    1|Apache Felix Gogo Command (0.12.0)
>     3|Active     |    1|Apache Felix Gogo Runtime (0.10.0)
>     4|Active     |    1|Apache Felix Gogo Shell (0.10.0)
>    16|Resolved   |    1|Commons Collections (3.2.1)
>    23|Resolved   |    1|jcl-over-slf4j (1.7.5)
>    24|Resolved   |    1|slf4j-api (1.7.5)
>    25|Resolved   |    1|slf4j-simple (1.7.5)
>    27|Resolved   |    1|Cayenne Dependency Injection Container
> (3.2.0.M2-SNAPSHOT)
>    31|Resolved   |    1|Apache ServiceMix :: Bundles :: velocity (1.7.0.6)
>    32|Active     |    1|Cayenne Server (3.2.0.M2-SNAPSHOT)
>    35|Resolved   |    1|Commons Lang (2.4.0)
>
> Next step is to write a bundle that uses Cayenne and see what we need to
> do with the ClassLoader.
>
> A.
>
>
>

Re: Cayenne under OSGi

Posted by Andrus Adamchik <an...@objectstyle.org>.
After today’s round of changes (CAY-1886), I am able to start Cayenne bundles in an OSGi container (Felix). Here are the prerequisites (shown as “install” commands inside the Felix container). As you see we can’t use some of the direct dependencies of Cayenne, specifically commons-logging and velocity, in an OSGi container. However there are suitable replacements out there:

install file:/Users/cayenne/.m2/repository/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar
install file:/Users/cayenne/.m2/repository/org/slf4j/jcl-over-slf4j/1.7.5/jcl-over-slf4j-1.7.5.jar
install file:/Users/cayenne/.m2/repository/org/slf4j/slf4j-api/1.7.5/slf4j-api-1.7.5.jar
install file:/Users/cayenne/.m2/repository/org/slf4j/slf4j-simple/1.7.5/slf4j-simple-1.7.5.jar
install file:/Users/cayenne/.m2/repository//org/apache/servicemix/bundles/org.apache.servicemix.bundles.velocity/1.7_6/org.apache.servicemix.bundles.velocity-1.7_6.jar
install file:/Users/cayenne/.m2/repository/commons-lang/commons-lang/2.4/commons-lang-2.4.jar

... now finally install 2 Cayenne bundles ...

install file:/Users/cayenne/work/cayenne/cayenne-di/target/cayenne-di-3.2.M2-SNAPSHOT.jar
install file:/Users/cayenne/work/cayenne/cayenne-server/target/cayenne-server-3.2.M2-SNAPSHOT.jar

after that cayenne-server can be started, and I end up with the following container state:

g! lb
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (4.2.1)
    1|Active     |    1|Apache Felix Bundle Repository (1.6.6)
    2|Active     |    1|Apache Felix Gogo Command (0.12.0)
    3|Active     |    1|Apache Felix Gogo Runtime (0.10.0)
    4|Active     |    1|Apache Felix Gogo Shell (0.10.0)
   16|Resolved   |    1|Commons Collections (3.2.1)
   23|Resolved   |    1|jcl-over-slf4j (1.7.5)
   24|Resolved   |    1|slf4j-api (1.7.5)
   25|Resolved   |    1|slf4j-simple (1.7.5)
   27|Resolved   |    1|Cayenne Dependency Injection Container (3.2.0.M2-SNAPSHOT)
   31|Resolved   |    1|Apache ServiceMix :: Bundles :: velocity (1.7.0.6)
   32|Active     |    1|Cayenne Server (3.2.0.M2-SNAPSHOT)
   35|Resolved   |    1|Commons Lang (2.4.0)

Next step is to write a bundle that uses Cayenne and see what we need to do with the ClassLoader.

A.


Re: Cayenne under OSGi

Posted by Andrus Adamchik <an...@objectstyle.org>.
So I finally started on the actual OSGi task. Here is what we have:

> 1. Reorg Cayenne Maven structure, making cayenne-server and cayenne-client real Maven modules instead of aggregates. We’ve discussed this a few times, and IIRC I was the only one who opposed it :) I no longer do. We can use <optional> and “provided” dependencies to exclude the extras like JGroups and keep it clean.

This was done on Sunday.

> 2. We need to add OSGi metadata to cayenne-server (and other Cayenne jars in the chain… likely just cayenne-di).

Just committed configs needed to turn cayenne-di.jar and cayenne-server.jar into proper OSGi bundles. I used the default configuration of maven-bundle-plugin, so every single Cayenne package is exported in the bundle. In the future we may be more specific. cayenne-di.jar has no dependencies. cayenne-server.jar has a bunch of optional dependencies, and 4 required ones:

cayenne-di
commons-collections
commons-logging
velocity

Also to generate a proper OSGi version (3.2.0.M2-SNAPSHOT) I had to add a dot to our Maven versioning scheme, so the trunk is now called 3.2.M2-SNAPSHOT. Which was probably the right thing to do anyways.

> 3. We need to create OsgiServerModule with an overridden AdhocObjectFactory. This will implement refactored ClassRegistry and will load all model classes per this example: http://www.snip2code.com/Snippet/12313/Apache-Cayenne--correctly-load-classes-u 
> 4. We may (or may not?) put those few OSGi classes in a separate cayenne-server-osgi module (to avoid dependency on OSGi framework in the base cayenne-server).

Still TODO.

Andrus



On Nov 14, 2013, at 5:56 PM, Andrus Adamchik <an...@objectstyle.org> wrote:

> So thanks to Cristiano pinging me offline, I spent some time on reviewing this again. I think we need to take the following steps to integrate Abodata’s OSGi code (or follow it as a pattern when we write ours) :
> 
> 1. Reorg Cayenne Maven structure, making cayenne-server and cayenne-client real Maven modules instead of aggregates. We’ve discussed this a few times, and IIRC I was the only one who opposed it :) I no longer do. We can use <optional> and “provided” dependencies to exclude the extras like JGroups and keep it clean.
> 
> 2. We need to add OSGi metadata to cayenne-server (and other Cayenne jars in the chain… likely just cayenne-di).
> 
> 3. We need to create OsgiServerModule with an overridden AdhocObjectFactory. This will implement refactored ClassRegistry and will load all model classes per this example: http://www.snip2code.com/Snippet/12313/Apache-Cayenne--correctly-load-classes-u 
> 
> 4. We may (or may not?) put those few OSGi classes in a separate cayenne-server-osgi module (to avoid dependency on OSGi framework in the base cayenne-server).
> 
> I placed #1 in my work stack (and really hope something else doesn’t pop up that pushes it down :-/ ) I don’t think Cristiano can create sensible patches against trunk without it. After this is done, we can discuss whether me or Cristiano can do 2..4.
> 
> Andrus
> 
> On Jan 31, 2013, at 3:42 PM, Cristiano Ghersi <cr...@abodata.com> wrote:
>> Good morning,
>> 
>> My company (Abodata, www.abodata.com) has ported Cayenne into OSGi
>> environment, and we would like to contribute to Cayenne project with this
>> enhancement as I posted under user mailing list on October 2012.
>> 
>> Following your instructions, we have uploaded the full content under the
>> github repo:
>> https://github.com/cristianoghersi/CayenneOSGi
>> 
>> Basically, we have packaged the source code of 3.1 version into an OSGi
>> bundle called cayenne-osgi, adding some stuff to manage the particular
>> classloading features of OSGi.
>> Then we added also another bundle, called Cayenne-3.1-Dependencies, that
>> packages all the required dependencies.
>> 
>> I'm at complete disposal for every clarification you need.
>> 
>> I'll wait for your feedback.
>> 
>> Best
>> cghersi
> 
> 


Re: Cayenne under OSGi

Posted by Andrus Adamchik <an...@objectstyle.org>.
On Nov 14, 2013, at 5:56 PM, Andrus Adamchik <an...@objectstyle.org> wrote:

> 1. Reorg Cayenne Maven structure, making cayenne-server and cayenne-client real Maven modules instead of aggregates. We’ve discussed this a few times, and IIRC I was the only one who opposed it :) I no longer do. We can use <optional> and “provided” dependencies to exclude the extras like JGroups and keep it clean.

Oh and if anyone thinks this is controversial for any reason, please comment.

A.


Re: Cayenne under OSGi

Posted by Andrus Adamchik <an...@objectstyle.org>.
So thanks to Cristiano pinging me offline, I spent some time on reviewing this again. I think we need to take the following steps to integrate Abodata’s OSGi code (or follow it as a pattern when we write ours) :

1. Reorg Cayenne Maven structure, making cayenne-server and cayenne-client real Maven modules instead of aggregates. We’ve discussed this a few times, and IIRC I was the only one who opposed it :) I no longer do. We can use <optional> and “provided” dependencies to exclude the extras like JGroups and keep it clean.

2. We need to add OSGi metadata to cayenne-server (and other Cayenne jars in the chain… likely just cayenne-di).

3. We need to create OsgiServerModule with an overridden AdhocObjectFactory. This will implement refactored ClassRegistry and will load all model classes per this example: http://www.snip2code.com/Snippet/12313/Apache-Cayenne--correctly-load-classes-u 

4. We may (or may not?) put those few OSGi classes in a separate cayenne-server-osgi module (to avoid dependency on OSGi framework in the base cayenne-server).

I placed #1 in my work stack (and really hope something else doesn’t pop up that pushes it down :-/ ) I don’t think Cristiano can create sensible patches against trunk without it. After this is done, we can discuss whether me or Cristiano can do 2..4.

Andrus

On Jan 31, 2013, at 3:42 PM, Cristiano Ghersi <cr...@abodata.com> wrote:
> Good morning,
> 
> My company (Abodata, www.abodata.com) has ported Cayenne into OSGi
> environment, and we would like to contribute to Cayenne project with this
> enhancement as I posted under user mailing list on October 2012.
> 
> Following your instructions, we have uploaded the full content under the
> github repo:
> https://github.com/cristianoghersi/CayenneOSGi
> 
> Basically, we have packaged the source code of 3.1 version into an OSGi
> bundle called cayenne-osgi, adding some stuff to manage the particular
> classloading features of OSGi.
> Then we added also another bundle, called Cayenne-3.1-Dependencies, that
> packages all the required dependencies.
> 
> I'm at complete disposal for every clarification you need.
> 
> I'll wait for your feedback.
> 
> Best
> cghersi