jakartaee / mail-api

Jakarta Mail Specification project
https://jakartaee.github.io/mail-api
Other
245 stars 101 forks source link

Use OSGi service loader mediator instead of osgi resource locator #630

Closed mnlipp closed 1 year ago

mnlipp commented 1 year ago

To separate the API and the implementation, the service loader pattern is used. This perfectly well suited mechanism is known to have problems in OSGi environments.

An attempt has been made in the jakarta mail api implementation to solve the problems with org.glassfish.hk2.osgi-resource-locator, which requires lots of special coding.

The "service loader and OSGi" problem has actually successfully been addressed before by http://docs.osgi.org/specification/osgi.enterprise/7.0.0/service.loader.html with the reference implementation (with an easier to read description) SPI Fly. What it boils down to is that instead of having to maintain the complicated code, you can simply use the service locator after adding some statements to MANIFEST.MF.

While this is not a runtime bug, because you can use Jakarta mail api in an OSGi environment (once you have found out that you need to include the hk2 jar and once https://github.com/eclipse-ee4j/mail/issues/629 will be fixed), I think it is a bug with respect to the design.

mnlipp commented 1 year ago

Having found the usage of hk2 to be implemented only partially, I have patched the MANIFEST.MF files of the jars as required for the use of the service loader mediator. I did it manually, as I don't know enough about maven. The required headers are:

In jakarta.mail-api:

Require-Capability: osgi.extender;filter:="(osgi.extender=osgi.servicelo
 ader.processor)";resolution:=optional,osgi.ee;filter:="(&(osgi.ee=JavaS
 E)(version=1.8))"

In angus-core (I know this is a different project/repository, but headers have to be added for providers of the service as well):

Provide-Capability: osgi.serviceloader;osgi.serviceloader="jakarta.mail.
 util.StreamProvider"
Require-Capability: osgi.extender;filter:="(osgi.extender=osgi.servicelo
 ader.registrar)",osgi.extender;filter:="(osgi.extender=osgi.serviceload
 er.processor)";resolution:=optional,osgi.ee;filter:="(&(osgi.ee=JavaSE)
 (version=1.8))"

And in imap (using this as an example):

Provide-Capability: osgi.serviceloader;osgi.serviceloader="jakarta.mail.
 Provider"
Require-Capability: osgi.extender;filter:="(osgi.extender=osgi.servicelo
 ader.registrar)",osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"

Note that adding these headers completely obsoletes the need for hk2.

jbescos commented 1 year ago

Ideally there should be a plugin to deal with the manifest.

You don't need an extra plugin. You can simply add this information using the Felix maven bundle plugin which is already in pom.xml with instructions <Provide-Capability> and <Require-Capability> (that's doing it "manually", see #630 (comment)). In general, the manual approach is considered a bit more difficult to maintain, but once it's there, it rarely changes (only if you add another loaded service).

If it helps, I can provide another PR with the pom.xml based solution.

In my opinion that new PR will be better. Also because there is a process to approve new dependencies (actually in APIs it is forbidden non-jakarta libs).