Skip to content
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

Add IContextFunction.ServiceContextKey OSGi component property type #1577

Conversation

HannesWell
Copy link
Member

This annotation simplifies the specification of the 'service.context.key' service property for IContextFunction implementations and makes it type-safe and more robust:

@Component(service = IContextFunction.class)
@IContextFunction.ServiceContextKey(IProgressService.class)
public class ProgressServiceCreationFunction extends ContextFunction {
...

Copy link
Contributor

github-actions bot commented Oct 1, 2024

Test Results

 1 758 files  ±0   1 758 suites  ±0   1h 29m 23s ⏱️ - 3m 54s
 4 170 tests ±0   4 148 ✅ ±0   22 💤 ±0  0 ❌ ±0 
13 107 runs  ±0  12 943 ✅ ±0  164 💤 ±0  0 ❌ ±0 

Results for commit 12af7b7. ± Comparison against base commit 7fa51b7.

♻️ This comment has been updated with latest results.

*/
@ComponentPropertyType
@Retention(RetentionPolicy.SOURCE)
@interface ServiceContextKey {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to not make it a top level class?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nesting it makes it more obvious that ServiceContextKey is only relevant for an implementation of the surrounding interface, in this case IContextFunction. It indicates the context better, instead to when it is a top-level class. Then one can think more easy that it's independently useful.
The SERVICE_CONTEXT_KEY string constant is defined here as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is rather unusual, I never seen this in any other (e.g. OSGi) defined property types, so I would suggest to make it a top-level class.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't be the first one:

image

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is rather unusual, I never seen this in any other (e.g. OSGi) defined property types, so I would suggest to make it a top-level class.

I haven't seen it often too, but in case we all agree that it's a good idea, why not do it differently? :)
What do you think is the advantage of having it as a top-level class?
From my POV having it nested has the advantage that the context is more clear.

It wouldn't be the first one:

It might be that I got the idea from that a while ago already (and forgot the source).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wouldn't be the first one:

Eclipse Testing framework is probably not the beste example...

So why not take as an example the other already existing property type in platform?

Or even how OSGi itself does it (spoiler it is using dedicated types).

For me "inner interfaces" have really no added value at all (beside they safe a javafile) except one plant to have multiple ones with the same name (what makes no sense in property types), e.g. if one has an Interface + a Builder interface or like java do with Entry and want to have multiple ones in the same package.

But for me this more leads to confusion due to the name clashes (I use one framework that makes use of it and its just horrible) even the java case is annoying (e.g. JDT suggest mes always the "wrong" first and I have to carefully inspect what really to import).

I also don't think it really makes things more "clear" ist just harder to discover as it is hidden inside the rest of the source code. Most of the time where I used such construct I later refactor it to being a top-level interface for several reasons.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even how OSGi itself does it (spoiler it is using dedicated types).

In OSGi all ComponentPropertyType implementations are placed in a dedicated propertytypes because there are many of them for each topic:
https://github.com/search?q=repo%3Aosgi%2Fosgi+import+org.osgi.service.component.annotations.ComponentPropertyType&type=code

But as far as I can see it, no property-type is colocated in the same package to the targeted service interface.
However, for one type I don't think it makes sense to add a new package.

So why not take as an example the other already existing property type in platform?

That's the only existing property-type annotation I found in the equinox, eclipse-platform, JDT and PDE organization and you added it that way in

I know I also reviewed that PR back than and didn't suggest the same, but my point is, that with one occurrence I wouldn't say it a well established style that is used commonly and very often all over Eclipse. To me this seems to be more an open field and if this is submitted as it is we have a 50:50 split. So maybe this could be considered as an experiment to see what works better on the long run?

But for me this more leads to confusion due to the name clashes (I use one framework that makes use of it and its just horrible) even the java case is annoying (e.g. JDT suggest mes always the "wrong" first and I have to carefully inspect what really to import).

But for the this inner interface we have no name clash and if it would clash with another class you always have to check what is exactly imported, because you cannot be sure it's the right one, just because it's a top-level class?
I even did some small experiment to check how JDT proposes the annotations as a top-level and nested annotation-interface and there seems to be no difference:
grafik

I also don't think it really makes things more "clear" ist just harder to discover as it is hidden inside the rest of the source code.

This could happen in same cases but also the opposite could happen: One looks into the interface and then sees this property-type. And without that wouldn't have discovered it that person doesn't scan the entire package. Of course it could also be documented accordingly, but summed up we would probably have more documentation to mention the property-type in the service and reference back to the service in the property-type. With a nested annotation/interface it would be (at least partly) be implied by the 'context'.

But I think we are starting to turn in circles and each one of us has a clear but unfortunately opposite opinion on that. Still I think neither one is wrong, both are valid approach, it's just the question which style is better.

So I would like to ask others what their opinion is and what they think is overall better?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very biased. I do a lot of nesting to keep the concepts that used together close together:

image

@HannesWell HannesWell force-pushed the add-IContextFunction-ServiceContextKey-componentPropertyType branch from c4cf1be to ec03a19 Compare October 4, 2024 13:30
@HannesWell HannesWell force-pushed the add-IContextFunction-ServiceContextKey-componentPropertyType branch from ec03a19 to e423bf1 Compare October 11, 2024 21:39
@HannesWell
Copy link
Member Author

@laeubi can you tell why this build has compilation errors and how to fix them?

The existing AdapterTypes, that is the other ComponentPropertyType in the SDK, also seems to compile without any special setup:
https://github.com/eclipse-equinox/equinox/blob/19b406bea5b340cee4009cd9f2c358f23b3840da/bundles/org.eclipse.equinox.common/src/org/eclipse/core/runtime/AdapterTypes.java#L44

@laeubi
Copy link
Contributor

laeubi commented Oct 12, 2024

The existing AdapterTypes, that is the other ComponentPropertyType in the SDK, also seems to compile without any special setup:

Maybe because it is a top-level class 😛

Beside from that I would assume that enable DS Annotations for the project could solve the issue.

@HannesWell
Copy link
Member Author

HannesWell commented Oct 12, 2024

The existing AdapterTypes, that is the other ComponentPropertyType in the SDK, also seems to compile without any special setup:

Maybe because it is a top-level class 😛

I expected that answer :P And therefore checked
Tycho's DeclarativeServicesClasspathContributor, where I didn't see any sign that the class is scanned at all.
Furthermore I assumed that one first has to compile the class to be able to scan it for annotations, unless one operates only on the AST.

Beside from that I would assume that enable DS Annotations for the project could solve the issue.

I thought about this as well, but at least in org.eclipse.equinox.common I didn't find any sign of such configuration, neither in the project files nor in a parent pom. And actually the project does not contain an DS components, it just needs the classpath contribution.

@laeubi
Copy link
Contributor

laeubi commented Oct 12, 2024

I thought about this as well, but at least in org.eclipse.equinox.common I didn't find any sign of such configuration, neither in the project files nor in a parent pom. And actually the project does not contain an DS components, it just needs the classpath contribution.

It might pull it in by a transitive dependency (that uses DS annotations), and because DeclarativeServicesClasspathContributor actually looks for such configuration at the moment.

@HannesWell HannesWell force-pushed the add-IContextFunction-ServiceContextKey-componentPropertyType branch from e423bf1 to 3d63042 Compare October 12, 2024 13:04
@HannesWell
Copy link
Member Author

HannesWell commented Oct 12, 2024

I thought about this as well, but at least in org.eclipse.equinox.common I didn't find any sign of such configuration, neither in the project files nor in a parent pom. And actually the project does not contain an DS components, it just needs the classpath contribution.

It might pull it in by a transitive dependency (that uses DS annotations), and because DeclarativeServicesClasspathContributor actually looks for such configuration at the moment.

I still have not found out why it works in o.e.equinox.common, but adding the pde.ds preference file indeed fixes the build failure. 🎉 Thanks for the hints.

Therefore this is now ready for submission.
Since we have a 2:1 result pro inner-class in above's discussion I plan to submit this as it is this evening unless somebody has strong new arguments.
We can the finally complete eclipse-platform/eclipse.platform.ui#2344.

@HannesWell HannesWell force-pushed the add-IContextFunction-ServiceContextKey-componentPropertyType branch from 3d63042 to edad7ba Compare October 12, 2024 14:56
This annotation simplifies the specification of the
'service.context.key' service property for IContextFunction
implementations and makes it type-safe and more robust:
'''
@component(service = IContextFunction.class)
@IContextFunction.ServiceContextKey(IProgressService.class)
public class ProgressServiceCreationFunction extends ContextFunction {
'''
@HannesWell HannesWell force-pushed the add-IContextFunction-ServiceContextKey-componentPropertyType branch from edad7ba to 12af7b7 Compare October 12, 2024 16:27
@HannesWell HannesWell merged commit e14565e into eclipse-platform:master Oct 12, 2024
17 checks passed
@HannesWell HannesWell deleted the add-IContextFunction-ServiceContextKey-componentPropertyType branch October 12, 2024 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants