How to use org.apache.felix.scr annotations for a bundle from scratch?

Kjellski picture Kjellski · Sep 28, 2012 · Viewed 8.7k times · Source

I've started developing a bundle for apache felix and did so with the ops4j pax plugin.

I've created the project structure with pax-create-project and in there did the normal pax-create-bundle. Then you get the initial project structure for building the whole thing with maven. The important part here is, that your bundle has it's own pom (bundlename/pom.xml) and bnd file (bundlename/osgi.bnd) but the configuration for maven-bundle-plugin is already provided under poms/compiled/pom.xml. The bundle metadata is configured under poms/compiled/pom.xml but the standard activator is configured under the above mentioned osgi.bnd file. The default in the bnd file is Bundle-Activator: ${bundle.namespace}.internal.ExampleActivator.

Now I wanted to start using annotations from org.apache.felix.scr so I included this in the bundles own pom under dependencies:

<dependency>
  <groupId>org.apache.felix</groupId>
  <artifactId>org.apache.felix.scr</artifactId>
  <version>1.6.0</version>
</dependency>

And I created my interface for the service:

package namespace;

public interface Sample {
  void sayHello();
}

As well as the implementation with the annotations from org.apache.felix.scr:

package namespace.internal;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import namespace.Sample;

@Component
@Service
public class SampleImpl implements Sample{

  @Activate
  void start(){
    System.out.println("Started SampleImpl.");
  }

  @Deactivate
  void stop(){
    System.out.println("Stopped SampleImpl.");
  }

  @Override
  public void sayHello() {
    System.out.println("Hello!");
  }
}

What do I need to place in the osgi.bnd file in order to start the components? I had to remove the default entry mentioned above because I`m not using the BundleActivator any more.

Now here is the question: What do I need to do to any of the above mentioned files in order to let the mvn clean install pax:provision start up a felix environment that starts my bundle and let me see any of the printouts? I have already looked at the log output of the Apache Log Service which I'm starting too and it just tells me:

2012.09.28 16:52:44 INFO - Bundle: namespace - BundleEvent STARTED
2012.09.28 16:52:44 INFO - Bundle: namespace - BundleEvent RESOLVED

Any hints are very well appreciated. Or links, I've searched for more then hours to find a complete guide to use the maven plugins for scr and bundle together.

Greetings, Kjellski

Answer

Kjellski picture Kjellski · Sep 30, 2012

This is a modification of my coderwall writeup on this topic: http://coderwall.com/p/q39uxq

First configure the general compilation configuration of the submodules from poms/compiled/pom.xml. Add the plugin right where the maven-bundle-plugin already is:

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-scr-plugin</artifactId>
    <version><timeofwriting:1.8.0></version>
    <executions>
        <execution>
            <id>generate-scr-scrdescriptor</id>
            <goals>
                <goal>scr</goal>
            </goals>
        </execution>
    </executions>
</plugin>

In the same file, under poms/compiled/pom.xml, look at the instructions for maven-bundle-plugin and add right under the <_include> statement:

<Service-Component>
    OSGI-INF/serviceComponents.xml
</Service-Component>

Now depend on the annotations in the subprojects in order to use them:

<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>org.apache.felix.scr</artifactId>
    <version><timeofwriting:1.6.0></version>
</dependency>
<dependency>
    <groupId>org.apache.felix</groupId>
    <artifactId>
        org.apache.felix.scr.annotations
    </artifactId>
    <version><timeofwriting:1.7.0></version>
</dependency>

Now define your components with annotations @Component and @Service. When you want none to be included, like in any api bundle, just insert "Service-Component: *" in the osgi.bnd file. This will cause the bundle plugin to stop complaining about the missing OSGI.INF for the project that doesn't contain any.

Hope this helps somebody ;)

Cheers, Kjellski