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.
Solved! Go to Solution.
Views
Replies
Total Likes
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.
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.
Views
Replies
Total Likes
@arunpatidar Only single bundles is there where all the OSGi services lies.
Views
Replies
Total Likes
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:
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".
Hi @Andrew_Khoury , Thanks for your suggestions.
But I have few doubts:
Views
Replies
Total Likes
If runmodes aren't preferrable as this is build specific and not environment specific then you could dynamically set the OSGi configurations via your code:
http://www.nateyolles.com/blog/2015/10/updating-osgi-configurations-in-aem-and-sling
You might consider to have some separate projects in your maven builds that build different package for deploy per build that have different OSGi configs. There are many ways to achieve what you want, it is just to decide how to implement it.
https://maven.apache.org/plugins/maven-resources-plugin/examples/copy-resources.html
As for clarification to my other 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".
What I meant there is to refactor your code. Instead of using different OSGi services for different builds then programmatically *enable* or *disable* the functionality via boolean flag. Or use less services and run the correct functionality per the build. You might look at sling feature flags feature https://sling.apache.org/documentation/the-sling-engine/featureflags.html
Views
Replies
Total Likes
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.
I agree with @Jörg_Hoh, 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-configurati...
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?
Views
Replies
Total Likes
Hi @Jörg_Hoh @Andrew_Khoury @Theo_Pendle Thanks you all for these valuable suggestions.
Sorry, I wasn't much clear with my use case earlier.
Let me explain you my use case. Actually I am working on a aem plug-in and it supports two functionalities and they share some common code base and few OSGi services separately for each functionality. The goal is to have 3 artifacts with all three possibilities.(first, second and both) And we don't want our customers to see other OSGi Configuration if we have build the artifact for different functionality to avoid confusion. So instead of removing the aem services, I have removed their specific OSGI-INF during build time based on build parameter passed by creating maven profile and maven shade plugin.
Does that make sense?
Regards,
Arpit Varshney
Views
Replies
Total Likes
Views
Replies
Total Likes
Views
Replies
Total Likes
Views
Replies
Total Likes
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>
Views
Likes
Replies
Views
Likes
Replies
Views
Likes
Replies