Managing OSGi services programatically

ArpitVarshney

MVP

22-04-2020

Hi Team,

 

Can anyone help what would be perfect way to achieve this requirement:

We have number of OSGi services in our project and divided into 2 sets.

Based on a parameter passed during build, we need to enable one set of OSGi services and disable other set.

For Example:

We have OSGi service1, service2, service3, service4.

If param == enableFirstSet ----> then enable service1 & service2

If param == enableSecondSet ----> then enable service3 & service4

 

Also,

I have tried below code in activate method to deactivate individual services  based on param but the problem is their attached OCD(configuration) still available in OSGi configuration tab as those configurations attached at bundle level rather than component level.

 

context.disableComponent((String) properties.get(Constants.SERVICE_PID));

 Any pointer will be good.

Accepted Solutions (1)

Accepted Solutions (1)

Jörg_Hoh

Employee

23-04-2020

Andrew gave a few suggestions how you could achieve it, but I have a more generic question: Why do you want to do this during runtime? Because then you cannot deploy the same artifact(s) on any environment, but you will have specialized builds. Which could make sense if you have multiple production environments. But for every other case (multiple/different development stages) I would definitely use runmodes.

 

And even if you have different PROD environments because you client1, client2 and client3 and they run the same application bundle with some specialities, you still can use runmodes. Just give them the name "client1", "client2" and "client3", and still have all services/components in the same bundle.

 

If this approach doesn't work, you should really think of splitting the functionality in separate bundles and build dedicated deployment packages. Then it is not a decision of the application which services/components to start and stop, but it's a decision at deployment time.

 

There are ways to stop and start services, but these operations are not persisted, unless you switch the value of the service property "enabled" and persist it (see https://osgi.org/specification/osgi.cmpn/7.0.0/service.component.html, search for "enabled"; this is R7 but also works for OSGI R6). But be warned: This is a real hack and from my point of view a sign of bad application design and architecture. I would always try to solve this by runmodes.

 

 

Answers (3)

Answers (3)

Theo_Pendle

MVP

23-04-2020

Hi Arpit,

Using Maven profiles, it is possible to build your bundle using some source .java files and not others (hence deploying one service and not another).

Here is what I came up with, I recorded a short video (<2min) to illustrate how it works: https://youtu.be/Mqq9L6GsEp4 

And here is the relevant XML to be added to your pom.xml file:

    <profiles>
        <profile>
            <id>service-a</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <configuration>
                            <excludes>
                                <exclude>**/core/service/impl/b/**</exclude>
                            </excludes>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>service-b</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <configuration>
                            <excludes>
                                <exclude>**/core/service/impl/a/**</exclude>
                            </excludes>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

Andrew_Khoury

Employee

22-04-2020

One way to do what you want is to make it so an OSGi configuration needs to be available for the component to be enabled (this is called ConfigurationPolicy.REQUIRE on the OSGi Component).  See here, for example:

http://www.computepatterns.com/43/osgi-component-in-aem-that-is-active-only-in-specific-run-mode-say...

 

Then using this, you can leverage runmodes like /apps/myapp/config.qaauthor, /apps/myapp/config.qapublish.  Or you can enable them by removing the config of one component and enabling the config of the other.

 

Also, you might consider thinking about it differently.  Instead of having different OSGi components / services active for different builds, maybe have a logical controller that checks a method on the service interface that returns boolean (true/false) to see if the service is "enabled".

Arun_Patidar

MVP

22-04-2020

Do you have 2 bundles or one?

If 2 bundles are there then in maven apps pom.xml, skip one of them to be packaged based on param.