Difference between revisions of "How to Create a new OSGi Bundle"

From Opentaps Wiki
Jump to navigationJump to search
Line 57: Line 57:
 
$ git mv modules/notes/api/services/src/main/java/org/opentaps/notes/domain/Note.java modules/notes/domain/src/main/java/org/opentaps/notes/domain/
 
$ git mv modules/notes/api/services/src/main/java/org/opentaps/notes/domain/Note.java modules/notes/domain/src/main/java/org/opentaps/notes/domain/
 
</pre>
 
</pre>
 +
 +
It looks pretty good, doesn't it?  Let's try to build it:
 +
<pre>
 +
$ mvn clean install
 +
...
 +
[INFO] ------------------------------------------------------------------------
 +
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project notes.services.api: Compilation failure: Compilation failure:
 +
[ERROR] /Users/sichen/git/opentaps-2/modules/notes/api/services/src/main/java/org/opentaps/notes/services/GetNoteByIdServiceOutput.java:[20,32] package org.opentaps.notes.domain does not exist
 +
[ERROR] /Users/sichen/git/opentaps-2/modules/notes/api/services/src/main/java/org/opentaps/notes/services/GetNoteByIdServiceOutput.java:[24,12] cannot find symbol
 +
[ERROR] symbol  : class Note
 +
[ERROR] location: class org.opentaps.notes.services.GetNoteByIdServiceOutput
 +
[ERROR] /Users/sichen/git/opentaps-2/modules/notes/api/services/src/main/java/org/opentaps/notes/services/GetNoteByIdServiceOutput.java:[26,24] cannot find symbol
 +
[ERROR] symbol  : class Note
 +
[ERROR] location: class org.opentaps.notes.services.GetNoteByIdServiceOutput
 +
[ERROR] /Users/sichen/git/opentaps-2/modules/notes/api/services/src/main/java/org/opentaps/notes/services/GetNoteByIdServiceOutput.java:[27,11] cannot find symbol
 +
[ERROR] symbol  : class Note
 +
[ERROR] location: class org.opentaps.notes.services.GetNoteByIdServiceOutput
 +
[ERROR] -> [Help 1]
 +
</pre>
 +
 +
Ouch!  What happened?
 +
 +
What happened is that the bundle where we moved <tt>Note.java</tt> was still looking for it!  In fact, if you look at <tt>notes/api/services/pom.xml, you will notice that it is listing <tt>org.opentaps.notes.domain</tt> as one of the packages that it exports:
 +
<pre>
 +
 +
                        <Export-Package>
 +
                            org.opentaps.notes.services,
 +
                            org.opentaps.notes.services.security,
 +
                            org.opentaps.notes.domain
 +
                        </Export-Package>
 +
</pre>
 +
 +
So first I need to remove that, since the package is no longer there. 
 +
 +
Then, I need to add to a dependency from the <tt>notes/api/services</tt> bundle to our new <tt>notes/domain</tt> bundle by modifying the <tt>notes/api/services/pom.xml</tt>:
 +
 +
<pre>
 +
  <dependencies>
 +
...
 +
        <dependency>
 +
            <groupId>${project.groupId}</groupId>
 +
            <artifactId>notes.domain</artifactId>
 +
            <version>${project.version}</version>
 +
            <scope>provided</scope>
 +
        </dependency>
 +
    </dependencies>
 +
</pre>
 +
 +
I also added this to the other bundles which were using <tt>Note.java</tt>.  Since this is a domain class, it was used throughout the application, so there were many bundles which I had to change.  Finally, though, they were all fixed, and I get a different build error message:
 +
<pre>
 +
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:testCompile (default-testCompile) on project tests-run: Compilation failure: Compilation failure:
 +
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[27,32] package org.opentaps.notes.domain does not exist
 +
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[125,12] cannot find symbol
 +
[ERROR] symbol  : class Note
 +
[ERROR] location: class org.opentaps.testsuit.notes.NotesTests
 +
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[80,8] cannot find symbol
 +
[ERROR] symbol  : class Note
 +
[ERROR] location: class org.opentaps.testsuit.notes.NotesTests
 +
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[134,16] cannot find symbol
 +
[ERROR] symbol  : class Note
 +
[ERROR] location: class org.opentaps.testsuit.notes.NotesTests
 +
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[134,46] cannot find symbol
 +
[ERROR] symbol  : class Note
 +
[ERROR] location: class org.opentaps.testsuit.notes.NotesTests
 +
[ERROR] -> [Help 1]
 +
</pre>
 +
 +
This is because in this last bundle <tt>integration-tests/tests-run</tt>, we need to reference the groupId explicitly when we import the dependency to our bundle:
 +
<pre>
 +
        <dependency>
 +
            <groupId>org.opentaps</groupId>
 +
            <artifactId>notes.domain</artifactId>
 +
            <version>${project.version}</version>
 +
            <scope>provided</scope>
 +
        </dependency>
 +
</pre>
 +
 +
Why?  Read its <tt>pom.xml</tt>:
 +
<pre>
 +
    <parent>
 +
        <artifactId>integration-tests</artifactId>
 +
        <groupId>org.opentaps.testsuit</groupId>
 +
        <version>2.0.1-SNAPSHOT</version>
 +
    </parent>
 +
</pre>
 +
 +
It belongs to a different group!

Revision as of 23:34, 24 February 2012

While writing Customizing opentaps 2: an OSGi Tutorial, I realized that one of the Java classes was in the wrong place. Note.java, which is the object representation of a note, is a domain class under the Domain Driven Architecture. Since domain classes represent data, not actions, it shouldn't be part of the services API bundle, so I'm going to move it into a new bundle for a domain class. In the process, I thought this would be a good tutorial on how to create an OSGi bundle.

