No more need in core Vaadin to explicitly call VaadinResourceServiceImpl nor any dependencies to OSGi in the core Vaadin bundles. If you want Vaadin to be OSGi compatible all you will have to do is to add an additional bundle to your runtime.
UIs will be Declarative Services that can have their own references to other OSGi components/services. The lifecycle of UIs is managed so that all dependencies are resolved before init() is called.
New themes/widgetsets/resources can be made available by adding just one line to the manifest (currently a call to a static method of VaadinResourceServiceImpl is required and this only works if the bundles are started in the right order
Is this an enhancement that you would like to see in the framework? Or do you have any plans on your own regarding enhancing OSGi support in Vaadin that I’m not aware of?
If this is an enhancement you’d like to see I would prepare a pull request for this and rewrite my solution in Java (currently written in Xtend).
I’ve also created an issue in GitHub so that I can reference it if the enhancements are accepted. (https://github.com/vaadin/framework/issues/10616)
Your solution helped me a lot to understand Vaadin OSGi for resources, themes and widgetset. So I decided to use it in a Liferay DXP (i.e… Equinox enviornment), everything worked ok but I had a problem: bunle initialization.
When I shit down LiferayDXP and start again a OSGi runtime does not contain HttpService! exception is thrown. This is because the HTTPService is not up. So I had to start de bundle manually and averything is ok again.
do you have more information on the exception that is thrown? Or any Log information that might help to understand your problem? Right now it sounds as if the http service is doing something wrong that somehow leads to an exception during
its initialization, which again would lead to it not being started properly.
Here is the log information when I start Liferay DXP:
13:52:31,992 ERROR [Framework Event Dispatcher: Equinox Container: 701c952f-fe5c-0018-1f50-d9146102d4cb]
[lskit-osgi-vaadin-components:97]
FrameworkEvent ERROR
java.lang.IllegalStateException: OSGi runtime does not contain HttpService!
at com.legosoft.vaadin.widgetset.OSGiVaadinTracker.addingBundle(OSGiVaadinTracker.java:54)
at com.legosoft.vaadin.widgetset.OSGiVaadinTracker.addingBundle(OSGiVaadinTracker.java:1)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:469)
at org.osgi.util.tracker.BundleTracker$Tracked.customizerAdding(BundleTracker.java:1)
at org.osgi.util.tracker.AbstractTracked.trackAdding(AbstractTracked.java:256)
at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:229)
at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444)
at org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:905)…
…
As I understand this is because the HttpService is not instanciated yet. This is part of my code for the Activator:
@Override
public Bundle addingBundle(Bundle bundle, BundleEvent event) {
String resourcePath = bundle.getHeaders().get(header);
if (resourcePath != null) {
VaadinResourceService service = null;
try {
service = OsgiVaadinResources.getService();
} catch (ResourceBundleInactiveException e) {
e.printStackTrace();
return bundle;
}
ServiceReference httpRef = context.getServiceReference(HttpService.class.getName());
if (httpRef == null)
throw new IllegalStateException("OSGi runtime does not contain HttpService!");
// ^ Here is where the exception is thrown.
.....
Ricardo
First: I stored the resources (widgetset, themes, images and JS libraries) defined in the MANIFEST file at the bundle activation time (NOT published the resources) following our code.
Second: I create a ServiceTracker for the HttpService class. When the services is added I publish the resources with the HttpService instance.
This solution works if I start and stop a bundle manually and also works is I shutdown and start Liferary DXP.
note: With this solution I don´t need the VAADIN path since it comes from the HttpsService so no Vaadin version dependency is needed.
sorry for the late response, but I see you got a working solution anyway
Meanwhile I always try to implement such things as Declarative Services, as they take away the OSGi complexity. So a possible solution I could imagine would be:
This way you don’t have to deal with the HttpService service yourself but let OSGi do the hard work.
BTW: If you too want Vaadin to support OSGi out of the box in the future (Vaadin 10) then you could add yourself to this issue https://github.com/vaadin/flow/issues/455
Your solution is simpler than declaring a ServiceTracker. Have yout test it?
Our experience of the @Reference annotation in Liferay DXP has not been always a good one. Specially when are not mandatory and many service need to be tracked List. Sometimes it nevers initialized the service (because bundle order initialization). This happened when we implemented a Vaadin component for a BPM (jBPM version 6.4) user tasks. But again, it is a simpler and cleaner solution than mine. Thanks for your help.
Of course that we are very interested using Vaadin 10 in an OSGi environment. For our customers this is the right path to follow. Thanks for the invitation.
I’m glad that I could help. I didn’t test specifically this piece of code, but I used this pattern more often recently, as it provides me with a simple solution to couple non-OSGi code to the lifecycle of OSGi components. You still have to take care of concurrency issues yourself, but those are not so difficult.
I’m not sure what SCR implementation Liferay DXP uses, but if it relies on Equinox then I think the newest version uses the Apache Felix SCR. I never had troubles with this one if I planned my component dependencies accordingly. Anyway, for this case it is just a static/mandatory reference to the HttpService, so this should not cause any trouble in Liferay DXP either.