Problems with manifest files in 4.0.0-rc2 regarding OSGi

(1) Replace the component-xml by those found in the diff. The namespace is important for SCR.
done

(2) There cannot be two methods which the same name, but which an input output structure not corresponding to the SCR spec. Therefore, I had to introduce the class MultiException to get rid of the return type List and remove the initialize(ClassLoader) method.
I don’t understand “There cannot be two methods with the same name”. But from OSGi 5.0 CMPN 112.5.8 I see that the ‘List’ return type is not valid for the activate method. My fix was simply creating a new ‘activate’ method with ‘void’ as return type. And since this method is also named ‘activate’, we can omit the attribute in the component XML configuration.

A blocker is now, that the correct classloader must be forwarded to SmackConfiguration.
My solution is to use ‘this.getClass().getClassLoader()’ in the activate method. Since ‘this’ is a class out of the components bundle, e.g. o.j.s.initializer.experimental.ExperimentalInitialzier, I would expect this class loader to be able to see and load the required files and classes. Or am I wrong? If so, what is the correct classloader? And how to obtain it?

Have a look at my current OSGi work at https://github.com/Flowdalic/Smack/tree/osgi

A blocker is now, that the correct classloader must be forwarded to SmackConfiguration. From my point of view, we have only two options to solve this issue:

(1) Create a separate class that performs the config file parsing which can be instantiated with a classloader used for class loading.

After reading this section again: Are you talking about the config file parsing that is done by smack-core? Does smack-cores initialization by processing of org.jivesoftware.smack/smack-config.xml fail in OSGi? If so, this should be easily fixable by also adding a Declarative Service for smack-core.

I checked your changes… The introduction of an activate method should work. The classloaders are the correct ones. I will test your changes tomorrow in order to validate that everything works.

Well, let’s code speak :wink:

UrlInitializer (line: 83)

SmackConfiguration.processConfigFile(is, exceptions);

The classloader is able to get an InputStream and the method call of “processConfigFile” ends finally in the method “loadSmackClass”, where the class is loaded “initClass = Class.forName(className);”. Here, the call is processed from the core bundle classloader which fails. We need at this point the classloader from e.g. the extension bundle.

Here, the call is processed from the core bundle classloader which fails.

The core bundle should be able to load it’s classes, which are the defined as startupClasses in smack-config.xml. All other classes are defined as optionalStartupClasses, of which most are not from the core bundle and therefore should fail when the core bundle tries to load them. But in the OSGi world that job is done by the Declarative Service we just created.

So I see no problem here. Or am I missing something?

Sorry, I didn’t get it… DS calls the activate method of e.g, “ExtensionsInitializer” and this call leads to “getConfigUrl” where ExtensionsInitializer returns “classpath:org.jivesoftware.smackx/extensions.xml”. The inputstream is obtained and then leads to the call “SmackConfiguration.processConfigFile(is, exceptions);”. Here, the classloader is lost… “extensions.xml” contains e.g. “org.jivesoftware.smackx.disco.ServiceDiscoveryManager”. This class can and will never be loaded because where are in the core scope.

Ahh now I got you. https://github.com/Flowdalic/Smack/commit/42eb408e124a45bde7a0fcf75821b4f8a2d652 2f should take care of that.

I think, we have got it, but please fix the component files (see my diff):

(1) src -> scr (xml namespace prefix)

(2) activate=“activate” (declare the activation method)

We should also provide a “deactivate”-method that removes the Provider from the ProviderManager.
02.diff.zip (599 Bytes)

(2) activate=“activate” (declare the activation method)
Is this required? From the spec it appeared that ‘activate’ is the default value for the activtate attribute? I would like to pefer “convention over configuration” and therefore avoid stating this if we use the default value.

We should also provide a “deactivate”-method that removes the Provider from the ProviderManager.
I thought about this too. What happens atm if you unload/deactivate a Smack API extension bundle (experimental, extensions, legacy)? Does the deactivation fail/hang, e.g. because the ProviderManager still holds references to classes from the bundle?

Yes, you are right, you can omit the “active” declaration.

I thought about this too. What happens atm if you unload/deactivate a Smack API extension bundle (experimental, extensions, legacy)? Does the deactivation fail/hang, e.g. because the ProviderManager still holds references to classes from the bundle?

That’s a Java problem, you cannot destroy a reference that is hold by another object, that’s why OSGi recommends interaction via services, but (like in our case) the creation of a technology independent solution often requires an interaction on object level. If we uninstall an extension, everything will still work, because the provider instances registered in the ProviderManager still exist. If we install the bundle again, the active methods registers new instances. In the deactivate method we must do all the cleanup necessary to create a state as if the bundle was never installed. The main task is to remove the registered instances hold by the ProviderManager. All other instances created must be notified to shutdown.

If we install the bundle again, the active methods registers new instances. In the deactivate method we must do all the cleanup necessary to create a state as if the bundle was never installed.
I wonder if this is really required. If a new version from e.g smack-extension is installed, then the old provider instance is overwritten with the new one.

All other instances created must be notified to shutdown.
Provider instances? What should they do if they are notified about their bundle being shut down?

II’d like to defer any further related code changes after the 4.0 release. Do you consider the missing deactivation method a blocker? Does Smack work reasonably well in an OSGi environment as of 13b522?

Do you consider the missing deactivation method a blocker?

No. The shutdown of the extension, experimental and legagcy bundle should not be part of a proper use case.

Does Smack work reasonably well in an OSGi environment as of 13b522?

I will check that tomorrow (not so much time) or on Thursday and will give you feedback here.

I will check that tomorrow (not so much time) or on Thursday and will give you feedback here.
That would be great, as I’m planing to release 4.0.0-rc2 after your OK.

At a first glance:

  • smack-experimental-components.xml: “org.jivesoftware.smack.initializer.experimental.ExtensionsInitializer” -> “org.jivesoftware.smack.initializer.experimental.ExperimentalInitializer”

Awaiting your fix and will check again.

Fixed with https://github.com/Flowdalic/Smack/commit/9a32f7b00c4b604aa4592082d40057ad4359cb fe

The current state of the components works so far under OSGi, but I have to admit that I was not able to conduct an extensive test. From my side: I am awaiting the new rc2-release

Thank you very much for your commitment. Interesting when we think, that the stumbling block was a malformed Bundle-Version.

Alright then. I’ve squash merged the OSGi commits in master and pushed the new master to the offical repo. Will later wrap up 4.0.0-rc2

Thanks for you effort

@Jens I’ve created SMACK-576 about making smack-resolver-javax an OSGi ServiceComponent.

I wonder why I didn’t think about it when we made smack-experimental, smack-extensions and smack-legacy an ServiceComponent. As of Smack 4.0.0 OSGi users would need to manually install smack-resolver-javax. This shouldn’t be the case any more with Smack 4.0.1-SNAPSHOT. Could you verify this? Thank you.

Unfortunately, there is is small mistake in the manifest file of smack-resolver-javax:

Solution 1:

Service-Component: org.jivesoftware.smackx/smack-resolver-javax-components.xml

->

Service-Component: org.jivesoftware.smack/smack-resolver-javax-components.xml

Solution 2 (recommended):

Rename the resource path from org.jivesoftware.smack to org.jivesoftware.smackx

Thanks Jens, fixed in 4.0.2-SNAPSHOT

(3) Versioning#2:

“smack-resolver-javax” and “smack-resolver-dnsjava” import the package “org.jivesoftware.smack.util” without any version. It works, but it should be avoided.

Logged as SMACK-587