Managing OSGi services programatically | Community
Skip to main content
ArpitVarshney
Community Advisor
Community Advisor
April 22, 2020
Solved

Managing OSGi services programatically

  • April 22, 2020
  • 4 replies
  • 12710 views

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.

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by joerghoh

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.

 

 

4 replies

arunpatidar
Community Advisor
Community Advisor
April 22, 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.

Arun Patidar
ArpitVarshney
Community Advisor
Community Advisor
April 22, 2020

@arunpatidar  Only single bundles is there where all the OSGi services lies.

akhoury
Adobe Employee
Adobe Employee
April 22, 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-publish/

 

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".

ArpitVarshney
Community Advisor
Community Advisor
April 23, 2020

Hi @akhoury , Thanks for your suggestions.

But I have few doubts:

  1. The services needs to be controlled based on the build param not the run modes. If I'm using ConfigurationPolicy as require then how we can dynamically create and remove corresponding OSGi service configuration file from my Java code or controller based on param?
  2. Could you please elaborate your second point: "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"."
joerghoh
Adobe Employee
joerghohAdobe EmployeeAccepted solution
Adobe Employee
April 23, 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.

 

 

akhoury
Adobe Employee
Adobe Employee
April 23, 2020

I agree with @joerghoh, the concept of having different builds removing / adding configs could be prone to issues and isn't the recommended approach. Leveraging runmodes is good for environment specific stuff and if you have site / path specific functionality then maybe you could drive that via Sling Context Aware configs:
https://sling.apache.org/documentation/bundles/context-aware-configuration/context-aware-configuration.html

 

Otherwise, in general, adding / removing OSGi components per build would generally be discouraged.  OSGi is designed to be dynamic, I can't see a reason why you would need to enable / disable the components per different build.

Can you elaborate on your use case?

Theo_Pendle
April 23, 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>