Here are some intermediate results on using the FactorySPI pattern in an OSGi environment:
- I've verified that it works as expected as long as you do not use wrapped JARs in your bundles and configure buddy classloading appropriately. - OSGifying all of Geotools will be harder than expected due to a considerable number of split packages in Geotools. The whole story is a bit longer, and this mailing list is probably not the best place to keep track of the results. I'm thinking of writing an article in the Geotools wiki to summarize the results and give some code examples and links to relevant documentation elsewhere, if that would be ok for the Geotools community - of course I don't want to act against project policies. For the time being, let me just give an overview of what I tried to do. It took me longer than I had hoped, but after a while I realized that I was trying to solve too many problems at once. My initial plan was to 0) Identify a minimal self-contained subset of Geotools libraries to show that the FactorySPI pattern works with OSGi, simply by changing the corresponding POMs to build OSGi bundles instead of plain old JARs. When I got stuck with the split packages, I realized that it would help to deal with the following issues one after another: 1) Manually convert a subset of Geotools libraries to OSGi bundles to show that FactorySPIs work in OSGi. 2) Change the POMs to turn the generated JARs into OSGi bundles by inserting handcrafted MANIFEST.MF files. 3) Replace Import-Bundle by Import-Package in the manifests, or in fact let the maven-bundle-plugin do this automatically. Having split the original problem into these steps, it was fairly straightforward to solve step 1, and this was the main issue anyway. Step 3) could be equally straightforward if Geotools would take care to avoid split packages. (A split package is a Java package occurring in more than one OSGi bundle, e.g. org.geotools.factory in gt-main AND in gt-metadata). There are ways of dealing with split packages both in OSGI and in the maven-bundle-plugin and I'm about 95 % convinced that you could make it work after careful analysis of the package structure and some manual work in the POMs, but it would probably be a lot easier to simply make package names globally unique within Geotools. I don't know if this is an option, considering backward compatibility, so I left it at that. Step 2) is not of much value in itself, I only see it as a fallback solution if it turns out that Geotools packages cannot be refactored, and that the split-package mechanisms do not work. The drawback would be that you'd have to use bundle instead of package dependencies (Import-Bundle vs. Import-Package). Some more details about step 1): I started off with the following subset of geotools libraries from the Geotools svn trunk gt-api gt-cql gt-main gt-metadata gt-referencing taking org.geotools.filter.expression.Function as an example of Factory SPI usage, invoking CommonFactoryFinder.getFunctions(null). If you only use gt-main, gt-metadata and gt-api, you get 139 functions from gt-main. If you add gt-cql and its dependency gt-referencing, you get another function from gt-api, thus a total of 140 functions. These 5 Geotools libraries have a number of external dependencies: jai-codec jai-core commons-beanutils commons-collections commons-logging commons-pool jdom geoapi jsr-275 jts log4j junit4 vecmath osgi I turned each of these dependencies into a separate OSGi bundle - actually, I found osgified versions for most of them in the SpringSource Enterprise Bundle Repository. I ran a full Maven build of all of Geotools from the command line to get hold of the required generated sources (JAXB, JavaCC). Then I forgot about Maven and used Eclipse PDE to manually create my 5 Geotools bundles such that bundle org.geotools.xxx corresponds to library gt-xxx. At first, I created a dedicated target platform, containing just the external dependency bundles listed above, and I configured my Eclipse workspace to use this target platform. Then I created the Geotools bundles as Plug-in projects, adding one or more source folders per project, including the generated sources produced by Maven. Using the PDE Manifest editor, I added the Import-Bundle statement via the "Required plug-ins" form. The class which scans the META-INF/services resources is FactoryRegistry in bundle org.geotools.metadata. You need to make sure that this class will see the resources contributed by other bundles, which can be achieved by Eclipse buddy classloading. So I manually added Eclipse-BuddyPolicy: registered to the org.geotools.metadata manifest, and a matching Eclipse-RegisterBuddy: org.geotools.metadata to the manifests of org.geotools.main and org.geotools.cql (the bundles containing the META-INF/services resources). Finally, I created a simple factoryclient bundle which invokes CommonFactoryFinder.getFunctions() in its bundle activator and prints out the number of registered functions. This bundle only depends on bundles org.geotools.main, geoapi and package org.osgi.framework. Now when I launch this bundle with an Eclipse OSGi framework launcher, I get the desired number of 139 or 140 functions, depending on whether or not the launch configuration includes the org.geotools.cql bundle. QED I hope this was sufficient to get the general idea, and I'm happy to provide more details on the Maven stuff for step 3 if required. Just let me know if this is of any value and how to proceed. Regards, Harald -----Ursprüngliche Nachricht----- Von: [EMAIL PROTECTED] im Auftrag von Wellmann, Harald Gesendet: Di 02.09.2008 23:31 An: Jody Garnett Cc: User-friendly Desktop Internet GIS Betreff: AW: AW: [udig-devel] External dependencies innet.refractions.udig.libs My guess is this: <quote> If so that would be great news; what we really wanted to do is have a situation like: - org.geotools.main plugin -- contains gt-main-2.6-SNAPSHOT.jar -- wants to process a factory SPI (looking for every jar with a services file for "org.opengis.filter.Function") </quote> It seems you're trying to wrap a plain old JAR in an OSGi bundle. So you would deliver an org.geotools.main_2.6.SNAPSHOT.jar bundle (aka Eclipse plugin). When you unzip this outer JAR, you get the OSGi manifest and the plain old gt-main-2.6-SNAPSHOT.jar. This wrapping is not really required - after all, an OSGi bundle is nothing but a JAR with some extra manifest headers. If you simply add the extra headers to the MANIFEST.MF in gt-main*.jar, then your gt-main*.jar _is_ an OSGi bundle, and you won't even break anything for people putting this JAR on their plain old classpath. The difference is that your META-INF/services/whatever is now a resource in a JAR and no longer hidden in a JAR within a JAR. Ok, I'll give this a try with gt-main and gt-renderer, which may take a couple of days, but I'll get back to you on this. Regards, Harald ******************************************* innovative systems GmbH Navigation-Multimedia Geschaeftsfuehrung: Edwin Summers - Kevin Brown - Regis Baudot Sitz der Gesellschaft: Hamburg - Registergericht: Hamburg HRB 59980 ******************************************* Diese E-Mail enthaelt vertrauliche und/oder rechtlich geschuetzte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtuemlich erhalten haben, informieren Sie bitte sofort den Absender und loeschen Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet. This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and delete this e-mail. Any unauthorized copying, disclosure or distribution of the contents in this e-mail is strictly forbidden. *******************************************
<<winmail.dat>>
_______________________________________________ User-friendly Desktop Internet GIS (uDig) http://udig.refractions.net http://lists.refractions.net/mailman/listinfo/udig-devel