This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 166680 - META-INF should be seen as a package name in the bundle manifest
Summary: META-INF should be seen as a package name in the bundle manifest
Status: RESOLVED FIXED
Alias: None
Product: PDE
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.3   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.3 RC1   Edit
Assignee: Brian Bauman CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 157810 170409 187600 (view as bug list)
Depends on:
Blocks:
 
Reported: 2006-12-04 15:26 EST by Olivier Thomann CLA
Modified: 2021-08-15 11:36 EDT (History)
14 users (show)

See Also:


Attachments
patch (1.18 KB, patch)
2007-05-07 14:48 EDT, Brian Bauman CLA
wassim.melhem: review+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Olivier Thomann CLA 2006-12-04 15:26:19 EST
In order to provide jsr199 support, I need to define a service which provides our implementation of the jsr199 as a possible java compiler.
In order to do that I define a file called javax.tool.JavaCompiler inside the META-INF/services folder. This folder is located in a source folder in order to be copied to the output folder.
Inside the package explorer META-INF/services is seen as a non-java resources.
In order to make it visible to other plugins (like my test plugin), I need to add it as part of the Export-Package section of the bundle manifest.
Export-Package: org.eclipse.jdt.compiler.tool,
 META-INF.services

On the line that contains it, I get an error saying that "Package 'META-INF.services' does not exist in this plug-in". Since I need this line, I'd like it to be error-free.

To reproduce the problem, check out the project org.eclipse.jdt.compiler.tool from dev.eclipse.org.
Comment 1 Wassim Melhem CLA 2006-12-04 15:34:12 EST
Brian, please take a look
Comment 2 Olivier Thomann CLA 2006-12-05 13:50:29 EST
Just to clarify.
META-INF is not a valid package name according to the JLS since '-' is not a valid java identifier part.
The problem in this case is that the entry inside the Export-Package section is a requirement from OSGI to "export" the services (in the java sense).
The services are located in a services folder inside the META-INF folder.
So if I want the plugin to export its services when used as a bundle, I need to have this entry in the Export-Package section. From an OSGI point of view, this is not an error even if PDE reports it as is.
PDE seems to validate all entries of the Export-Package section using the JLS meaning. This is not a requirement for OSGI.
There is no way from my end to fix this issue since the services has to be located inside the META-INF folder in order to be found by the call:
java.util.ServiceLoader.load(<Class name>);
See the java.util.ServiceLoader class in the JDK 6 javadoc.
Comment 3 Jeff McAffer CLA 2006-12-06 21:32:58 EST
I'm not following this.  If you export this "package" then someone must be either requiring the containing bundle or importing the package.  Which is it?  Which classloader is used when doing java.util.ServiceLoader.load(<Class name>)?

One of the challenges here is that exporting such packages will form a massive split package in the general case.  Worse, the package cannot be versioned effectively.  So it is not clear that you will get deterministic behaviour at all.  

While I am not disputing the PDE issue, it seems that there may be something more fundamental at play here.
Comment 4 Wassim Melhem CLA 2006-12-06 23:09:44 EST
adding Tom to the party.
Comment 5 Thomas Watson CLA 2006-12-07 09:14:06 EST
We need Jeff's questions answered from comment 3.  In particular we need to know what classloader is used to find the META-INF/services/... resource.  If this is the bundle classloader that contains the META-INF/services/... resource then there is no need to export it because the classloader will find the resource in its own bundle.
Comment 6 Pascal Rapicault CLA 2006-12-07 09:34:48 EST
ServiceLoader is the extension mechanism for java. When a service is being looked up, the serviceloader either use a specified classloader (ServiceLoader.load(Class, ClassLoader)) or uses the famous context classloader. 

In either case I can't see how the mechanism can work without exporting meta-inf/services since at one point ServiceLoader do a getResources on the classloader.
Comment 7 Pascal Rapicault CLA 2006-12-07 09:35:08 EST
Here is the doc of ServiceLoader: http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html
Comment 8 Jeff McAffer CLA 2006-12-07 09:49:01 EST
the classloader used bears on how the dependencies should/can be set up.  It would also be interesting to know how this service mechanism works in more detail.  That is, what class is looked up?  How does the referer know what service to name?  For example, in the OSGi service mechanism you look up by the interface but get an instance of some other class.  If the Java services mechanism is just a lookup then you know what interface/class you are looking for.  If you had to instantiate it as well then the dependencies get more complex.
Comment 9 Pascal Rapicault CLA 2006-12-07 14:55:02 EST
Similarly to osgi services, the java serviceloader takes the name of the class for which you want a service. In the present case, we want an instance of the JavaCompiler service, so the actual call being made is: 
   ServiceLoader.load(javax.tool.JavaCompiler) 
This method returns an iterator on all the services available.

