开发者

What is a reasonable OSGi development workflow?

I'm using OSGi for my latest project at work, and it's pretty beautiful as far as modularity and functionality.

But I'm not happy with the development workflow. Eventually, I plan to have 30-50 separate bundles, arranged in a dependency graph - supposedly, this is what OSGi is designed for. But I can't figure out a clean way to manage dependencies at compile time.

Example: You have bundles A and B. B depends on packages defined in A. Each bundle is developed as a separate Java project.

In order to compile B, A has to be on the javac classpath.

Do you:

  1. Reference the file system location of project A in B's build script?
  2. Build A and throw the jar into B's lib directory?
  3. Rely on Eclipse's "referenced projects" feature and always use Eclipse's classpath to build (ugh)
  4. Use a common "lib" directory for all projects and dump the bundle jars there after compilation?
  5. 开发者_StackOverflow中文版Set up a bundle repository, parse the manifest from the build script and pull down the required bundles from the repository?

No. 5 sounds the cleanest, but also like a lot of overhead.


My company has 100+ bundle projects and we use Eclipse to manage the dependencies. However, I don't recommend the "Required Plugins" approach to managing the dependencies. Your best bet is to create Plugin Projects. Export just the packages from each project that you want to be visible. Then on the import side do the following:

Open the Manifest editor

Goto the dependencies tab In the bottom left is a section called "Automated Management of Dependencies"

Add any plugins that the current plugin depends on there

Once you have code written, you can click the "add dependencies" link on that tab to auto-compute the imported packages.

If you run from Eclipse, this gets done automatically for you when you execute.

The benefits of this approach is that your built bundles are only using OSGi defined package import/export mechanism, as opposed to something from Eclipse.

If you want to learn more, I'd recommend going to this site and ordering the book. It's excellent.

http://equinoxosgi.org/


Well, do what you should have a long time before, separate implementation and API ... ok, this is not always that easy on existing systems but that model has a huge bang for your buck. Once your API is in a separate (much more stable) bundle/jar you can compile the clients and implementations against that bundle/jar.

One of the key qualities of a successful bundle is that it makes as little assumptions about the outside world as possible. This implies you do not have to compile against the bundles you run against in runtime, I have a preference to try hard to not do that. You should only compile against the bundles minimum set of dependencies. If assumptions are made they are explicit as imported packages and the use of services. Well designed OSGi systems attempt to use services for all inter-bundle communications. Not only does this model get rid of class loading issues it also makes your build setup more decoupled.

Unfortunately most code is written as libraries that have a rather wide interface because they hand code lots of the functionality that services provide out of the box like Factories and Listeners. This code has a tight relationship between implementation and API so you have to have the same on the class path during compile and in OSGi. One solution to this problem is to include this kind of code inside the bundle using it (but make sure no objects of this library leak to other bundles). A bit of extra memory consumption but it saves you from some headaches.

So with OSGi, try to create systems relying on services and compile against their service API, not an implementation bundle.


Basically, you can use:

  • source dependency (with Eclipse's "referenced projects")
  • binary dependency (using the jar of bundle A)

But since binary dependency is much cleaner, it is also the kind of dependency best managed by a release management framework like maven.
And you can integrate maven in your Eclipse project through m2eclipse.

The Maven plugin to use would then be: maven-bundle-plugin, that you can see in action in:

  • Using maven to create an osgi bundle (osgi felix sample)
  • Bundle Plugin for Maven
  • Getting the benefits of maven-bundle-plugin in other project types
  • How to build OSGi bundles using Maven Bundle Plugin

Consider this more real-world example using Felix' Log Service implementation.
The Log Service project is comprised of a single package: org.apache.felix.log.impl.
It has a dependency on the core OSGi interfaces as well as a dependency on the compendium OSGi interfaces for the specific log service interfaces. The following is its POM file:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.apache.felix</groupId>
  <artifactId>org.apache.felix.log</artifactId>
  <packaging>bundle</packaging>
  <name>Apache Felix Log Service</name>
  <version>0.8.0-SNAPSHOT</version>
  <description>
    This bundle provides an implementation of the OSGi R4 Log service.
  </description>
  <dependencies>
    <dependency>
      <groupId>${pom.groupId}</groupId>
      <artifactId>org.osgi.core</artifactId>
      <version>0.8.0-incubator</version>
    </dependency>
    <dependency>
      <groupId>${pom.groupId}</groupId>
      <artifactId>org.osgi.compendium</artifactId>
      <version>0.9.0-incubator-SNAPSHOT</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Export-Package>org.osgi.service.log</Export-Package>
            <Private-Package>org.apache.felix.log.impl</Private-Package>
            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
            <Bundle-Activator>${pom.artifactId}.impl.Activator</Bundle-Activator>
            <Export-Service>org.osgi.service.log.LogService,org.osgi.service.log.LogReaderService</Export-Service>
          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>


There is a 6th option, which I've used for several projects, which is to use a single Eclipse project (not a plugin project, but just an ordinary Java project) and put all source code in there. A build file associated with the project will simply compile all code in a single pass and subsequently create bundles out of the compiled classes (using Bnd from Ant or from the soon to be released BndTools).

This has the downside that it does not honor visibility at development and compile time, but the upside that it's a really simple development model that gives you very fast build and deploy times.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