First, I create a directory for my bundle. Under the opentaps-2/modules/notes, I will add a new directory called domain, parallel to api and impl.

Next, I create a directory within this bundle for my Java files: src/main/java under the opentaps-2/modules/notes/domain directory. This is where the Java source files go. If there were other types of source files, like web.xml for webapp configuration or .properties files for localizations, then I would also need a src/main/resources, but I don't have those right now, so I'm not going to create this.

Next, I need a pom.xml for maven in the domain/ directory. I will borrow from the one for the api bundle and modify it:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <artifactId>notes.domain</artifactId>
    
    <name>Notes domain</name>
    <packaging>bundle</packaging>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>

    <parent>
        <groupId>org.opentaps</groupId>
        <version>2.0.1-SNAPSHOT</version>
        <artifactId>notes</artifactId>
    </parent>
</project>

Let's look at this pom.xml. There are a few things you should notice:

  • The packaging is bundle because we're trying to get a bundle built, whether it's a jar or war file. If we're just using this to manage other bundles, then it would be pom.
  • It does not have its own groupId or version because they are the same as the one for the parent. Putting these tags again would cause an error when you try to build.

We'll also want to add our new bundle to its parent, notes/pom.xml:

    <modules>
        <module>domain</module>
    	<module>api</module>
    	<module>impl</module>
    	<module>rest</module>
        <module>rest_ru</module>
        <module>rest_fr</module>
        <module>eba</module>
    </modules>

Now my notes/domain bundle is set up. I create the directory structure and move my Note.java over:

$ git mv modules/notes/api/services/src/main/java/org/opentaps/notes/domain/Note.java modules/notes/domain/src/main/java/org/opentaps/notes/domain/

It looks pretty good, doesn't it? Let's try to build it:

$ mvn clean install
...
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:compile (default-compile) on project notes.services.api: Compilation failure: Compilation failure:
[ERROR] /Users/sichen/git/opentaps-2/modules/notes/api/services/src/main/java/org/opentaps/notes/services/GetNoteByIdServiceOutput.java:[20,32] package org.opentaps.notes.domain does not exist
[ERROR] /Users/sichen/git/opentaps-2/modules/notes/api/services/src/main/java/org/opentaps/notes/services/GetNoteByIdServiceOutput.java:[24,12] cannot find symbol
[ERROR] symbol  : class Note
[ERROR] location: class org.opentaps.notes.services.GetNoteByIdServiceOutput
[ERROR] /Users/sichen/git/opentaps-2/modules/notes/api/services/src/main/java/org/opentaps/notes/services/GetNoteByIdServiceOutput.java:[26,24] cannot find symbol
[ERROR] symbol  : class Note
[ERROR] location: class org.opentaps.notes.services.GetNoteByIdServiceOutput
[ERROR] /Users/sichen/git/opentaps-2/modules/notes/api/services/src/main/java/org/opentaps/notes/services/GetNoteByIdServiceOutput.java:[27,11] cannot find symbol
[ERROR] symbol  : class Note
[ERROR] location: class org.opentaps.notes.services.GetNoteByIdServiceOutput
[ERROR] -> [Help 1]

Ouch! What happened?

What happened is that the bundle where we moved Note.java was still looking for it! In fact, if you look at notes/api/services/pom.xml, you will notice that it is listing org.opentaps.notes.domain as one of the packages that it exports:


                         <Export-Package>
                             org.opentaps.notes.services,
                             org.opentaps.notes.services.security,
                             org.opentaps.notes.domain
                         </Export-Package>

So first I need to remove that, since the package is no longer there.

Then, I need to add to a dependency from the notes/api/services bundle to our new notes/domain bundle by modifying the notes/api/services/pom.xml:

   <dependencies>
...
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>notes.domain</artifactId>
            <version>${project.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

I also added this to the other bundles which were using Note.java. Since this is a domain class, it was used throughout the application, so there were many bundles which I had to change. Finally, though, they were all fixed, and I get a different build error message:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.2:testCompile (default-testCompile) on project tests-run: Compilation failure: Compilation failure:
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[27,32] package org.opentaps.notes.domain does not exist
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[125,12] cannot find symbol
[ERROR] symbol  : class Note
[ERROR] location: class org.opentaps.testsuit.notes.NotesTests
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[80,8] cannot find symbol
[ERROR] symbol  : class Note
[ERROR] location: class org.opentaps.testsuit.notes.NotesTests
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[134,16] cannot find symbol
[ERROR] symbol  : class Note
[ERROR] location: class org.opentaps.testsuit.notes.NotesTests
[ERROR] /Users/sichen/git/opentaps-2/integration-tests/tests-run/src/test/java/org/opentaps/testsuit/notes/NotesTests.java:[134,46] cannot find symbol
[ERROR] symbol  : class Note
[ERROR] location: class org.opentaps.testsuit.notes.NotesTests
[ERROR] -> [Help 1]

This is because in this last bundle integration-tests/tests-run, we need to reference the groupId explicitly when we import the dependency to our bundle:

        <dependency>
            <groupId>org.opentaps</groupId>
            <artifactId>notes.domain</artifactId>
            <version>${project.version}</version>
            <scope>provided</scope>
        </dependency>

Why? Read its pom.xml:

    <parent>
        <artifactId>integration-tests</artifactId>
        <groupId>org.opentaps.testsuit</groupId>
        <version>2.0.1-SNAPSHOT</version>
    </parent>

It belongs to a different group!