So let's start by describing the component in iPOJO terms. The task consists of the addition of the meta.xml
descriptor under src/main/ipojo
of the bookshelf-inventory-impl-mock
project and the modification of the POM to configure the maven-ipojo-plugin
.
The modification of the POM is usually the step that's forgotten. So let's get that out of the way first.
In our case, as we're moving the component from using a bundle activator to declaring itself using iPOJO, we'll need to do two things:
Edit the pom.xml
file and go to the build plugins section. In the maven-bundle-plugin
configuration, comment out (or remove) the Bundle-Activator
instruction. Also, the Private-Package
instruction is no longer needed, so it will also be commented out:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.1.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Category>sample</Bundle-Category>
<Bundle-SymbolicName>${artifactId}</Bundle-SymbolicName>
<Export-Package>
com.packtpub.felix.bookshelf.inventory.impl.mock
</Export-Package>
<!-- <Bundle-Activator>
com.packtpub.felix.bookshelf.inventory.impl.mock.activator.- BookInventoryMockImplActivator
</Bundle-Activator>
<Private-Package>
com.packtpub.felix.bookshelf.inventory.impl.mock.activator
</Private-Package> -->
</instructions>
<!-- ... -->
</plugin>
You may choose to also delete the BookInventoryMockImplActivator
class, for completeness.
Next, we hook the maven-ipojo-plugin
. Do not forget to include the ipojo-bundle
goal in its execution goals.
<plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-ipojo-plugin</artifactId> <version>1.4.2</version> <executions> <execution> <goals> <goal>ipojo-bundle</goal> </goals>
We will also specify an alternate metadata file location:
<configuration> <metadata>src/main/ipojo/meta.xml</metadata> </configuration> </execution> </executions> </plugin>
Also, update the project version to 1.9.0
and that's it for the POM. Let's write the metafile now.
Edit the file src/main/ipojo/meta.xml:
We will go through the parts of the descriptor while explaining them:
<ipojo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/CURRENT/core.xsd" xmlns="org.apache.felix.ipojo">
First, we start by declaring the component. The classname
designates the name of the component
class and points the iPOJO plugin to it for inspection. It retrieves the interface that it will use to register the service.
<component classname="com.packtpub.felix.bookshelf.inventory.impl.mock.BookInventoryMockImpl" name="BookInventoryMockImpl">
The name is arbitrary really; it is used to refer to this component. If it's not set, it defaults to the class name.
This component provides a service; the<provides />
element tags it as so.
<provides /> </component>
As we saw earlier, declaring a component is not enough to make iPOJO instantiate it. The instance declaration below is also necessary:
<instance component="BookInventoryMockImpl" name="bookshelf.inventory.impl.mock" /> </ipojo>
The inventory implementation does not require any service injection, so it's enough to replace its activator with the above iPOJO XML declaration. Let's give it a try.
Rebuild and deploy the bundle to the releases repository and update it in Felix. It should now be at version 1.9.0
.
If everything went well, the update should event-less, nothing happens differently in appearance. Test the service to ensure it's working correctly.
Notice that we've modified the inventory implementation bundle, but not the bookshelf service. It still looks up its dependency through the bundle context service locator. Moving one component to iPOJO does not force you to move the others.
Also note that this modification was released with a different version, but we did not need to update the bookshelf-service
dependencies. The service depends on the inventory API, not its implementation. This is one of the gains of having decoupled the API bundle from the implementation bundle(s).
Let's take a closer look at what happened in each of the steps. We declared the component and an instance of it in the iPOJO meta.xml
file and configured the ipojo
plugin to attach its ipojo-bundle
goal to the build lifecycle.
During the build cycle, the iPOJO Maven plugin picked up the metadata file and kicked off the manipulation. The plugin manipulates the bundle, based on the metadata file:
[INFO] [ipojo:ipojo-bundle {execution: default}]
[INFO] Start bundle manipulation
[INFO] Metadata file : C:projectsfelixbooksources- com.packtpub.felix.bookshelf-inventory-impl-mock- srcmainipojometa.xml
[INFO] Input Bundle File : C:projectsfelixbooksources com.packtpub.felix.bookshelf-inventory-impl-mock targetcom.packtpub.felix.bookshelf-inventory-impl-mock-1.9.0.jar
[INFO] Bundle manipulation - SUCCESS
This is a good part to check when building, looking for any warnings or errors.
Take a look at the changes it made: open the bundle archive (or unzip it somewhere) and inspect the file META-INF/MANIFEST.MF
. The header iPOJO-Components
was added to it (replacing the Bundle-Activator
header, which we have omitted from the plugin configuration).
We don't need to go through it here, but if you inspect it, you'll find that its value is a compilation of the description we've given in the XML file and some additional information that iPOJO extracted from the component class, encoded in a Lisp-like format.
3.12.162.37