Cayenne under OSGi works

From: Jeremias Maerki (de..eremias-maerki.ch)
Date: Wed May 13 2009 - 04:08:14 EDT

  • Next message: Tobias Schoessler: "Re: reverse engineering partially changed schema"

    Since there was no mention of OSGi on the Cayenne lists recently, I
    thought I would just drop a note that I've managed to get Cayenne (Trunk)
    to run in an OSGi environment. After getting OpenJPA to work under OSGi,
    doing the same for Cayenne was surprisingly easy.

    Ok, Cayenne (and some of its dependencies) doesn't provide OSGi metadata
    in the manifest header, yet, so I had to modify the JARs (including some
    dependencies) with the usual necessary imports and exports (no
    Dynamic-Import necessary). I've used my own unpublished tools to do that
    so I can't contribute that back to the project, yet, but I hope to find
    time in a few weeks to do that. It would be great for Cayenne to be a
    first class citizen under OSGi.

    One thing that was necessary was to set the context class loader on the
    current thread inside what I called a persistence session
    (~ObjectContext) so the Cayenne bundle can load the classes from the
    domain bundle which it usually can't see in OSGi. Class.forName() is
    usually problematic under OSGi so it's great to see that the context
    class loader is well used inside Cayenne. That simplifies things.

    Another problem was the configuration loading. I'm not sure my approach
    will already work with multiple domains (probably not), but a special
    Confguration subclass allowed me to load the cayenne.xml from the place
    I wanted to (META-INF/cayenne/cayenne.xml instead of the root).

    public class LocalConfiguration extends MultiProjectConfiguration {

        public LocalConfiguration() {
            ClasspathResourceFinder finder = new MetaInfResourceFinder();
            finder.setClassLoader(this.getClass().getClassLoader());
            this.resourceFinder = finder;
        }

        private class MetaInfResourceFinder extends ClasspathResourceFinder {

            public MetaInfResourceFinder() {
                super();
                this.rootPaths.clear();
                addRootPath("/META-INF/cayenne");
            }

        }

    }

    I've not configured the data node in cayenne.xml (just the data map) as
    the DataSource is only known at runtime (the DataSource here is just
    another OSGi service). Here's how I attach the DataSource to the domain:

        public static DataDomain setupDataDomain(DataSource ds) {
            Configuration.initializeSharedConfiguration(LocalConfiguration.class);
            Configuration cfg = Configuration.getSharedConfiguration();
            DataDomain domain = cfg.getDomain(DOMAIN_NAME);
            DataMap map = domain.getMap(MAP_NAME);

            domain.removeDataNode(MAIN_DATA_NODE);

            DataNode node = new DataNode(MAIN_DATA_NODE);
            node.setDataSource(ds);
            node.setSchemaUpdateStrategy(new SkipSchemaUpdateStrategy());
            node.addDataMap(map);
            node.setAdapter(new AutoAdapter(node.getDataSource()));

            domain.addNode(node);
            return domain;
        }

    At any rate, this was rather painless once I started to understood how
    Cayenne works. I'm looking forward to exploring Cayenne further now. The
    first steps are done.

    Jeremias Maerki



    This archive was generated by hypermail 2.0.0 : Wed May 13 2009 - 04:08:53 EDT