9

We have lot of components out of which we want to modularize only a few to start with. Wondering what is the best way (in the context of my build environment) to create bundles out of all these components?

My environment: Java 6, Maven 2.2.1, Hudson

Technologies: Spring 3.0.5, WebSphere 7, Hibernate 3.2.x and most of apache commons.

Requirements

  1. Modularize only few components. Rest of the components can export all of the packages.
  2. When imported into eclipse, I should be able to see the bundles of imported-packages as dependencies in build path (mvn eclipse:eclipse doesn't seem to do this)
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327

3 Answers3

11

Start by only changing the MANIFEST.MF entries such that all your artifacts become bundles - they obviously won't magically work but it's a good non-destructive first step.

When using the maven-bundle-plugin ensure you set extensions and supportedProjectTypes as you may have problems with CI builds, Maven repos and m2e failing if the packaging type is bundle (see end).

Test your riskiest/core external dependencies early on - for example if you're using JPA for persistence then ensure that the provider works in an OSGi environment with your domain bundle and JDBC driver.

If you're migrating from Java EE/spring look at Karaf or Virgo. But if your components are for embedded systems or have no external dependencies the Felix or Equinox may be enough (though check out the pax-url project if that's the case).

Might be worth editing your question to be a bit more specific about the domain/technologies?


eclipse:eclipse only generates that when the project is first configured, m2e's lifecycle problems might be a bit of pain but it's far better than using the old eclipse plug.


The following will add manifest entries to your existing artifacts without changing them in any other way. It tells the standard maven jar and war plugins to use the MANIFEST.MF generated by maven-bundle-plugin.

Put this in the parent POM:

<pluginManagement>
<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <version>2.3.7</version>
    <extensions>true</extensions>
    <configuration>
        <archive>
            <addMavenDescriptor>true</addMavenDescriptor>
        </archive>
        <supportedProjectTypes>
            <supportedProjectType>jar</supportedProjectType>
            <supportedProjectType>war</supportedProjectType>
        </supportedProjectTypes>
        <instructions>
            <Built-By>${project.organization.name}</Built-By>
            <Bundle-Vendor>${project.organization.name}</Bundle-Vendor>
            <Bundle-ContactAddress>${project.organization.url}</Bundle-ContactAddress>
            <Bundle-Description>${project.description}</Bundle-Description>
            <Bundle-DocURL>${bundle.doc.url}</Bundle-DocURL>
            <Bundle-Category>${bundle.category}</Bundle-Category>
            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
            <Bundle-Version>${project.version}</Bundle-Version>

            <Import-Package>*</Import-Package>
            <Export-Package>*</Export-Package>
        </instructions>
    </configuration>
    <executions>
        <execution>
            <id>bundle</id>
            <goals>
                <goal>manifest</goal>
            </goals>
            <phase>prepare-package</phase>
            <inherited>true</inherited>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.3.1</version>
    <configuration>
        <archive>
            <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
        </archive>
    </configuration>
</plugin>

<plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.1.1</version>
    <executions>
        <execution>
            <id>create-war</id>
            <phase>package</phase>
            <goals>
                <goal>war</goal>
            </goals>
            <inherited>true</inherited>
        </execution>
    </executions>
    <configuration>
        <archive>
            <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
        </archive>
    </configuration>
</plugin>
</pluginManagement>

Then in child POMs, you may simply do:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
        </plugin>
        <!-- Below is mutually exclusive: Either jar or war plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
        </plugin>
    </plugins>
</build>
Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
earcam
  • 6,662
  • 4
  • 37
  • 57
  • I have two options of running these few bundles 1) in embedded Apache Felix witin WAR 2) Witin WAB – Aravind Yarram May 03 '12 at 20:09
  • I've updated my post with the technologies. Have you tried Tycho? – Aravind Yarram May 07 '12 at 14:41
  • Very informative post - the POM content is especially useful, thank you earcam. Note to users: You must comment-out the maven-war-plugin section if running on a JAR, or else the package goal will fail. – KomodoDave Jan 02 '13 at 14:57
  • Hi @KomodoDave, the listing above is supposed to go into the ... section of the parent POM, so you can then just use the plugins by specifying only the group+artifact ID of each plugin in the child POMs. I'll edit the section above to highlight that. Thanks =) – earcam Jan 02 '13 at 15:26
  • Sorry @Pangea, I didn't see your comments - no I haven't tried Tycho. Hope your OSGi migration went well. – earcam Jan 02 '13 at 15:27
  • 1
    @earcam - Perfect, thank you =) I used profiles for each of jar,war instead, since you can specify a different BundleActivator for each type this way. The maven-war-plugin configuration went in the 'war' profile. This is only necessary for us because we're using your code in a partial archetype which may be applied to an existing project of either packaging type. – KomodoDave Jan 04 '13 at 12:07
  • @KomodoDave, Maven's profiles and archetypes are very powerful. I setup some archetypes a while back but we stopped using them due to burden of maintenance - however I hadn't heard of partial archetypes until now - sounds like I should resurrect them and convert to partials. Thanks for enlightening =) – earcam Jan 04 '13 at 15:11
  • @earcam You're very welcome - watch out for the lack of documentation on them, the key thing to remember is that running `archetype:generate` with a partial archetype will _merge_ the pom.xml you've put in the archetype-resources with that of the existing project. The existing project must be in the current directory when you run this `archetype:generate` goal, and be of the same name as the artifactId you specify to the goal with `-DartifactId`. Also be aware there's a new archetype version 2.0 standard to adhere to; the `archetype-metadata.xml` differs significantly from the old standard. – KomodoDave Jan 04 '13 at 17:31
  • @earcam ..and if you get weird errors when running the partial archetype, it's likely due to you specifying POM attributes which can't be merged, e.g. your partial archetype's `archetype-resources/pom.xml` contains tags such as `` or `` which can't be merged with the existing project pom.xml . Besides fundamental attributes like this, almost everything merges fine (plugin configuration and so on). The newer archetype metadata spec is linked in my next comment, and you just set `partial="true"` in the `archetype-descriptor` element to enable. – KomodoDave Jan 04 '13 at 17:33
  • 1
    http://maven.apache.org/archetype/archetype-models/archetype-descriptor/archetype-descriptor.html P.S. The summary of what a partial archetype does is i. merge the `archetype-resources/pom.xml` with that of the existing project, and ii. Add into the existing project any other resources you have in `archetype-resources`. It's very useful for reusable wrapper functionality such as the OSGi-fication we're discussing ehre. – KomodoDave Jan 04 '13 at 17:34
5

Take a look at bndtools, it has excellent support for creating projects that wrap bundles. It provides a lot of insight how JARs are structured and how they depend on other things.

Peter Kriens
  • 15,196
  • 1
  • 37
  • 55
3

Use the maven bundle plugin. It will add the required import and export statements to you manifest based on scanning your code and the dependencies defined in the pom. This will require the least amount of effort to convert.

I also recommend you use M2Eclipse instead of mvn eclipse:eclipse. It will keep your maven config and workspace in sync.

Robin
  • 24,062
  • 5
  • 49
  • 58
  • 1
    It's configurable, you can set it to an external installation - might work with Maven2. But you'll have considerably better mileage with m2e and maven-bundle-plugin – earcam May 03 '12 at 19:07