In my current application i want to create and configure osgi services at runtime through a user interface. I've looked into the OSGi Metatype specification but it only supports simple type attributes.
So my questions are: Is there a good reason why there is no support for attribute types such as other osgi services and does anyone know about an already existing project that does something like this?
UPDATE
To further clarify my question:
What i want to do is to create and configure new services as needed by the user of the software. This should even work if new service interfaces are added to the system.
Lets assume i have a service interface for sending notifications
public interface NotificationService {
void notify(Notification n);
}
and an implementation for sending notifications to e.g. Twitter. Through the Metatype specification i could encode the information that the twitter service needs a username and password. This allows me to dynamically create a UI at runtime for creating new twitter notification services.
This works with simple datatypes, but the Metatype spec does not handle dependencies to other services. E.g. lets say a Notification has file attachment and therefore the Twitter service needs a FileUpload service to store files.
You can always inject new services using BundleContext#registerService(), however the service at that time must have been initialized and ready to run. You may find useful the new Blueprint service of the OSGi 4.2 specification - or even Dynamic Services, which is older but more widespread.
In the end, it depends on what you want to do. When you say "create" and "configure" osgi services at runtime, what do you mean?
So in your example, you're basically saying that an implementation of a service can be configured and that that configuration might state that the implementation requires another service. Basically, you're looking for a system that allows you to declare the dependencies of an implementation in code, instead of in a static XML file (as Declarative Services and most others do).
A solution to your problem is to use the Apache Felix Dependency Manager. It has a declarative Java API that allows you to add and remove dependencies at runtime. Some basic examples to get you started can be found here: http://felix.apache.org/site/apache-felix-dependency-manager-getting-started.html I would advise you to build a 3.0.0-SNAPSHOT from source, as this is the latest and greatest, fairly stable by now.
If it helps, I could provide actual sample code for the example you describe above. Let me know.
Related
I'd like to get CXF, which implements JAX-RS, up and running in OSGI (specifically, Apache Karaf running Apache Felix).
Using this project: cxf-osgi-activator as an example, I see that the engineer made a design decision to split up the jetty Karaf feature from the jax-rs Karaf feature. Is there a dependency between the two at runtime? Does the jax-rs feature use some trick (from the environment: OSGI HTTP Service, for example) to get itself listening for inbound connections, or is that still needed? Maybe my question can be answered with an explanation of line 250 of the RestDeployer.java file. Where is it pulling its Server from exactly? Does it always get one, or does it have a dependency on the jetty Karaf feature?
I had a look at the tests, which seem to use iPojo or Declarative Services (hard for me to tell the difference!) to cut down on boiler plate code, but at the expense of understanding (because it requires more in-depth knowledge on the subject than I have at the moment it would seem.)
The official CXF documentation is less than desirable on this subject.
My understanding is that it boils down to having:
a web resource file annotated with JAX-RS annotations to map inbound calls to local functions
CXF runtime (some registration service that manages the lifecycle from reception of a call to return of serialized information)
a server (Java Servlet or effectively an abstraction thereof that spawns threads for a given port) Purpose of cxf-rt-transports-http-jetty
How does this all play together in OSGI? I should also mention that am most familiar with Gradle, and the Maven pom.xml files likely contain things that I do not recognize.
I do not like the accepted answer to CXF web services with OSGI and Karaf, because it is specific to Blueprint, which I do not want to use because of its reliance on XML. I am looking for a technical answer here that explains the relationship between CXF and OSGI (like the OSGI HTTP Service).
Related:
Apache CXF/JAX-RS, Felix and Jetty
Purpose of cxf-rt-transports-http-jetty
Firstly, a tiny recap about OSGi :
OSGi is a specification that needs to be implemented
Felix/Equinox are the two implementations found in karaf (see your etc/config.properties, with the property karaf.framework to check the one you use, you can change it !)
Karaf is an administration tool that will use Felix/Equinox behind each command you make. Often, those commands are proxied to the corresponding behaviour defined by OSGi to the Felix/Equinox implementation.
So, the solution you linked with Blueprint is still true no matter your context. However, if you don't like Blueprint, you can either check Declarative Services where each "bean" you would have defined in a "spring/blueprint" world would become #Service/#Reference (more pure to OSGi original way of thinking) or use OSGI CDI Integration which will be way more intuitive if you are used to the more classic #Named/#Inject way of thinking inside a bundle.
But in the end, it's exactly the same principles : you want to have a Server running registering itself to the CXF Bus (which normally you shouldn't declare in your bundle, you can use the default one) and your Service registering itself in Server.
I want to develop a service that exposes a rest API to upload plugins and the plugins are locally executable, i.e. other classes from the server use them.
The plugins also:
The plugin should be a jar file that is submitted through the REST API and once is validated, is then made available through another API method to see the metadata and to execute.
Are not too complex (they should all contain at least a a class that extends of an abstract class or an interface implementation of an interface, the service) but could have their own dependencies.
The API allows to validate that the plugin is compliant with the service and that it declares some additional information on an XML or JSON file contained on the JAR.
Have some metadata that has to be exposed through the API (Version, who made it, is it usable, what data can it be handled) in Json form.
All implement an algorithm to perform some data crunch so they all have something like an execute() method. The result of executing this method is handled to another class, so is not totally important to expose it on the API.
Must be able to be uploaded and executed by the other server classes in runtime, so no restart is possible
The thing is that I am not sure where to start, since I had already developed some of the basic API on Spring-boot since it had all the things I needed to easily develop a REST API but the more I read about how to dynamically load modules (plugins) the more I see that Spring does not support this ind of thing and I am not sure a class loader or Service loader would work in that context.
I found out about OSGi framework but I honestly do not know it changing the whole technology stack will help me so I want to make sure it is the right answer, and if yes, then find some resources that point me in the right direction, e.g. some tutorial that implements something similar.
Thank you for any advice.
Checkout OSGi enRoute. It includes a model to developing RESTful services: http://enroute.osgi.org/services/osgi.enroute.rest.api.html.
OSGi sounds like the best match to what you try to do.
You can install everything as a bundle including your main application. Nowadays this is much less work than some years before but still not to be underestimated.
The other option is to start an embedded OSGi framework where you just install your plugins. This is less work but you need to know exactly how it works.
So for both cases I suggest to get help from an external OSGi expert as it speeds up the transition a lot and avoids many wrong paths you will choose as a beginner.
I am currently trying to find a way to "filter" bundles in OSGI, while installing them. I use Karaf as an OSGI implementation and iPOJO for service resolution.
Is there any way I can ensure, that only services provided by iPOJO are allowed to be installed in OSGI?
I already searched the web for methods to see wether the specific service imports OSGI stuff(like BundleContext etc.), but that doesnt seem to be working easily.
Thank you :)
Probably no, and I don't recommend doing it. The way how a service is published is better to consider as an implementation-specific detail. If you want to search for the services provided by your library, then it is better to add a custom key-value property to your services (don't know how to do that with iPOJO) and use that key in your LDAP filter.
edit: the provided services' only externally visible characteristics are the classname and the key-value service properties, so if you can't find any reasonable information there about iPOJO, then you don't have too much chance
I got a solution to my problem... I kind of did it like erosb was suggesting.
Every IPOJO service reference owns the property "name", so i just created a LDAP-filter for the #Bind method, which accepts all values for the name-property(filter = "(instance.name=*).
Services, that were not created with iPOJO, don't have that field, so in that way i can filter any iPOJO-service.
Thanks alot
:)
Being someone who is allergic to dependencies, when would I use something like OSGi instead of the built in java 6 http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html (I want to let plugin jars just be dropped in).
(FYI this is in a scala app, open to any suggestions, ServiceLoader is pretty damn close to what I want).
If ServiceLoader mostly fits your needs, that says that you're looking for service discovery via the presence of files on the class path. That's only a small part of what OSGi provides.
OSGi will let you dynamically install bundles, advertise services, revoke advertisements, and uninstall bundles all while the application is running. Furthermore, as a consumer of services, you can look them up eagerly -- with filtering predicate queries -- and detect when offered service providers come and go. These bundles need not lie on the class path, and they can be provided in various forms; Jar files and "exploded directories" are the two I recall.
By contrast, ServiceLoader does just one thing: it exposes discoverable factories. Usually you'll create a factory-style interface that takes some argument to decide whether that provider can offer the appropriate service, such as mapping a given character set name to a CharsetDecoder. There's no formalized protocol for acquiring and releasing a service from such a provider. OSGi does formalize the binding and unbinding of consumers to services. The consumer can receive notification when new providers come online, and the provider can receive notification when a consumer acquires and releases a service instance. If this life-cycle control is important to your service and you forgo OSGi, you'll have to build this yourself; ServiceLoader doesn't go that far.
Alternately, rather than eager service lookup and use, you can take a more passive, declarative approach and let one of the OSGi dependency managers match your stated needs to the available service providers. There are many dependency managers to choose from. Spring Dynamic Modules is one of the most capable.
OSGi provides many other "middleware" facilities. I won't try to sell you on them here, as your question focuses mostly on what you'd be missing out on by choosing ServiceLoader.
As seh points out, if you're only interested in simple service discovery then ServiceLoader is a lightweight way to decouple consumers from providers. But it doesn't offer any assistance with composing services together.
For example, suppose service A needs to use service B. This is a "service dependency"... but what should A do if B is not available? In OSGi we can arrange that if B is not available then neither will A be -- assuming the dependency is mandatory; we can also support optional dependencies. On the other hand when using ServiceLoader, service A has no control over its availability so long as the JAR enclosing it is on the classpath... so it must provide its functionality even in the absence of required "back end" services.
Another thing to bear in mind with ServiceLoader is to try to abstract the lookup mechanism. The publish mechanism is quite nice and clean and declarative. But the lookup (via java.util.ServiceLoader) is as ugly as hell, implemented as a classpath scanner that breaks horribly if you put the code into any environment (such as OSGi or Java EE) that does not have global visibility. If your code gets tangled up with that then you'll have a hard time running it on OSGi later. Better to write an abstraction that you can replace when the time comes.
I have successfully managed to start Apache Felix from code and register an own Bundle.
Following relation between OSGI-projects is needed:
[OsgiInterface] -- provides interfaces.
[OsgiModuleA] -- (bundle) provides an implementation of those interfaces.
knows [OsgiInterface]
[OsgiUsage] -- makes use of one or more bundle.
knows [OsgiInterface] and [OsgiModuleA]
Now I have problems registering a service which implements an interface.
I would guess that my entries in manifest.mf files are wrong.
Additional information
It would be very kind, if someone could look at the code in my previous question
Let me refer to this question:
I tried to create a third project OsgiInterfaces, which provides an interface SomeInterface in the package interfaces. This project is known by both OsgiModuleA and OsgiUsage.
OsgiModuleA: manifest.mf has now an additional value interfaces for the entry Import-Package:. Furthermore, there is an instance of SomeInterface provided to the activator.
When the bundle is started, an NoClassDefFoundError occurs: the interface SomeInterface is not known.
EDIT:
Now, that the error is fixed, I can tell, that the most important part was:
map.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA,
"my.interfaces; version=1.0.0");
Without this, I got ClassCastException.
In the most basic form, services are registered in Java code, not using manifest or any other file. This usually happens in your BundleActivator.
Long i = new Long(20); // the service implementation
Hashtable props = new Hashtable();
props.put("description", "This an long value");
bundleContext.registerService(Long.class.getName(), i, props);
I suggest you read a tutorial, like the one at Knopflerfish
An alternative is using Declarative Services, or the new Blueprint facility. Using either of these (or other non-standardized systems) you will declare your services in a (usually XML) file, instead of writing code to interact with the services registry.
But you should probably figure out the fundamentals manually first.
[OsgiUsage] -- makes use of one or more bundle.
knows [OsgiInterface] and [OsgiModuleA]
It should not be necessary for the bundle that uses a service to know about the bundle that provides it. Both of them just need to know the service interface. In fact, bundles should not need to know about other bundles at all. They only need to import packages, and consume or provide services.
I understand that you have SomeInterface in another bundle, right? Then you must also export that package in that bundle's manifest, eg.
Export-Bundle: interfaces
But you really should have a look at the bnd tool mentioned in another answer. This generates standard OSGi manifests.
I suggest you look at the iPOJO project. This make using Felix much easier.
https://felix.apache.org/documentation/subprojects/apache-felix-ipojo.html
I would say use bnd directly or maven-bundle-plugin to create OSGI enabled jars.
It's easier than writing the OSGI manifest yourself(typos, mistakes, missing imports/exports)
Trying wrapping the jars with bnd as a start.