I've read several articles about the difference between #Service and #Component. Now I understand that #Component is user to annotate an object as an OSGi component and its lifecycle will then be managed by OSGi.
However, what is the need to declare an object as service with #Service is unknown. What happens if you write your business logic in a object that is declared as a component?
I also want to know what does the below statement means:
Components can refer/call (using container injection – #Reference) other services but not components. In other words, a component cannot be injected into another component / service. Only services can be injected into another component.
Question 1:
What is the #Service annotation in Apache Felix?
http://felix.apache.org/documentation/subprojects/apache-felix-maven-scr-plugin/scr-annotations.html#service:
The #Service annotation defines whether and which service interfaces
are provided by the component.
You should understand that this is about the OSGi Service concept, not the Declarative Service (DS) concept described with #Component.
Avoid using annotations from Felix SCR (package org.apache.felix.scr.annotations).
http://felix.apache.org/documentation/subprojects/apache-felix-maven-scr-plugin/scr-annotations.html :
The annotations itself do not support the new features from R6 or
above. It is suggested to use the official OSGi annotations for
Declarative Services instead.
Use #Component from package org.osgi.service.component.annotations, this annotation replaces both #Component and #Service from Felix.
Question 2
What happens if you write your business logic in
a object that is declared as a component?
Happens to work fine.
Question 3
I also want to know what does the below statement means:
Components can refer/call (using container injection – #Reference) other services but not components. In other words, a component cannot be injected into another component / service. Only services can be injected into another component there.
This is how components share functionality in OSGi. They offer their features as OSGi services. But when OSGi injects the object into the reference, you get your component.
BONUS: Read this article: https://medium.com/adobetech/using-the-osgi-declarative-service-in-aem-6-4-21102f649d54
Related
I want to solve the following problem and need advice, what the best solution is.
I have a bundle A in which a service interface X is defined. A bundle B provides a service implementation of X and contributes the implementation to the tool. A and B use Google Guice and Peaberry to configure the setup of the objects.
There are two possibilities I can use to contribute the service implementation:
Using an eclipse extension:
In this solution I can use the GuiceExtensionFactory mechanism of Peaberry to create the service implementation using Guice and therefore can inject stuff needed by the implementation. The disadvantage here is that in the bundle defining the extension point, I need the boilerplate code for the resolution of the extensions because there is to my knowledge no way to get the extensions injected into the class which uses the extensions.
This looks like this:
<extension point="A.service.X">
<xservice
...
class="org.ops4j.peaberry.eclipse.GuiceExtensionFactory:B.XImpl"
.../>
</extension>
<extension
point="org.ops4j.peaberry.eclipse.modules">
<module
class="B.XModule">
</module>
</extension>
but I need the boilerplate code like this:
private List<X> getRegisteredX() {
final List<X> ximpls = new ArrayList<>();
for (final IConfigurationElement e : Platform.getExtensionRegistry().getConfigurationElementsFor( X_EXTENSION_POINT_ID)) {
try {
final Object object = e.createExecutableExtension("class"); //$NON-NLS-1$
if (object instanceof X) {
ximpls.add((X) object);
}
} catch (final CoreException ex) {
// Log
}
}
return ximpls;
}
Using an OSGI service:
My main problem here is to ensure that the service is registered. I want the bundle loaded lazily, so at least an access to one of the classes of the bundle is required. Registering the service programmatically using Peaberry has an issue, because nobody ever asks for a class of the bundle. The solution is to provide the service as a declarative service, but I do not know a way to create the service implementation in a way, that I can use Guice to inject required objects.
So I have some questions:
Is there something I do not know so far that implements the code needed to read the extensions at an extension point generically and allows to inject the extensions to the class using the extensions?
Is there a way to ensure that the service is provided even if it is added using the standard Peaberry mechanism, i.e., the bundle is activated when the service is requested?
Is there a way like the GuiceExtensionFactory for declarative services, so that the creation of the service implementation can be done by the injector of the bundle?
Something that look like:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Ximpl">
<implementation class="some.generic.guiceaware.ServiceFactory:B.Ximpl"/>
<service>
<provide interface="A.X"/>
</service>
</scr:component>
Summarized, I want a service implementation generated by Guice and I want to get the service implementations simply injected into the classes using the service without extensive boilerplate code. Has anybody a solution for that?
Sorry, to ask, but I searched the web for quite a while and so far I did not find a solution.
Thanks and best regards,
Lars
I found a solution, but since I did not find it without a lot of trying out and thinking I thought I share it here. From the options I mentioned in my posting, my solution uses the first one, that is Eclipse extension points and extensions. In order to use Guice in the context of extension points there are two aspects to consider:
Providing an extension that is created by an Guice injector
This is explained very well here: https://code.google.com/p/peaberry/wiki/GuiceExtensionFactory. There is one remark to make from my side. The creation of the extension object is done in an injector inside of the GuiceExtensionFactory, so it is an own context, which needs to be configured by the module given as additional extension to the factory. This can become an issue, if you have other needs that require creating the injector in the bundle on your own.
Defining an extension point so that the extensions are simply injected into the classes which use the extensions.
First thing to do is to define the extension point schema file as normally. It should contain the reference of an interface that has to be implemented by the extensions.
The id of the extension point has to be connected to the interface which is provided by the extensions and which is injected by guice/peaberry. Therefore peaberry provides an annotation to be used to annotate the interface:
import org.ops4j.peaberry.eclipse.ExtensionBean;
#ExtensionBean("injected.extension.point.id")
public interface InjectedInterface {
...
}
On some web pages you also find the information that if the id is equal to the qualified name of the interface, it can be found directly without the annotation but I did not try this out.
In order to enable the injection, you have to do two things to configure the Guice injector creation.
First the EclipseRegistry object of Peaberry has to be set as ServiceRegistry. Second the binding of the extension implementations to a provided service has to be done.
The injector creation has to be done in this way:
import org.osgi.framework.BundleContext;
import com.google.inject.Guice;
import com.google.inject.Injector;
import org.ops4j.peaberry.eclipse.EclipseRegistry;
import static org.ops4j.peaberry.Peaberry.*;
void initializer() {
Injector injector = Guice.createInjector(osgiModule(context, EclipseRegistry.eclipseRegistry()), new Module() {
binder.bind(iterable(InjectedInterface.class)).toProvider(service(InjectedInterface.class).multiple());
});
}
The extension implementations can then simply be injected like this:
private Iterable<InjectedInterface> registeredExtensions;
#Inject
void setSolvers(final Iterable<InjectedInterface> extensions) {
registeredExtensions = extensions;
}
With the described way it is possible to have injected extensions which are implemented by classes using Guice to get dependencies injected.
I did not find a solution to use osgi services so far, but perhaps there is someone who has an idea.
Best regards,
Lars
I am using J2EE with WASLiberty & Apache Wink (REST Impl).
I would need in some cases to have api class to be singleton, however private constructor probably wont work with REST. Has anyone used api to be singleton ? any hints ?
As per Wink doc
The #Scope annotation
According to the JAX-RS specification, by default, provider and resource classes are instantiated once for each JAX-RS application. This instantiation involves the default constructor for the class being called, with the injection of dependencies happening afterwards.
Since the instantiation of your resource class (in your words, API class) will be carried out by injection, I don't think the default ctor visibility will be an issue (In the worst case, make it public)
I just started playing around with OSGi services and have the following situation. I have a project which contains 2 services. Service A requires Service B, so I tried to inject the dependent service using
#Inject
private ServiceB svc;
but the framework wont inject. If I setup the following two methods in Service A
and set these methods as "bind / undbind" in my OSGi componentA.xml the framework calls
these methods and I can use Service B in Service A.
public synchronized void bind(IServiceB service)
{
this.svc = service;
}
public synchronized void unbind(IServiceB service)
{
if (this.svc == service)
{
this.svc = null;
}
}
The question is, why does it not work with #Inject ? Sorry if this is a stupid question, I'm quite new to this whole topic. Many thanks in advance!
It looks like you are using Declarative Services, which does not support field injection or the JSR-330 annotations. Field injection has limited utility in OSGi, where services may be injected or "un-injected" at any time. Method injection is more generally useful because it gives you an opportunity to do something when this happens.
However I do urge you to use the annotations for Declarative Services. This will save you from having to write the component.xml by hand.
I'd like to know what the best practices are for Eclipse 4 dependency injection.
After reading about this subject on the internet, I came up with the following strategy.
requirements
Share the data model of the application (e.g. company, employee, customer, ...) so that framework objects (view parts, handlers, listeners, ...) can access it with as little coupling as possible.
proposed strategy
I've used the lifeCycleURI plugin property to register a handler which is triggered at application startup. Such handler creates an "empty" top-level data model container object and place it into the EclipseContext. It is also discarded when application stops.
All Eclipse framework classes (view parts, handlers) use the classic DI to get such data model object injected.
Button listeners created with the class constructor can't have the data model object injected in them. So I thought they could be created with ContextInjectionFactory.make() to have injection performed. This would couple the class which creates the listener with CIF, but the great advantage is that injection works out of the box.
This is the best solution I've found yet to leverage E4 DI with as little coupling as possible. The weak spot is in my opinion this coupling with CIF. My question would be whether any strategy exist to remove even this coupling, or alternate solutions for the same requirements.
You can create a service class in your project, let's say ModelService.
Add #creatable and #singleton annotations to that class :
#creatable
#singleton
class ModelService{
}
And let DI do its job using following syntax in your parts/handlers/etc ..
#Inject ModelService modelService;
Then you can implement methods in your service like 'createBaseModel()', updateModel() and so on.
This creates a low coupling solution : you can also implement ModelService in a separate plugin and define it as a OSGi service.
for that solution, you can read this Lars Vogel article.
I'm using JBoss AS 7.1 and leveraging Contexts and Dependency Injection. There is no spring involved here.
My question is how can i inject a dependency into a hazelcast MapStore implementation? Might there be a programmatic way? Any help is appreciated.
For instance
public class ClientRepositoryCache implements MapStore<Integer, ClientItem> {
#Inject
ClientRepository repository;
#Override
public ClientItem load(Integer clientNumber) {
return repository.getClientById(clientNumber);
}
}
At the moment Hazelcast supports dependency injection using only Spring. Instead you can use MapStoreFactory which gives ability to create your own MapStore instance.
See a related Hazelcast group post;
MapStore/MapLoader configuration
...
To integrate with Guice, for example, you can supply the name of a singleton MapStoreFactory implementation that is statically injected with enough information to implement newMapStore(String name, Properties properties) with Injector-aware logic.
If you use programmatic configuration, as I do, you can avoid the static injection by passing an already-injected factory to MapStoreConfig.setFactoryImplementation.
-Tim Peierls-
See also MapStoreFactory and MapStoreConfig javadocs.
https://github.com/hazelcast/hazelcast/issues/440
This works very well! Integration with CDI done with a CDI Extension.