Accessing BundleContext with Felix dependency manager - osgi

I am using Apache Felix dependency manager in my project. In the service activation method
#org.apache.felix.dm.annotation.api.Start
public void activate() {
// Need BundleContext here
}
I need an access to BundleContext or Bundle. How can I achieve this?

You can make a volatile BundleContext field in your class and the dependency manager will inject it.

Related

Is there some way to get access to Spring bean from Spock extension?

There is an example what I want to do.
The service client is a Spring bean, which is retrieving from external configuration class and should be called from Spock extension.
class ServiceCleintExtension implements IGlobalExtension {
#Autowired
ServiceCLient client
#Override
void start() {
client.execute()
}
...
}
UPD:
I've found a solution by using Spring TestExecutionListener and custom static "container" for SpecInfo/FeatureInfo.
No that is not possible, IGlobalExtension are initialized and manged by Spock. Furthermore, they are singletons which doesn't mesh well with multiple possible Spring contexts.
If you just want to call a method on an injected bean during setup, then I'd suggest to use an annotation based extension. Look at the builtin AutoCleanup extension for reference.

How do I call OSGI service from outside OSGI?

I am considering writing the OSGI bundle and will expose this as a OSGI service. Now, I wanted to call this OSGI service from another java module,assuming both OSGI bundle and java module running in same JVM.
Is that possible to call OSGI exposed service from outside OSGI ?
Thanks in advance!
BundleContext is required to obtain a ServiceReference which is required to get a Service.
Assuming that the MyService is in your classpath and that there is only one implementing service in the OSGi container:
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
[...]
BundleContext bundleContext = FrameworkUtil.getBundle(MyService.class).getBundleContext();
ServiceReference<MyService> serviceReference = bundleContext.getServiceReference(MyService.class, null);
try {
MyService myService = bundleContext.getService(serviceReference);
// do something with myService
} finaly {
bundleContext.ungetService(serviceReference);
}
Variations
The MyService is not available in your classpath. That is not a problem as you can use any class which is deployed to the OSGi container for the FrameworkUtil.getBundle() method and you can pass a String (FQCN) to the BundleContext#getServiceReference() method.
There are multiple implementations of the MyService. Use an LDAP filter for the second parameter of the BundleContext#getServiceReference() or call the BundleContext#getServiceReferences() method which will return an array or use the same code and rely on the ServiceRanking.

Can Blueprint beans have #Reference services auto injected?

Can instances created by the Blueprint <bean> tag be auto injected with service references specified using the OSGi Declarative Services mechanism?
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
#Component(service={})
public class DatabaseThing{
#Reference
public void setDataSource(DataSource ds){
...
}
If I instantiate via immediate=true in the #Component then my DataSource OSGi service is injected. If I create the instance via blueprint <bean class="DatabaseThing"> then no auto-injection occurs.
I've had a look at the Aries source, and it seems that the service injection is specific to org.apache.aries.blueprint.container.ServiceRecipe and isn't part of ...BeanRecipe which is used for <bean> style instantiation.
That does not work. The DS annotations are processed by bnd and result in a DS xml file that will then be evaluated by felix scr at runtime. In this case the full lifecycle of the object is controller by scr.
If you additionally declare a blueprint bean for the same class then it will be a separate instance. Blueprint can the inject services and beans into this instance but it is completely disconnected from DS.
If your main concern is to use annoations for blueprint injections then I recommend the blueprint-maven-plugin. It allows to use CDI and Java EE annotations in your code. These are translated to a blueprint.xml at build time. So the result is similar to DS but powered by blueprint.

How to inject osgi service with felix scr annotations

I have a osgi bundle in felix contanier, that exports service
#Component(label= "App Service",
description = "App Service",
immediate = true, enabled = true, metatype=true)
#Service(AppServiceImpl.class)
public class AppServiceImpl implements AppService {
}
in web console I see that service starts normally.
Then I want to inject it with #Reference felix scr annotation in other bundle. I understand that there should be some injector, but could not find it.
Are you running the Felix SCR bundle? It is the "injector" as it processes the XML generated from these annotations by the tools that assembled your bundles.
If you use maven, make sure you have the following instruction in your pom.xml: <_dsannotations>*</_dsannotations>
SCR annotations will not work without that.

How to expose the spring couchbase template as OSGI service

Had one more question regarding the Spring-data-couchbase and OSGI.
I want to have different persistence bundles based on the functionality but I would like to have a common bundle while provides me the connection to couchbase.
If I want to scan for the repositories from a different bundle, I have to pass the template-ref object to it.
<couchbase:repositories base-package="xyz.abc.model"
couchbase-template-ref="cb-template-first">
</couchbase:repositories>
The template is created in the way as shown below as per the examples
<couchbase:template id="cb-template-first"
client-ref="cb-first" />
Basically, I wanted to know is there a way to expose the template as an OSGI Service, so that this service can be referenced in my other bundle.
If you use just "OSGi" as mentioned in your comment, you have a bundle activator class which initializes your context.
In this case your activator would look like this:
public class Activator implements BundleActivator
{
#Override
public void start( BundleContext context ) throws Exception
{
// start spring application context
// template-interface = application context get bean
context.registerService( template-interface.class.getName(), template-interface, null );
}
}
But if you want to build an OSGi application based on spring i would recommend to use gemini blueprint to remove boilerplate code. Gemini Blueprint is an extensions which scans all started bundles for context-files inside of META-INF/spring and starts them automatically. Due to namespace-support of gemini blueprint, you can publish or fetch a service within your context:
<osgi:service id="simpleServiceOsgi" ref="simpleService" interface="org.xyz.MyService" />
<osgi:reference id="messageService" interface="com.xyz.MessageService"/>

Resources