DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

OSGi Services: Automated Discovery and Registration

OSGi's Declarative Services are a powerful feature. This article shows some details on going from annotations to registered services.

Alan Hohn user avatar by
Alan Hohn
·
Nov. 06, 16 · Tutorial
Like (8)
Save
Tweet
Share
8.26K Views

Join the DZone community and get the full member experience.

Join For Free

This article continues a series on declarative services in OSGi. We started with a basic OSGi bundle, then discussed architecting a multi-bundle application. Then we looked closer at declarative services and how to register them. All of this is fully demonstrated in an example application on GitHub.

With the last article, we left off with a service interface, and implementation, and a few ways to tell the service registry about it. However, we didn't cover the mechanics of registration for our last method (SCR using Java annotations) and we didn't cover service lookup. In this article, I'll be tackling the first of those two topics.

SCR Annotations

Our service implementation looks like this:

@Component(immediate = true)
@Service
@Property(name="language", value="fr")
public class FrenchGreeter implements Greeter {

    private static final Logger LOGGER = LoggerFactory.getLogger(FrenchGreeter.class);

    @Override
    public String greet() {
        LOGGER.info("Le 'greeter' en francais!");
        return "Bonjour tout le monde!";
    }
}


Those @Component, @Service, and @Property annotations by themselves don't do anything; there needs to be some code that processes them. In this case, we need code that scans the classpath, finds annotated classes, instantiates them, and registers them in the service registry.

Since I'm using Karaf and therefore Apache Felix, I'm using the Felix version of these annotations. So I'm going to demonstrate the Felix way of using them. This involves processing the annotations at build time and generating an XML file that gets packed into the JAR. This XML file is then specified in the META-INF/MANIFEST.MF file so the OSGi container knows to process it. (It's worth noting that there is a vendor-neutral set of annotations) that can also be used; the process is very similar. Under the covers, the bnd tool from Peter Kreeft is ultimately doing a large part of the work.)

To process the annotations at build time, we use Felix's maven-scr-plugin. This plugin provides a goal to generate the XML descriptor files from the annotations.

The plugin declaration is shown below. For those looking at the source code in GitHub, note that this is specified in the parent POM; it doesn't hurt anything to apply it to modules where the annotations aren't used, and specifying it in the parent reduces duplication.

    <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-scr-plugin</artifactId>
        <version>${maven.scr.version}</version>
        <executions>
            <execution>
                <id>generate-scr-scrdescriptor</id>
                <goals>
                    <goal>scr</goal>
                </goals>
                <configuration>
                    <outputDirectory>target/classes</outputDirectory>
                </configuration>
            </execution>
        </executions>
    </plugin>


With this particular bit of magic applied, when our JAR is generated we get two special things. First, we get this line in META-INF/MANIFEST.MF:

Service-Component: OSGI-INF/org.anvard.karaf.greeter.french.FrenchGreeter.xml


Second, we get the actual XML file:

<?xml version="1.0" encoding="UTF-8"?>
<components xmlns:scr="http://www.osgi.org/xmlns/scr/v1.0.0">
    <scr:component immediate="true" name="org.anvard.karaf.greeter.french.FrenchGreeter">
        <implementation class="org.anvard.karaf.greeter.french.FrenchGreeter"/>
        <service servicefactory="false">
            <provide interface="org.anvard.karaf.greeter.api.Greeter"/>
        </service>
        <property name="language" value="fr"/>
        <property name="service.pid" value="org.anvard.karaf.greeter.french.FrenchGreeter"/>
    </scr:component>
</components>


There's nothing special about this file. We could have written it ourselves and used the maven-bundle-plugin to add the Service-Component information to the manifest. But this is obviously much more verbose than Java annotations. It's also worth mentioning that the reason I showed Blueprint XML in the previous article is because Blueprint XML does the same thing less verbosely, and is capable of doing many other useful things, as I hope to show in a future article.

Wrapping Up

We've almost described every piece of our OSGi declarative services example. The one thing that's missing is to perform the service lookup. I want to save that for another article for two reasons. First, I want to discuss finding multiple service instances and choosing between them based on properties. Second, I want to show both programmatic lookup and service lookup using Blueprint XML. Across both of these, we need to consider the fact that in OSGi, bundles can come and go dynamically, and we need to deal with the fact that the available services could change at any time.

Discovery (law)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • DevOps Roadmap for 2022
  • The Top 3 Challenges Facing Engineering Leaders Today—And How to Overcome Them
  • Top 5 Java REST API Frameworks
  • Promises, Thenables, and Lazy-Evaluation: What, Why, How

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: