-
-
Notifications
You must be signed in to change notification settings - Fork 305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Parses META-INF/services files for annotations #5912
Conversation
It is possible to add addnotions in the comments of the service files of the Service Loader. Fixes bndtools#5903 --- Signed-off-by: Peter Kriens <Peter.Kriens@aQute.biz> Signed-off-by: Peter Kriens <Peter.Kriens@aQute.biz>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you a lot for working on this.
Adding the annotation comments to the services file is a clever idea to still have control about which services are processed and to handle the non default cases.
Just for clarification, in the simplest case I could to something like
META-INF/services/com.example.ServiceType:
#import aQute.bnd.annotation.spi.ServiceProvider
#@ServiceProvider
com.example.impl.Impl2
#@ServiceProvider
com.example.impl.Impl1
or
META-INF/services/com.example.ServiceType:
#@aQute.bnd.annotation.spi.ServiceProvider.ServiceProvider
com.example.impl.Impl2
#@aQute.bnd.annotation.spi.ServiceProvider.ServiceProvider
com.example.impl.Impl1
and would have Impl1 and Impl2 registered?
And if I would do
META-INF/services/com.example.ServiceType:
#@aQute.bnd.annotation.spi.ServiceProvider.ServiceProvider
com.example.impl.Impl2
com.example.impl.Impl1
... I only would have Impl2 registered respectively if the annotation were only above Impl1 only Impl1 would be registered?
static final Pattern IMPORT_P = Pattern | ||
.compile("#import\\s+(?<fqn>" + FQN_S + ")\\s*;?\\s*$"); | ||
static final Pattern ANNOTATION_P = Pattern | ||
.compile("#@(?<fqn>" + FQN_S + ")\\((?<attrs>.*)" + "\\)\\s*;?\\s*$"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make the braces optional if no attributes are specified for an annotation?
And naming the capturing group type
or just name
would avoid possible confusion with the IMPORT_P
Pattern.
.compile("#@(?<fqn>" + FQN_S + ")\\((?<attrs>.*)" + "\\)\\s*;?\\s*$"); | |
.compile("#@(?<type>" + FQN_S + ")(\\((?<attrs>.*))?" + "\\)\\s*;?\\s*$"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am ok with this, but if you change 'fqn', don't you then also not have to change the code where we get the group?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, of course the code below has to be adjusted.
In fact I mainly noticed this when reading the code below where it was first read like it would look up a fully-qualified name in the imports (which is of course not necessary), when it actually just looked up the class-name.
I just wanted to keep the suggestion short. :)
/** | ||
* Get the comments that preceded this implementation definition | ||
*/ | ||
public Optional<String> getComments() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not yet, but it is important information for use. I always make my code handle a use case but try to stay away from the specifics. I compare it with drawing a rectangle around a messy curvy perimeter of requirements.
I find it very important that all code is refective so outsiders can use it in many different ways. Notice that this class has no clue about Service Provider
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. I just wanted to make sure it is not left-over from early development steps and ended up here accidentally.
I've played with the idea of automatically repeating the annotations but decided against it. I think it is confusing and it would require a new mechanism to stop the repetition. And this is a rather bad thing anyway. Using the Java annotation is so much cleverer. It gets you all the IDE help, it adds your type to the services file, and the compiler verifies, you can use constants, etc. It is pretty dumb to use this over the real annotations. The only reason I worked on this is because there are a lot of people out there that prefer to cut off their nose to spite their face :-( It would be nice if we had a good article somewhere to explain what the annotations do and how useful they are outside OSGi. After all, most open source programs actually use the bnd mvn plugin already. Why not use it to maintain your META-INF/services directory? |
The key advantage of using the annotations is that the the actual manifest code as orchestrated by the ServiceProvider and its Capability and Requirement annotations is used. You realize that you can make a custom application annotation in a similar way? |
That's right.
Fully agree, but I can only speculate about why other projects are reluctant to use them.
Absolutely. That would be great. I'm trying to contribute OSGi metadata to the libraries and projects I'm getting in touch (slowly but steadily) and therefore it would be great to have something to reference instead of explaining it again and again.
I didn't, but you are right. But can you tell a use-case where I would need that? I would need my own processor of these annotations to use it, wouldn't I? |
Actually there are a few approaches already, for example https://metainf-services.kohsuke.org/ and also some maven-plugin was to do it here and there. What mostly bugs people I think is that these are bnd specific and the don't (and don't want to) know about OSGi and all that stuff. So it might help to have these |
--- Signed-off-by: Peter Kriens <Peter.Kriens@aQute.biz> Signed-off-by: Peter Kriens <Peter.Kriens@aQute.biz>
I've added an article https://bnd.discourse.group/t/automate-meta-inf-services-chores/397 |
Thank you for this PR. :) |
Can you take a look at the article, suggest improvements if anything is missing? If you let me know if it is ok, I will send a post on X. |
this is an experiment based on an idea mentioned in bndtools#6304 it leverages the recent addition of PR bndtools#5912 that allowed to add annotations in comments of files in META-INF/services. But in this PR we basically pretent and add a aQute.bnd.annotation.spi.ServiceProvider annotation artificially. this causes bnd to generate Provide-Capability manifest headers for the services make sure biz.aQute.bndlib is on the buildpath which contains the 'aQute.bnd.annotation.spi.ServiceProvider' annotation Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
it leverages the recent addition of PR bndtools#5912 that allowed to add annotations in comments of files in META-INF/services. But in this PR we basically pretent and add a aQute.bnd.annotation.spi.ServiceProvider annotation artificially. this causes bnd to generate Provide-Capability manifest headers for the services Signed-off-by: Christoph Rueger <chrisrueger@gmail.com>
It is possible to add addnotions in the comments of the service files of the Service Loader.
Fixes #5903
Signed-off-by: Peter Kriens Peter.Kriens@aQute.biz