On 04/03/2011, at 11:44 PM, Glaeser, Thomas wrote: > Niclas - Well. The current OSGi plugin is very simple as it basically only > invokes BND to generate the manifest. As of now, the OSGi plugin itself does > not apply the Java plugin. Let's discuss the following cases > > (1) Apply the OSGi plugin together with the Java Plugin > (2) Apply the OSGi plugin together with the War Plugin > > I guess over here we are in a similar situation like you guys from Qi4j. We > have mostly non OSGi-aware applications but moving more and more into the > direction of OSGi. More and more projects we build need to run in the two > different execution environments. > > Right now, case (1) works reasonable well for simple scenarios where you > don't want to embed any dependencies into your bundle and don't work with > fragments. Here we use an extension to the Gradle OSGi plugin in order to > handle embedded jar files. > > I have not invested anything in case (2), however would expect some surprises. > > But what should happen is that with case (2) all your runtime dependencies > will be embedded into the bundle under path WEB-INF/lib while with case (1) > it is expected that your runtime dependencies are provided as part of the > application classpath. > > So we already have different behavior here when it comes to runtime > dependencies. This is not good, one would expect the same handling of > dependencies no matter what kind of OSGi bundle gets build. The reason for > this is, that the current OSGi plugin does not care about dependency > configurations at all. This has to change as an OSGi classpath will be > different from a plain old Java classpath. > > Now I would argue that an OSGi bundle is very similar to a WAR. I believe > that Peter Kriens documentation about WAB confirms this. Both are container > applications.
I agree that we should think of OSGi bundles as similar to WARs. We could also think of a jar published to a repository in a similar way, where the ivy.xml/pom.xml descriptor provides meta-data about what must be provided by the execution container at runtime. More generally, we might do something like: * A Gradle project bundles bytecode for the JVM into a number of different archives. These archives might be a JAR, WAR, OSGi bundle, and so on, or some combination of these. We might also model GWT/Android/GAE applications and Gradle plugins, and so on, the same way. * At build time, a subset of runtime dependencies for the project must be embedded in the archive. For example, a WAR generally embeds (all runtime dependencies - those dependencies provided by the web container). A 'fat' JAR might embed all runtime dependencies. An OSGi bundle might embed (all runtime dependencies - those provided by the container itself - those provided as services in other bundles). * At build time, some meta-data is generated to describe to the target container which runtime dependencies the archive now requires. This meta-data is included either in the archive, in the case of an OSGi bundle, or published with the archive, such as in the case of a JAR + pom.xml. The key point here is that it is the target environment that determines which dependencies will be provided at runtime, and those which need to be embedded. That is, there is no single 'provided' classpath. Instead, there are potentially several. I think it would be useful to model the target environments/containers, so that: * A target environment can define which dependencies will be provided by that environment. * A target environment can contribute to the compile classpath for the project. For example, we might have a 'generic servlet 3.0 container', which adds the appropriate servlet api, and so on to the compile classpath. Or we might have a 'jetty 7 container' which adds the jetty-specific api to the compile classpath. Similarly for 'generic OSGi container' and 'equinox OSGi container' * A target environment can influence generation of the archive. For example, we might have a 'tomcat 7.0 container' which adds, say, some tomcat-specific descriptor to the WAR. > > This would have some consequences for the new OSGi plugin > - It would need to apply the Java plugin internally the same way the WAR > plugin does > - The meaning of the provided* configurations are the same as with the WAR > plugin > (- There would be additional supply* configurations; that's something the WAR > doesn't have) I would do this slightly differently: 1. Split the Java plugin into 3 pieces: * A 'java' plugin which knows how to compile Java source into bytecode and how to run unit tests for it. * A 'jar-library' plugin which knows how to build and publish a plain jar. * A 'java-runtime' base plugin which provides the minimal pieces to define the runtime meta-data for the project: the set of classes, and the set of runtime dependencies. The 'jar-library' plugin would: * Implicitly apply the 'java-runtime' plugin. * Add the jar task. * Configure the publications so that the jar is published, along with the runtime dependencies in the dependency descriptor. 2. Change the 'osgi' plugin to: * Implicitly apply the 'java-runtime' plugin. It would not apply the 'java' plugin. * Add an osgiBundle task. It would not modify the jar task. It would create a separate bundle task. * Configure the publications so that the bundle is published. * Introduce the concept of target OSGi container. 3. Change the 'war' plugin to: * Implicitly apply the 'java-runtime' plugin. It would not apply the 'java' plugin. * Add the war task. * Configure the publications so that the war is published. * Introduce the concept of target web container. * We would remove the provided* configurations. 4. Change the 'application' plugin to: * Implicitly apply the 'java-runtime' plugin. It would not apply the 'java' plugin. * Add the distZip and install tasks. * Configure the publications so that the application zip is published. This approach allows: * Creating any combination of stand-alone jar, OSGi bundle and WAR. * Multiple jars, bundles or WARS, each targeting a different environment. * A project which contains no Java source code. For example, a parent project which aggregates the classes of its children. Or a Groovy/Scala/Clojure project. > > When migration your project from POJO to OSGi the following would need to be > done > - Apply the OSGi plugin +instead+ of the Java plugin > - Replace most, if not all, of your compile/runtime dependencies by > providedCompile/providedRuntime > > I would consider this a minor migration effort. One has to divide the project > dependencies into three buckets anyway when moving to OSGi. When running with > Equinox, the feature descriptor would list additional dependencies (supply*) > that need to be injected into the execution environment in order to run your > bundle. > > Everything build with the new OSGi plugin could be executed in an OSGi > container +or+ as normal Java application, the only difference is how you > would create the classpath from the three sets of configurations. Does this > make sense? > > /Thomas > > -----Original Message----- > From: Niclas Hedhman [mailto:[email protected]] > Sent: Friday, March 04, 2011 1:42 AM > To: Glaeser, Thomas > Cc: [email protected] > Subject: Re: Gradle's OSGi plugin > > On Fri, Mar 4, 2011 at 8:01 AM, Glaeser, Thomas > <[email protected]> wrote: >> So for now let's consider these two runtime configurations only: >> >> (1) runtime >> (2) providedRuntime >> >> These configurations exist already in Gradle and Maven and we do not >> want to redefine them. > > Good. > >> The two configurations are required for building Web Archives (WAR). >> Please see the Gradle WAR Plugin documentation for their meaning. What >> we can take from here is that the libraries from the runtime >> configuration are embedded into the WAR while the dependencies from >> the providedRuntime configuration are provided by the hosting container. >> >> Now, how does this all map to Web Application Bundle (WAB)? Please see >> the BND documentation. >> >> So someone who used the Gradle War Plugin should get a valid WAB by >> simply also applying the OSGi Plugin. In my opinion this would be the >> first use case the new OSGi Plugin needs to pass. > > If runtime implies 'embedded', then we *must* have a different produced > artifact from the OSGi project. Why? > > As I explained; Many projects, Qi4j included, are not OSGi specific, only > OSGi-aware. I.e. their primary use is 'normal', but they provide the Bundle > Manifest entries so they can be loaded in OSGi. It is *not* reasonable to bug > these projects down with having all their dependencies embedded in the output > artifact. > > But, as I discovered for Qi4j, some dependencies are not OSGi-aware, and to > allow deployment of "Qi4j bundles", I either need to OSGify those > dependencies (hard work) or provide the runtime configuration embedded in > each Qi4j library. So that requirement contradicts the previous paragraph. > Hence, I am leaning very heavily towards generation of separate artifacts for > the "normal jar" vs "bundle jar". > > > Makes sense? > > > Cheers > -- > Niclas Hedhman, Software Developer > http://www.qi4j.org - New Energy for Java > > I live here; http://tinyurl.com/3xugrbk > I work here; http://tinyurl.com/24svnvk > I relax here; http://tinyurl.com/2cgsug > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > -- Adam Murdoch Gradle Developer http://www.gradle.org Co-Founder and VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting http://www.gradleware.com