Because the convention to register new service implementations is to create a file called <serviceClassName> located in the Meta-INF/services folder, the service loader will use the classloader being passed down (I will refer to it as SL-CL) (the classloader can either be an actual classloader, the system classloader when null is set, or the CCL is nothing is passed down (like in the previous call)) and do a call to getResources. In this case it does getResources("Meta-inf/services/javax.tools.JavaCompiler") on the CCL.

The <serviceClassName> file contains the fully qualified name of the classes implementing the service interface.

As the client code iterates over the iteration returned from the call, the implementation classes will be loaded from the SL-CL.

Here a few problems that I can think of:
- if a client bundle of serviceLoader imports meta-inf.service, then it will be able to see service declaration files whose type won't be loadable unless the proper classloader is passed down. Example:
   A registers a new service and exports meta-inf/services
   B import meta-inf/services but does *not* depend on A
   B's call to serviceloader will cause A service declaration file to be found but the loading of it will fail since B classloder (to whom the context finder delegates) does not see the service impl class.
To solve that problem, a "God" classloader that can see all the classes would have to be passed while doing the serviceloader lookup.

- if a client bundle requires a bundle that exports meta-inf.services, only the services defined in a prereq'ed bundle will be accessible.

- if the service loader object is being passed outside the bundle who instantiated it, then the context classloder will be different since our context classloader is the finder which computes the value dynamically.

- serviceloaders would have to be hooked in bundle lifecycles to ensure dynamic awareness.
Comment 10 Jeff McAffer CLA 2006-12-07 16:25:41 EST
exactly.  So the summary is, this is not going to work correctly/reliably even if you could export the META-INF/services package.  This sounds like a fine topic for discussion in the OSGi CPEG community.  Is there anything that PDE could/should do in the mean time?
Comment 11 Aleksander Bandelj CLA 2006-12-12 07:27:53 EST
I'm using Provide-Package: META-INF.services with buddy classloading in latest Eclipse. Package is exported, service is discovered. But it shouldn't work, since Bundle-ManifestVersion: 2 disallows Provide-Package. Is this an accidental feature ? ;)
Comment 12 Thomas Watson CLA 2006-12-12 08:26:51 EST
At runtime the Provide-Package is simply converted to an Export-Package statement for backwards compatibility.  Strictly speaking we could ignore this header if Bundle-ManifestVersion > 1 but it does not violate the specification to recognize headers that are not defined by the specification.  At a minimum I would expect PDE to flag these as deprecated if Bundle-ManifestVersion > 1
Comment 13 Chris Aniszczyk CLA 2007-01-02 17:03:51 EST
The provide-package issue will be tracked here: 
https://bugs.eclipse.org/bugs/show_bug.cgi?id=169373
Comment 14 Brian Bauman CLA 2007-01-15 12:58:51 EST
*** Bug 170409 has been marked as a duplicate of this bug. ***
Comment 15 David Williams CLA 2007-01-15 14:36:43 EST
(In reply to comment #14)
> *** Bug 170409 has been marked as a duplicate of this bug. ***
> 

Just wanted to summarize from the dup'd bug, that we encounter this in some xerces bundles. We had META-INF.services on the exported packages list, removed it since PDE said it was an error, but then found problems in some runtime situations (for example, running our code on some 1.4 JRE's did not find the more recent xerces libraries as they do, with META-INF.services included. For us, this was a pretty hard bug to find and track down and is evidence that I was beginning to blindly trust those PDE warnings :) 

Comment 16 Ed Merks CLA 2007-05-07 11:40:58 EDT
Given that this problem shows up in bundles from orbit, such as the batik ones, I sure hope this problem gets fixed for 3.3 because I too wasted much time on these problems that aren't problems.  What's the outlook for getting this fixed (i.e., getting the PDE not to mark this as an error)?
Comment 17 Wassim Melhem CLA 2007-05-07 14:01:10 EDT
Brian, can we please make them go away?  

I suspect the problem here is that we explicitly look for legitimate package fragments.  We should let in regular folders too. 
Comment 18 Brian Bauman CLA 2007-05-07 14:48:19 EDT
Created attachment 66184 [details]
patch

Wassim, this is the one line fix you mentioned earlier.  Can you verify this is ok to release?
Comment 19 Brian Bauman CLA 2007-05-07 14:50:24 EDT
*** Bug 157810 has been marked as a duplicate of this bug. ***
Comment 20 Wassim Melhem CLA 2007-05-07 17:26:02 EDT
Comment on attachment 66184 [details]
patch

Looks good, Bauman :)
Comment 21 Brian Bauman CLA 2007-05-07 17:29:50 EDT
Sorry for not getting to this earlier.  Should no longer be a problem after RC1
Comment 22 Christian Damus CLA 2007-05-17 13:11:42 EDT
*** Bug 187600 has been marked as a duplicate of this bug. ***