Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

Felix and OSGi in Practice

Posted on April 23, 2010 By Luis Fernandez

What if your Java app could load new code while it keeps breathing?

That is the daily promise of Apache Felix and OSGi. We keep chasing modular code, faster deploys, and fewer production facepalms. Sun is now Oracle, app servers feel heavy, and the cloud buzz is loud. In the middle of that noise, OSGi gives a calm idea that works in practice. Split your app into bundles, wire them through the service registry, and swap pieces without bringing the house down. Felix is a lean runtime that makes this concrete, with a simple console and a set of well shaped tools you can explain to your team in one coffee.

Felix keeps things small and honest.

Eclipse Equinox is great and ships in a lot of places, and Knopflerfish has fans too. Felix sits in a sweet spot: small download, friendly shell, very readable code, and a lively Apache vibe. If you want to sprinkle OSGi into an existing app or ship a headless service, Felix feels natural. You can start it from plain Java, embed it inside your app, or run it as its own process. The goal is simple: build modules that hide their guts, expose clear services, and stop fighting classloader weirdness in the dark.

You get a runtime you can reason about.

Why Felix for OSGi today

We all want faster cycles. With OSGi on Felix, you can update one feature by pushing one bundle. No giant ear, no full restart. The service registry encourages decoupling by default. You code against an interface, register an implementation as a service, and find it at runtime with zero ceremony. Your web features, job schedulers, cache adapters, even payment connectors can live as separate bundles with their own versions. The pay off is not just reloads. It is how your code reads after six months.

It is modularity you can touch.

From zero to a running Felix

Download Felix from the Apache site, unzip it, and launch the main class. No magic. If you do not want the jar switch on the command line, call the main class directly. You will land in a console that lets you list bundles, install new ones, start and stop them, and peek into wiring. The first impression matters, and this one says simple and focused.

# Start Felix by class name to avoid jar flags
java -cp bin/felix.jar org.apache.felix.main.Main

# In the shell try
lb
help

You now have a living module system in your terminal.

Your first bundle service

Let us write a tiny service and register it. Keep the public surface small. Put the interface in one bundle and the implementation in another. Yes, two jars, and that is the point. The interface bundle becomes a stable contract while the impl bundle can move fast.

// bundle: hello.api
package com.example.hello.api;

public interface HelloService {
    String greet(String name);
}

Now the implementation bundle with a BundleActivator that registers the service.

// bundle: hello.impl
package com.example.hello.impl;

import com.example.hello.api.HelloService;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

    private HelloService service;

    @Override
    public void start(BundleContext context) {
        service = new HelloService() {
            public String greet(String name) {
                return "Hi " + name + " from Felix";
            }
        };
        context.registerService(HelloService.class.getName(), service, null);
        System.out.println("HelloService registered");
    }

    @Override
    public void stop(BundleContext context) {
        System.out.println("HelloService stopped");
    }
}

Build both jars, make sure the impl imports the api package, drop them into the Felix load directory or install them from the console, and start them. You can now look up the service from another bundle and call it. No reflection circus. Just a registry and a contract.

Declarative Services that feel natural

Writing an activator is fine for learning. For real apps, Declarative Services keeps your code clean. With Felix SCR you can use annotations and skip the XML dance. Mark your class as a component and a service, add references for what you consume, and let the runtime manage lifecycle.

// bundle: hello.impl.ds
package com.example.hello.impl;

import com.example.hello.api.HelloService;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;

@Component(immediate = true)
@Service(value = HelloService.class)
public class HelloServiceImpl implements HelloService {
    public String greet(String name) {
        return "Hello " + name + " with DS";
    }
}

With DS you get activation and deactivation hooks when needed, and services appear only when their dependencies are present. Your code reads like plain Java and the runtime does the wiring.

Working the Felix console

The shell is where Felix shines in day to day work. Install a built jar from a file path or a URL. Start it. Stop it. Update it. List all bundles and see states. The command names are short on purpose. Pair this with a file watcher that calls update on change and you get quick feedback without rebuilding the world.

# List bundles
lb

# Install from a local path
install file:hello.api.jar
install file:hello.impl.jar

# Start by bundle id
start 7
start 8

# Update and restart in place
update 8
stop 8
start 8

Small moves add up to fast loops.

Class loading gotchas and versioning

OSGi gives you strong boundaries, and that also means you must be clear with what you export and import. Keep your exported packages stable and version them. Keep your imports as ranges. Watch out for splitting a package across bundles. That is a trap. Place each public package in one bundle, version it, and describe a sensible range in the consumers. Also avoid static singletons that reach across bundles. Use services for that. Services are the friendly way to share. Static state is the gremlin that breaks reloads.

Design for change and your runtime will thank you.

Build and packaging tips

You can build bundles with bnd, with Ant tasks, or with Maven. If you go Maven, look for the maven bundle plugin and the Felix SCR plugin. They add the right headers and generate DS metadata from annotations. Pick one path and keep it boring. The trick is to make bundle metadata part of the code review, not a mystery file nobody touches. Agree on version rules for packages and services and stick to them. Your future self will be grateful.

Automate the boring parts, keep the smart parts human.

When you might pick Equinox instead

If you are deep into the Eclipse world or need tight ties with PDE and buddies, Equinox is a strong choice. Tooling around Eclipse RCP is mature and plenty of teams ship desktop apps that way. For server and headless work where you want a tiny core and you plan to script your own path, Felix feels lighter. Both follow the same OSGi specs, so you can switch if you keep your code honest with standard APIs.

Choose the runtime that fits your team, not your neighbor.

Small bundles and clear services beat giant jars every single time.

Software Architecture Software Engineering

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes