How to inject osgi service with felix scr annotations - osgi

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.

Related

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.

Accessing BundleContext with Felix dependency manager

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.

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

How to use OSGI service inside Vaadin web application running in Jboss AS 7

I'm new to OSGI and currently trying to use it to create modular web application. Web application itself is created using Vaadin 6.
I following this WIKI article at Vaadin web site: Creating Modular Vaadin application with OSGI
Steps I've did so far:
- created OSGI bundle for module service (simple service which tracks other osgi modules a.k.a. plugins) and deployed it to jboss.
- created vaadin application, just a stub.
OSGI service supposed to be injected to Servlet class, like:
#WebServlet(urlPatterns="/*")
public static class Servlet extends AbstractApplicationServlet {
#Resource(mappedName="vaadin-moduleService")
ModuleService moduleService;
#Override
protected Class<? extends Application> getApplicationClass() {
return ModuleDemoApp.class;
}
#Override
protected Application getNewApplication(HttpServletRequest request) throws ServletException {
return new ModuleDemoApp(moduleService);
}
}
Now the question - how this service can be injected here? Currently I'm just getting NULL pointer, so DI doesn't work. From article referred above:
Note, that the servlet has a moduleService field annotated with the
#Resource annotation. One of the interesting features of GlassFish 3
is that it is possible to inject references to OSGi services into all
container managed Java beans, even though they are not actually
running in the OSGi container themselves. Thus, in this case, GlassFish
will find the module service we define in the previous section and inject it.
According to this Glassfish will do all the magic internally and automatically. Anyone aware of how to get it done using JBoss7?
Unfortunately didn't find any good (for newbie) explanation on how anything running inside of OSGI container can be referenced outside of it... Suppose that converting of the web application itself to OSGI bundle is not required to acomplish what I need. Is this true?
Thanks a lot.
The documentation states that the JavaEE component can get the BundleContext injected as a #Resource. If that works, then you can track your module service through a ServiceTracker.
I saw another example of using Vaadin together with OSGi here.

Resources